Compare commits

...
135 Commits
Author SHA1 Message Date
Akim Demaille 0535d2a608 version 3.6.3
* NEWS: Record release date.
2020-06-03 07:31:43 +02:00
Akim Demaille 52ce2a008b build: check -Wmissing-prototypes
pstate_clear is lacking a prototype.
Reported by Ryan
https://lists.gnu.org/r/bug-bison/2020-05/msg00101.html

Besides, none of the C examples were compiled with the warning flags.

* configure.ac (warn_c): Add -Wmissing-prototypes.
* data/skeletons/yacc.c (pstate_clear): Make it static.
* examples/local.mk (TEST_CFLAGS): New.
* examples/c/bistromathic/local.mk, examples/c/calc/local.mk,
* examples/c/lexcalc/local.mk, examples/c/mfcalc/local.mk,
* examples/c/pushcalc/local.mk, examples/c/reccalc/local.mk,
* examples/c/rpcalc/local.mk:
Use it.

GCC's warn_unused_result is not silenced by a cast to void, so we have
to "use" scanf's result.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25509
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425

Flex generated code produces too many warnings, including things such
as, with ICC:

    examples/c/lexcalc/scan.c(1088): error #1682: implicit conversion
              of a 64-bit integral type to a smaller integral type (potential portability problem)
    2259                YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
    2260                ^
    2261
    2262

I am tired of trying to fix Flex's output.  The project does not seem
maintained.  We ought to avoid it.  So, for the time being, don't try
to enable warnings with Flex.

* examples/c/bistromathic/parse.y, examples/c/reccalc/scan.l: Fix
warnings.
* doc/bison.texi: Discard scanf's return value to defeat
-Werror=unused-result.
2020-06-01 08:29:53 +02:00
Akim Demaille 12f4091de4 tests: show logs
* examples/c/bistromathic/bistromathic.test, examples/test: here.
2020-05-23 18:02:44 +02:00
Akim Demaille 8ece778cb8 c++: fix printing of state number on streams
Avoid this kind of display:

    LAC: checking lookahead identifier: R4 R3 G^B S5

* data/skeletons/lalr1.cc: Convert state_t to int before printing it.
2020-05-23 18:02:24 +02:00
Akim Demaille f80890c4bb fix generated comments
In Bison 3.6.2, the comments with brackets lose their brackets, for
improper m4 quotation.

* data/skeletons/bison.m4 (b4_gsub): New.
* data/skeletons/c-like.m4 (_b4_comment): Use it.
* tests/m4.at: Check b4_gsub.
2020-05-21 20:14:59 +02:00
Akim Demaille 1ebc2ac55c traces: provide a means to get short m4 traces
Let --trace=m4-early dump all the logs from the start (as --trace=m4
used to do), and have --trace=m4 now start traces only when actually
working of the user's grammar.

Can make a big difference in the case of small inputs.  E.g.

    $ bison -S tests/testsuite.dir/001/input.m4 tests/testsuite.dir/001/input.y --trace=m4 |& wc
       3952   19446  251068
    $ bison -S tests/testsuite.dir/001/input.m4 tests/testsuite.dir/001/input.y --trace=m4-early |& wc
      19491  131904 1830495

* data/skeletons/traceon.m4: New.
* src/getargs.h, src/getargs.c: Introduce --trace=m4-early.
* src/output.c (output_skeleton): Adjust for --trace=m4 and --trace=m4-early.
2020-05-21 20:13:04 +02:00
Akim Demaille 94952779b6 traces: show the full m4 invocation
Unfortunately the effect of -dV is still position independent.

* src/output.c (output_skeleton): here.
2020-05-21 20:13:04 +02:00
Akim Demaille 4d9fa28ba8 maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2020-05-17 08:55:47 +02:00
Akim Demaille a100a3c4c1 version 3.6.2
* NEWS: Record release date.
2020-05-17 08:30:46 +02:00
Akim Demaille b18ceb50f1 tests: improve update-test
* build-aux/update-test: When given a directory, use the testsuite.log
which it contains.
Do not accept empty "from"s, as substituting the empty string with
something is rarely a good idea.
2020-05-17 08:28:12 +02:00
Akim Demaille ff4d67ede8 CI: add GCC 10 and Clang 10
* .travis.yml: Here.
* tests/input.at, tests/regression.at: Beware of clang's -Wdocumentation.
2020-05-17 08:28:12 +02:00
Akim Demaille 465babb635 fix: do not emit nested comments
With input such as

    %token<fl> yVL_CLOCK "/*verilator sc_clock*/"

we generate

    yVL_CLOCK = 610,      /* "/*verilator sc_clock*/"  */

which is invalid since the comment will actually be closed on the
first "*/".  Let's turn "*/" into "*\/" to avoid this.  But GCC will
also warn about "/*" inside a comment, so let's "escape" it too.

Reported by Huang Rui.
https://github.com/akimd/bison/issues/38

* data/skeletons/c-like.m4 (_b4_comment): Escape comment delimiters in
comments.
* tests/input.at (Torturing the Scanner): Check thes cases.
* tests/m4.at: New.
2020-05-17 08:28:12 +02:00
Akim Demaille 6a28e6d412 todo: update 2020-05-15 07:18:15 +02:00
Akim Demaille f4495da337 examples: use markdown hyperlinks
* examples/c++/README.md, examples/c++/calc++/README.md,
* examples/c/README.md: here.
2020-05-14 07:26:55 +02:00
Akim Demaille dbaed0bbf2 tests: don't use == to compare const char *...
Reported by Dagobert Michelsen.
https://lists.gnu.org/r/bug-bison/2020-05/msg00091.html

* tests/c++.at: here.
2020-05-14 07:26:34 +02:00
Akim Demaille 78c7fb6460 gnulib: update 2020-05-14 07:25:09 +02:00
Akim Demaille da29809969 news: update 2020-05-10 17:32:28 +02:00
Akim Demaille 87e4895189 maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2020-05-10 14:47:51 +02:00
Akim Demaille 01e3f45f83 version 3.6.1
* NEWS: Record release date.
2020-05-10 14:28:24 +02:00
Akim Demaille 091943f265 c++: style: reorder generated code
The implementation of yy::parser::symbol_name is emitted even before
the implementation of yy::parser::parser.  This makes little sense.

* data/skeletons/lalr1.cc (symbol_name): Move its implementation in
the same place as in the class definition: after "error" and before
"context".
2020-05-10 10:06:11 +02:00
Akim Demaille bf98d94f4f c++: provide yy::parser::symbol_type::name
* data/skeletons/c++.m4 (yy::parser::basic_symbol::name): New.
* data/skeletons/lalr1.cc (yy_print_): Use it.
* doc/bison.texi: Document.
* tests/c++.at: Check.
2020-05-10 10:01:35 +02:00
Akim Demaille 6bb37dbe27 c++: make parser::symbol_name public
Reported by Martin Blais <[email protected]>.
https://lists.gnu.org/r/help-bison/2020-05/msg00005.html

* data/skeletons/lalr1.cc (symbol_name): Make it public.
Add a private hidden hook to enable testing of private parts.
* tests/local.at (AT_DATA_GRAMMAR_PROLOGUE): Help Emacs find the right
language mode.
* tests/c++.at (C++ Variant-based Symbols Unit Tests): Check that we
can read symbol_name.
2020-05-10 09:42:37 +02:00
Akim Demaille c3585f41ef examples: beware of ~/.inputrc
* examples/c/bistromathic/bistromathic.test: here.
2020-05-10 09:40:07 +02:00
Akim Demaille 6525abdc83 build: also provide lzip compressed tarballs
Suggested by Matias Fonzo <[email protected]>.

* cfg.mk: Post announcements to bison-announce.
* configure.ac: Build lzip packages.
* .travis.yml: Build only xz, we don't care about the other formats
here.
2020-05-10 08:03:49 +02:00
Akim Demaille 2b63c54f5a style: minor fixes
* examples/c/README.md: here.
2020-05-10 08:03:30 +02:00
Akim Demaille 2da399d15f yacc.c: restore ansi-c compatibility
Reported by neok-m4700.
https://github.com/akimd/bison/issues/37

* data/skeletons/yacc.c: Don't use // comments.
2020-05-09 17:05:03 +02:00
Akim Demaille 0c77d69721 maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2020-05-08 10:15:38 +02:00
Akim Demaille 307fcdee00 version 3.6
* NEWS: Record release date.
2020-05-08 09:57:14 +02:00
Akim Demaille d26d10ad6c examples: beware of portability issue on Windows
Reported by Jannick.
https://lists.gnu.org/r/bug-bison/2020-05/msg00040.html
https://lists.gnu.org/r/bug-bison/2020-05/msg00066.html

* examples/test (diff_opts): Use --strip-trailing-cr if supported, to
avoid \n vs. \r\n issues.
* examples/c/bistromathic/bistromathic.test: When on MSYS, don't try
to check autocompletion.
2020-05-08 09:45:29 +02:00
Akim Demaille 1b4108da3e regen 2020-05-08 09:45:29 +02:00
Akim Demaille 53bfc7df94 doc: fix the generation of the man page
When there is no bison.1 at all, the procedure fails.

* doc/local.mk (bison.1): Be robust to cold starts.
2020-05-08 09:02:45 +02:00
Akim Demaille a5fb4a88ef news: prepare for 3.6 2020-05-08 07:34:30 +02:00
Akim Demaille 54df196d49 doc: complete the table of symbols
* doc/bison.texi: Add YYEMPTY, YYEOF and YYUNDEF.
2020-05-08 07:34:30 +02:00
Akim Demaille 52bb6f0525 doc: clarify the glossary item about kinds
* doc/bison.texi (Glossary): here.
2020-05-07 08:38:58 +02:00
Akim Demaille 76dab18af3 maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2020-05-06 08:48:05 +02:00
Akim Demaille c982974f33 version 3.5.94
* NEWS: Record release date.
2020-05-06 08:28:36 +02:00
Akim Demaille dc2a3578b7 doc: document yypstate_expected_tokens
* doc/bison.texi (Push Parser Interface): Here.
2020-05-06 08:11:52 +02:00
Akim Demaille 9661b2fcbc doc: restructure the push parser documentation
I don't think it's fair to have yypstate_new, yypstate_delete,
yypush_parse and yypull_parse to have their own section, on par with
yyparse and yylex.  Let them be in a single section about push
parsers.  And show new/delete first.

* doc/bison.texi (Push Parser Interface): New.
Fuse the aforementioned sections into it.
2020-05-06 08:11:52 +02:00
Akim DemailleandAkim Demaille d9a9b054ae all: fix the interface of yyexpected_tokens
The user gives yyexpected_tokens a limit: the max number of tokens she
wants to hear about.  That's because an error message that reports a
bazillion of possible tokens is useless.

In that case yyexpected_tokens returned 0, so the user would not know
if there are too many expected tokens or none (yes, that's possible).

There are several ways to tell the user in which situation she's in:

- return some E2MANY, a negative value.  Then it makes the pattern

    int argsize = yypcontext_expected_tokens (ctx, arg, ARGS_MAX);
    if (argsize < 0)
      return argsize;

  no longer valid, as for E2MANY (i) the user must generate the error
  message anyway, and (ii) she should not return E2MANY

- return ARGS_MAX + 1.  Then it makes it dangerous for the user, as
  she has to iterate update `min (ARGS_MAX, argsize)`.

Returning 0 is definitely simpler and safer for the user, as it tells
her "this is not an error, just generate your message without a list
of expecting tokens".  So let's still return 0, but set arg[0] to the
empty token when the list is really empty.

* data/skeletons/glr.c, data/skeletons/lalr1.cc, data/skeletons/lalr1.java
* data/skeletons/yacc.c (yyexpected_tokens): Put the empty symbol
first if there are no possible tokens at all.
* examples/c/bistromathic/parse.y: Demonstrate how to use that.
2020-05-06 08:11:52 +02:00
Akim Demaille cb9f4cb543 examples: fix handling of syntax errors
The shell grammar does not allow empty statements in then/else part of
an if, but examples/test failed to catch the syntax errors from the
script it ran.  So exited with success anyway.

You would expect 'set -e' to suffice, but with bash 3.2 actually it
does not.  As a matter of fact, I could find a way to have this behave
properly:

    $ cat test.sh
    set -e
    cleanup ()
    {
      status=$?
      echo "cleanup: $status"
      exit $status
    }
    trap cleanup 0 1 2 13 15
    . $1
    s=$?
    echo "test.sh: $s"
    exit $s

    $ cat bistro.test
    if true; then
    fi

    $ /bin/sh ./test.sh ./bistro.test
    ./bistro.test: line 2: syntax error near unexpected token `fi'
    cleanup: 0
    $ echo $?
    0

Remove the set -e (or the trap), and tada, it works...  So we have to
deal with the error by hand.

* examples/test ($exit): Replace with...
($status): this.
Preserve the exit status of the test case.
* examples/c/bistromathic/bistromathic.test: Fix syntax error.
2020-05-05 08:21:12 +02:00
Akim Demaille b86dcaf40b doc: beware of timestamp issues on Haiku
On Haiku, help2man is fired on a freshly extracted tarball.
Reported by Bruno Haible.
https://lists.gnu.org/r/bug-bison/2020-05/msg00055.html

* doc/local.mk (bison.1): Be robust to a missing help2man.
2020-05-04 19:06:59 +02:00
Akim Demaille 0fafbbdefb tests: beware of wchar_t portability issues on AIX
https://lists.gnu.org/r/bug-bison/2020-05/msg00050.html
Reported by Bruno Haible.

* tests/diagnostics.at: here.
2020-05-04 08:09:22 +02:00
Akim Demaille 4b85b969d0 glr.c: beware of portability issues with PTRDIFF_MAX
For instance test 386, "glr.cc api.value.type={double}":

    types.at:366: $CXX $CXXFLAGS $CPPFLAGS  $LDFLAGS -o test test.cc $LIBS
    stderr:
    test.cc: In function 'ptrdiff_t yysplitStack(yyGLRStack*, ptrdiff_t)':
    test.cc:490:4: error: 'PTRDIFF_MAX' was not declared in this scope
       (PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : YY_CAST (ptrdiff_t, SIZE_MAX))
        ^
    test.cc:1805:37: note: in expansion of macro 'YYSIZEMAX'
           ptrdiff_t half_max_capacity = YYSIZEMAX / 2 / state_size;
                                         ^~~~~~~~~
    test.cc:490:4: note: suggested alternative: '__PTRDIFF_MAX__'
       (PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : YY_CAST (ptrdiff_t, SIZE_MAX))
        ^
    test.cc:1805:37: note: in expansion of macro 'YYSIZEMAX'
           ptrdiff_t half_max_capacity = YYSIZEMAX / 2 / state_size;
                                         ^~~~~~~~~

The failing tests are using glr.cc only, which I don't understand, the
problem is rather in glr.c, so I would expect glr.c tests to also fail.

Reported by Bruno Haible.
https://lists.gnu.org/archive/html/bug-bison/2020-05/msg00053.html

* data/skeletons/yacc.c: Move the block that defines
YYPTRDIFF_T/YYPTRDIFF_MAXIMUM, YYSIZE_T/YYSIZE_MAXIMUM, and
YYSIZEOF to...
* data/skeletons/c.m4 (b4_sizes_types_define): Here.
(b4_c99_int_type): Also take care of the #undefinition of short.
* data/skeletons/yacc.c, data/skeletons/glr.c: Use
b4_sizes_types_define.
* data/skeletons/glr.c: Adjust to use YYPTRDIFF_T/YYPTRDIFF_MAXIMUM,
YYSIZE_T/YYSIZE_MAXIMUM.
2020-05-04 07:44:42 +02:00
Akim Demaille 7727693711 todo: update 2020-05-04 07:37:40 +02:00
Akim Demaille ce27796b74 examples: beware of strnlen portability issues
One function missing on Solaris 10 Sparc:

     CCLD     examples/c/bistromathic/bistromathic
    Undefined                       first referenced
    symbol                             in file
    strnlen                             examples/c/bistromathic/bistromathic-parse.o
    ld: fatal: symbol referencing errors. No output written to examples/c/bistromathic/bistromathic

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

* examples/c/bistromathic/parse.y (xstrndup): Don't use strnlen.
xstrndup is assembled from gnulib's xstrndup, strndup and strnlen...
2020-05-04 06:48:00 +02:00
Akim Demaille 6135fdc152 examples: beware of portability issues with sh's trap
On AIX 7.2, when invoking "exit 77", we actually exit with 127.  The
"cleanup" function, called via trap, received an incorrect exit
status, something described in Autoconf's doc.
Reported by Bruno Haible.
https://lists.gnu.org/archive/html/bug-bison/2020-05/msg00029.html
https://lists.gnu.org/archive/html/bug-bison/2020-05/msg00047.html

* examples/test (skip): New.
* examples/c/bistromathic/bistromathic.test,
* examples/c/reccalc/reccalc.test: Use it, to ensure $? is set to 77
when the trap is called.
2020-05-04 06:48:00 +02:00
Akim Demaille f1497356e8 tests: beware of portability issues with diff -u
AIX 7.1 supports diff -u, but its output does not match the expected
one.
Reported by Bruno Haible.
https://lists.gnu.org/r/bug-bison/2020-05/msg00049.html

* tests/atlocal.in (DIFF_U_WORKS): New.
* tests/local.at (AT_DIFF_U_CHECK): New.
* tests/existing.at (_AT_TEST_EXISTING_GRAMMAR): Use AT_DIFF_U_CHECK.
2020-05-04 06:48:00 +02:00
Akim Demaille 1429569362 maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2020-05-03 19:52:38 +02:00
Akim Demaille 506c368ab2 version 3.5.93
* NEWS: Record release date.
2020-05-03 19:32:15 +02:00
Akim Demaille 4f9dc3bdc1 news: update for 3.5.93 2020-05-03 19:32:03 +02:00
Akim Demaille 0d81be2dc7 gnulib: update 2020-05-03 19:32:03 +02:00
Akim Demaille 32f44f4bfb tests: really skip tricky multichar test on Cygwin
In Autotest, anything outside AT_SETUP/AT_CLEANUP is discarded.

* tests/diagnostics.at (AT_TEST): Accept a skip-if test.
Use it to skip on cygwin.
2020-05-03 19:08:16 +02:00
Akim Demaille 38a8287813 bistromathic: beware of portability issues of readline on AIX
Readline may emit escape sequences before the prompt.
Reported by Bruno Haible.
https://lists.gnu.org/r/platform-testers/2020-05/msg00001.html.

* examples/c/bistromathic/bistromathic.test: Trust readline _only_ if
we get what we expect on some reference computation.
2020-05-03 18:10:58 +02:00
Akim Demaille df752784c2 examples: beware of portability issues with cmp
As someone wrote nearly 20 years ago in Autoconf's documentation,
don't use cmp to compare text files, but diff.
https://git.savannah.gnu.org/cgit/autoconf.git/commit/?id=abad4f0576a7dc361e5385e19c7681449103cdb1
Reported by Jannick.

* examples/test: Use diff, not cmp.
2020-05-03 17:53:47 +02:00
Akim Demaille 292409e91e build: fix warnings (shown on IRIX)
Appearing on IRIX with gcc -mabi=n32.
Reported by Bruno Haible.
https://lists.gnu.org/r/bug-bison/2020-05/msg00039.html

* examples/c++/variant-11.yy, examples/c/bistromathic/parse.y: Don't
give chars to isdigit, cast them to unsigned char before.
* src/complain.c: Use c_isdigit.
* src/fixits.c (fixits_run): Avoid casts.
* src/lalr.c (goto_print): Use %zu for a size_t.
2020-05-03 17:37:34 +02:00
Akim Demaille eea56d70d9 c++: be compatible with the pre-3.6 way to get a symbol's kind
Reported by Pramod Kumbhar.
https://lists.gnu.org/r/bug-bison/2020-05/msg00025.html

* data/skeletons/c++.m4: here.
2020-05-03 17:06:13 +02:00
Akim Demaille 6e2de439e6 bistromathic: beware of portability issues with strndup
Reported by Dagobert Michelsen.
https://lists.gnu.org/r/bug-bison/2020-05/msg00026.html

* examples/c/bistromathic/parse.y (xstrndup): New.
Use it.
2020-05-03 17:06:13 +02:00
Akim Demaille e33cd4b824 flex: fix incorrect use of Automake conditional
AM_CONDITIONAL does _not_ define a shell variable...
Reported privately by Denis Excoffier.

* configure.ac (LEX_CXX_WORKS): Fix its definition.
2020-05-03 17:04:15 +02:00
Bruno HaibleandAkim Demaille 0669780ff8 package: fix a link error on IRIX
https://lists.gnu.org/r/bug-bison/2020-05/msg00035.html

* src/local.mk (src_bison_LDADD): Mention libbison.a before, not after, the
system libraries.
2020-05-03 16:49:29 +02:00
Akim Demaille 160df220b1 bistromathic: beware of portability of readline
Don't try to build bistromathic if we don't have readline.
Reported by Bruno Haible.
https://lists.gnu.org/r/bug-bison/2020-05/msg00028.html

* configure.ac (ENABLE_BISTROMATHIC): New.
* examples/c/bistromathic/local.mk: Use it.
* examples/c/bistromathic/bistromathic.test: Exit 77 for skip.
2020-05-03 16:38:34 +02:00
Akim Demaille da5c072a62 tests: beware of portability issues of sh
"foo || bar" does not invoke bar on AIX 7.2 when foo does not exist.
It just dies.
Reported by Bruno Haible.
https://lists.gnu.org/r/bug-bison/2020-05/msg00029.html

* examples/c/reccalc/reccalc.test: Check for seq in a subshell.
2020-05-03 16:38:34 +02:00
Akim Demaille 73ac8ff409 maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2020-05-03 13:07:08 +02:00
Akim Demaille 0e0fb0efc9 version 3.5.92
* NEWS: Record release date.
2020-05-03 12:48:16 +02:00
Akim Demaille bb1d776be0 news: update for 3.5.92 2020-05-03 12:47:21 +02:00
Akim Demaille d7e1abe656 gnulib: update 2020-05-03 12:43:55 +02:00
Akim Demaille 13a1537dba java: demonstrate push parsers
* data/skeletons/lalr1.java (Location): Make it a static class.
(Lexer.yylex, Lexer.getLVal, Lexer.getStartPos, Lexer.getEndPos):
These are not needed in push parsers.
* examples/java/calc/Calc.y: Demonstrate push parsers in the Java.
* doc/bison.texi: Push parsers have been supported for a long time,
remove incorrect statements stating the opposite.
2020-05-03 11:28:36 +02:00
Akim Demaille ac2ba46053 doc: clarify what a location is
Reported by Arthur Schwarz <[email protected]>
https://lists.gnu.org/r/help-bison/2013-12/msg00009.html

* doc/bison.texi (Location Type): here.
2020-05-03 11:28:36 +02:00
Akim Demaille 2a7a2c1d3a tests: beware of mbswidth portability issues
Shy away from these issues on Cygwin.
Reported Denis Excoffier.
https://lists.gnu.org/r/bug-bison/2020-05/msg00003.html

* tests/diagnostics.at (Tabulations and multibyte characters): Split
in two.
2020-05-03 11:28:36 +02:00
Akim Demaille c9b5b68c73 examples: beware of intl portability issues
Reported by Horst von Brand.
https://lists.gnu.org/r/bug-bison/2020-04/msg00033.html

* examples/c/bistromathic/Makefile: libintl might not be needed, but
libm probably is.
* examples/c/bistromathic/parse.y: Include locale.h.
2020-05-03 10:32:33 +02:00
Akim Demaille 26aef31552 examples: beware of portability issues with readline
On OpenBSD 6.5, the prompt is repeated, but not the actual command
line...  Don't try to cope with that.
Reported by Bruno Haible.
https://lists.gnu.org/r/bug-bison/2020-05/msg00015.html

* examples/c/bistromathic/bistromathic.test: Skip when readline behave
this way.
2020-05-03 10:32:33 +02:00
Akim Demaille 392f3caef6 examples: beware of the portability of flex --header-file
The option --header was introduced in version 2.5.6.
The option --header-file was introduced in version 2.6.4.
Reported by Bruno Haible.
https://lists.gnu.org/r/bug-bison/2020-05/msg00013.html

So use --header, and do bother with versions that don't support it.

* m4/flex.m4: Check whether flex supports --header.
* configure.ac (FLEX_WORKS, FLEX_CXX_WORKS): Set to false if it doesn't.
* * examples/c/reccalc/local.mk, examples/c/reccalc/Makefile:
Use --header rather than --header-file.
2020-05-03 10:32:32 +02:00
Akim Demaille ccaa8e29f9 c++: provide backward compatibility on by_type
To write unit tests for their scanners, some users depended on
symbol_type::token():

    Lexer lex("12345");
    symbol_type t = lex.nextToken();
    assert(t.token() == token::INTLIT);
    assert(t.value.as<int>() == 12345);

But symbol_type::token() was removed in Bison 3.5 because it relied on
a conversion table.  So users had to find other patterns, such as

    assert(t.type_get() == by_type(token::INTLIT).type_get());

which relies on several private implementation details.

As part of transitioning from "token type" to "token kind", and making
this a public and documented interface, "by_type" was renamed
"by_kind" and "type_get()" was renamed as "kind()".  The latter had
backward compatibility mechanisms, not the former.

In Bison 3.6 none of this should be used, but rather

    assert(t.kind() == symbol_kind::S_INTLIT);

Reported by Pramod Kumbhar.
https://lists.gnu.org/r/bug-bison/2020-05/msg00012.html

* data/skeletons/c++.m4 (by_type): Make it an alias to by_kind.
2020-05-03 09:20:08 +02:00
Akim Demaille 76c3bccf40 yacc.c: improve formatting of the generated code
* data/skeletons/yacc.c (yy_reduce_print): here.
2020-05-02 10:17:01 +02:00
Akim Demaille 6275137378 doc: java supports push parsers since 3.0 (2013-07-25)
* doc/bison.texi: Clarify this.
2020-05-02 09:29:05 +02:00
Akim Demaille d0571c846f java: fix coding style
I don't plan to fix everything in one go.  But this was in the way of
the next commit.

* data/skeletons/lalr1.java: Avoid space before parens.
* tests/java.at: Adjust.
2020-05-02 09:27:16 +02:00
Akim Demaille 8c1002e4b7 style: comment changes
* tests/java.at: here.
2020-05-02 09:08:26 +02:00
Akim Demaille dbd8fd71ba todo: more 2020-05-02 08:18:20 +02:00
Akim Demaille 95bac741c3 style: more documentation about errs
Suggested by Angelo Borsotti.
https://lists.gnu.org/r/bug-bison/2014-02/msg00003.html

* src/state.h: here.
2020-05-02 08:18:20 +02:00
Akim Demaille f8ab4d81c0 doc: document the exit status
Suggested by Alexandre Duret-Lutz.
https://lists.gnu.org/r/bug-bison/2013-09/msg00015.html

* doc/bison.texi (Invocation): Here.
2020-05-01 10:48:44 +02:00
Akim Demaille d55c9b001a java: add missing i18n requests
* data/skeletons/lalr1.java (reportSyntaxError): Here.
2020-05-01 10:36:05 +02:00
Akim Demaille 611495999f java: style: fix coding style of yyerror/reportSyntaxError
* data/skeletons/lalr1.java: here.
2020-05-01 10:36:05 +02:00
Akim Demaille 01d5f232a9 java: avoid useless work
* data/skeletons/lalr1.java (yySymbolPrint): Avoid the computation of
the argument if useless.
While at it, fix Java coding style.
2020-05-01 10:36:05 +02:00
Akim Demaille 0407acbc59 java: comment changes
* data/skeletons/lalr1.java, examples/java/calc/Calc.y: here.
2020-05-01 10:36:05 +02:00
Akim Demaille 0c0e778bd1 news: make it more consistent
* NEWS: Use the same pattern for titles.
2020-05-01 10:36:05 +02:00
Akim Demaille 30357ae942 c++: use modern idioms to make classes non-copyable
Reported by Don Macpherson.
https://lists.gnu.org/r/bug-bison/2019-05/msg00015.html
https://github.com/akimd/bison/issues/36

* data/skeletons/lalr1.cc, data/skeletons/stack.hh,
* data/skeletons/variant.hh: Delete the copy-ctor and the copy operator.
2020-05-01 06:52:04 +02:00
Akim Demaille fb1d76d9a9 yacc.c: avoid the use of a temporary
* data/skeletons/yacc.c: Use YYLLOC_DEFAULT directly with the final
destination.
2020-04-30 08:07:55 +02:00
Akim Demaille a61bc3f9f8 maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2020-04-29 09:07:50 +02:00
Akim Demaille f0942df01a version 3.5.91
* NEWS: Record release date.
2020-04-29 08:47:35 +02:00
Akim Demaille 52ababbc89 build: fix syntax-check issues
* cfg.mk: We do want to gettextize the examples.
* po/POTFILES.in: Adjust.
2020-04-29 08:47:04 +02:00
Akim Demaille 8e11933e41 gnulib: update 2020-04-29 08:32:25 +02:00
Akim Demaille 99efa35369 doc: document YYEOF, YYUNDEF and YYerror
* doc/bison.texi (Special Tokens): New.
* examples/c/bistromathic/parse.y: Formatting changes.
2020-04-29 08:23:55 +02:00
Akim Demaille 547545a795 package: fix distcheck
Bison emits strings to translate in the generated code, for builtin
tokens.  So they appear only in generated parsers, which are not
shipped, so they are not in the src tree, so we cannot use them in our
POTFILE.

Except src/parse-gram.c, which is in the source tree.  And even in the
git repo.  But to avoid useless diffs in the repo, we do not keep the
src/parse-gram.c _with_ the #lines.  This is done in a dist-hook which
regenerates src/parse-gram.c when we run "make dist".

Unfortunately, then, update-po traverses the whole tree and sees that
the location of the strings to translate in src/parse-gram.c have
changed, so the bison.pot is to be updated.  And that is not possible
in the "make dist" which is run within "make distcheck"
(not the one preparing the dist for distcheck, the one run by
distcheck to check that a distributed tarball can build a tarball)
because then the src tree is read-only.

So let's not put src/parse-gram.c in the POTFILE, and expose these
strings to gettextize by hand.

* src/i18n-strings.c: New.
* po/POTFILES.in: Add it, and remove src/parse-gram.c.
2020-04-29 07:01:22 +02:00
Akim Demaille 1b5cf80e32 style: avoid gettextize warnings
* src/scan-gram.l, src/scan-skel.l: Help it see the start and end of
"character literals".
2020-04-29 07:01:22 +02:00
Akim Demaille 4c641c5189 tests: beware of portability of readline
* examples/test: here.
2020-04-29 07:01:22 +02:00
Akim Demaille 3b05de2d05 yacc.c: install backward compatibility for YYERRCODE
Some people have been using that symbol.  Some even have #defined it
themselves.
https://lists.gnu.org/r/bison-patches/2020-04/msg00138.html

Let's provide backward compatibility, having it point to YYUNDEF, so
that an error message is generated.

* data/skeletons/yacc.c (YYERRCODE): New, at the exact same location
it was defined before.
2020-04-28 08:26:49 +02:00
Akim Demaille 902a235ad3 style: c++: s/type/kind/ where appropriate
These are internal details.  `type_get ()` is still there to ensure
backward compatibility, `kind ()` being the modern way.

* data/skeletons/c++.m4 (by_type, by_type::type): Rename as...
(by_kind, by_kind::kind_): this.
Adjust dependencies.
2020-04-28 08:16:05 +02:00
Akim Demaille 11027558c8 java: clean up the definition of token kinds
From

    public interface Lexer {
      /* Token kinds.  */
      /** Token number, to be returned by the scanner.  */
      static final int YYEOF = 0;
      /** Token number, to be returned by the scanner.  */
      static final int YYERRCODE = 256;
      /** Token number, to be returned by the scanner.  */
      static final int YYUNDEF = 257;
      /** Token number, to be returned by the scanner.  */
      static final int BANG = 258;
    ...
      /** Deprecated, use b4_symbol(0, id) instead.  */
      public static final int EOF = YYEOF;

to

    public interface Lexer {
      /* Token kinds.  */
      /** Token "end of file", to be returned by the scanner.  */
      static final int YYEOF = 0;
      /** Token error, to be returned by the scanner.  */
      static final int YYerror = 256;
      /** Token "invalid token", to be returned by the scanner.  */
      static final int YYUNDEF = 257;
      /** Token "!", to be returned by the scanner.  */
      static final int BANG = 258;
    ...
      /** Deprecated, use YYEOF instead.  */
      public static final int EOF = YYEOF;

* data/skeletons/java.m4 (b4_token_enum): Display the symbol's tag in
comment.
* data/skeletons/lalr1.java: Address overquotation issue.
* examples/java/calc/Calc.y, examples/java/simple/Calc.y: Use YYEOF,
not EOF.
2020-04-28 07:56:00 +02:00
Akim Demaille cd4e799da4 error: rename the error token from YYERRCODE to YYerror
See https://lists.gnu.org/r/bison-patches/2020-04/msg00162.html.

* data/skeletons/bison.m4, data/skeletons/c.m4, data/skeletons/glr.cc,
* data/skeletons/lalr1.java, doc/bison.texi,
* examples/c/bistromathic/parse.y, src/scan-gram.l, src/symtab.c
(YYERRCODE): Rename as...
(YYerror): this.
Adjust dependencies.
2020-04-28 07:54:07 +02:00
Akim Demaille 7346163840 dogfooding: use YYERRCODE in our scanner
* src/scan-gram.l: Use it.
* tests/input.at: Adjust.
2020-04-27 08:21:50 +02:00
Akim Demaille 89c4e1becf scanner: avoid spurious errors about empty character literals
On an invalid character literal such as "'\777'" we used to produce
two errors:

    input.y:2.9-12: error: invalid number after \-escape: 777
    input.y:2.8-13: error: empty character literal

Get rid of the second one.

* src/scan-gram.l (STRING_GROW_ESCAPE): New.
* tests/input.at: Adjust.
2020-04-27 08:06:49 +02:00
Akim Demaille 3262747c5b scanner: bad character literals are errors
* src/scan-gram.l: These are errors, not warnings.
* tests/input.at: Adjust.
2020-04-27 07:17:04 +02:00
Akim Demaille 5f3cd49acc regen 2020-04-27 07:08:55 +02:00
Akim Demaille e6d928c4e8 todo: update 2020-04-26 19:55:52 +02:00
Akim Demaille b254b36db8 all: don't emit an error message when the scanner returns YYERRCODE
I'm quite pleased to see that the tricky case of glr.c was already
prepared by the changes to support syntax_error exceptions.  Better
yet, it is actually syntax_error that becomes a special case of the
general pattern: make yytoken be YYERRCODE.

* data/skeletons/glr.c (YYFAULTYTOK): Remove the now useless (Basil)
Faulty token.
Instead, use the error token.
* data/skeletons/lalr1.d, data/skeletons/lalr1.java: When computing
the action, first check the case of the error token.

* tests/calc.at: Check cases for the error token symbols before and
after it.
2020-04-26 19:55:52 +02:00
Akim Demaille 58e79539fc c: don't emit an error message when the scanner returns YYERRCODE
* data/skeletons/yacc.c (yyparse): When the scanner returns YYERRCODE,
go directly to error recovery (yyerrlab1).
However, don't keep the error token as lookahead, that token is too
special.
* data/skeletons/lalr1.cc: Likewise.

* examples/c/bistromathic/parse.y (yylex): Use that feature to report
nicely invalid characters.
* examples/c/bistromathic/bistromathic.test: Check that.
* examples/test: Neutralize gratuitous differences such as rule
position.

* tests/calc.at: Check that case in C only.
The other case seem to be working, but that's an illusion that the
next commit will address (in fact, they can enter endless loops, and
report the error several times anyway).
2020-04-26 18:05:30 +02:00
Akim Demaille 60366b152b examples: bistromathic: demonstrate error recovery
* examples/c/bistromathic/parse.y: here.
* examples/c/bistromathic/bistromathic.test: Check it.
Included a stupid case where the error is actually ignored.
2020-04-26 16:08:47 +02:00
Akim Demaille c90110efd3 examples: bistromathic: when quitting, close the current line
When the user ctrl-d the line, we left the cursor not at col 0.
Let's fix that.
This revealed a few short-comings in the testing framework.

* examples/test (run): Also display the diffs.
And support -n.
* examples/c/bistromathic/bistromathic.test
* examples/c/bistromathic/parse.y
2020-04-26 16:08:47 +02:00
Akim Demaille 3b50adf7f4 examples: bistromathic: comment changes
* examples/c/bistromathic/parse.y: here.
2020-04-26 16:08:47 +02:00
Akim Demaille 3aaa971096 doc: hacking tricks
* README-hacking.md: Here.
2020-04-26 16:08:42 +02:00
Akim Demaille 7eabe1c70b c++: make valid to print the empty symbol
* data/skeletons/lalr1.cc (yy_print_): here.
2020-04-26 15:09:52 +02:00
Akim Demaille 7fec669e42 c++: always define symbol_name
* data/skeletons/lalr1.cc (symbol_name): Always define it, even when
it's actually yytname which is used.
2020-04-26 15:09:52 +02:00
Akim Demaille cbbbe12e02 c++: fix a few style issues
* data/skeletons/lalr1.cc (yystack_print_, yy_reduce_print_): Add
missing const.
(yystack_print_): Rename as...
(yy_stack_print_): this.
* data/skeletons/glr.cc (yy_symbol_value_print_, yy_symbol_print_):
Add missing const.
2020-04-26 15:09:52 +02:00
Akim Demaille 286d0755f8 all: prefer YYERRCODE to YYERROR
We will not keep YYERRCODE anyway, it causes backward compatibility
issues.  So as a first step, let all the skeletons use that name,
until we have a better one.

* data/skeletons/bison.m4, data/skeletons/glr.c,
* data/skeletons/glr.cc, data/skeletons/lalr1.cc,
* data/skeletons/lalr1.d, data/skeletons/lalr1.java,
* data/skeletons/yacc.c, doc/bison.texi, tests/headers.at,
* tests/input.at:
here.
2020-04-26 15:09:51 +02:00
Akim Demaille 1c3d79b871 style: glr.c: clarify
* data/skeletons/glr.c: Make the code a bit clearer.
2020-04-26 14:49:26 +02:00
Akim Demaille 9c72d3c5a8 style: prefer b4_has_translations_if
* data/skeletons/glr.c, data/skeletons/yacc.c: here.
2020-04-26 13:34:30 +02:00
Akim Demaille bc083be055 style: glr.c: fix indentation issue
* data/skeletons/glr.c (yyparse): here.
2020-04-26 10:57:23 +02:00
Akim Demaille 22eeb1ab8a style: fix a few remaining 'type' instead of 'kind'
* data/skeletons/glr.c, data/skeletons/yacc.c (YY_SYMBOL_PRINT):
Here.
2020-04-26 10:57:22 +02:00
Akim Demaille c4dbc1776c skeletons: make the warning about implementation details clearer
* data/skeletons/bison.m4 (b4_disclaimer): Here.
* data/skeletons/lalr1.d, data/skeletons/lalr1.java: Use it.
2020-04-26 10:57:02 +02:00
Akim Demaille b74fc07d21 style: c: fix a few minor issues about indentation of cpp directives
* README-hacking.md: More about cpp.
* data/skeletons/c.m4, data/skeletons/yacc.c: Style changes.
2020-04-25 12:16:57 +02:00
Akim Demaille 3ab12c1036 bench: store in benches/012 rather than in benches/12
* etc/bench.pl.in ($basedir): New.
Format $count with a least three digits.
2020-04-25 11:34:06 +02:00
Akim Demaille 30ce43b2b5 bench: minor improvements
* etc/bench.pl.in: Don't force parse.error=detailed
Use a simpler way to display the pseudo %bison directive.
(&bench_with_gbenchmark): Give details about the compiler.
2020-04-25 11:06:16 +02:00
Akim Demaille 150dc95395 style: clarify #endif
We could try to avoid the weird "#if 1", but then the indentation of
the inner #if would be wrong.  Let' keep it this way.

* data/skeletons/yacc.c: here.
Also, avoid sticking the comment to the directive.
2020-04-25 11:06:16 +02:00
Akim Demaille bb7c4a5508 style: minor fixes
* data/skeletons/bison.m4, doc/bison.texi: Spell check.
* examples/c/bistromathic/parse.y (N_): Remove, now useless.
2020-04-25 08:00:08 +02:00
Akim Demaille 5c9f50b545 examples: bistromathic: shorten token description
* examples/c/bistromathic/parse.y: "number" is enough.
* doc/bison.texi: Likewise.
2020-04-24 19:03:12 +02:00
Akim Demaille b42702d738 examples: bistromathic: demonstrate internationalization
Currently it was only using stubs.  Let's actually translate the
strings using gettext.

* examples/c/bistromathic/local.mk: Define LOCALEDIR, BISON_LOCALEDIR
and link with libintl.
* examples/c/bistromathic/parse.y: Use them.
Remove useless includes.
Take ENABLE_NLS into account.
(error_format_string): New.
(yyreport_syntax_error): Rewrite to rely on a format string, which is
more appropriate for internationalization.
* examples/c/bistromathic/Makefile: We no longer use Flex.
We need readline and intl.

* doc/bison.texi: Point to bistromathic for a better option for
internationalization.
* po/POTFILES.in: Add bistromathic.
2020-04-24 19:03:12 +02:00
Akim Demaille 401e7c5c36 todo: update for YYERRCODE 2020-04-24 19:03:12 +02:00
Akim Demaille 93fec67c46 regen 2020-04-24 08:23:27 +02:00
Akim Demaille 4378e2dc3c diagnostics: fix a typo
* src/complain.c: here.
2020-04-24 08:22:22 +02:00
Akim Demaille 81334eb5a0 c, c++: provide a default definition for N_
In C/C++, N_ is a no-op.  Define it if the user didn't.
Suggested by Frank Heckenbach.
https://lists.gnu.org/r/bug-bison/2020-04/msg00010.html

* src/output.c (prepare_symbol_names): Rename has_translations as
has_translations_flag.
* data/skeletons/bison.m4 (b4_has_translations_if): New.
* data/skeletons/java.m4 (b4_trans): Use it.

* data/skeletons/glr.c, data/skeletons/lalr1.cc, data/skeletons/yacc.c
(N_): Provide a default definition.
2020-04-20 07:37:45 +02:00
Akim Demaille df373f1ea1 i18n: also look in src/parse-gram.c
Some strings appears in the generated file only, e.g., translation of
"end of file".  So don't forget to go and see there.
2020-04-19 15:40:12 +02:00
Akim Demaille 9b7e7077dd style: fix comments
* data/skeletons/glr.c, data/skeletons/lalr1.cc,
* data/skeletons/yacc.c: here.
2020-04-19 15:40:12 +02:00
Akim Demaille 5ab0086157 tokens: clean up the translation of special symbols
* src/output.c (prepare_symbol_names): Don't play tricks with the
symbols, it's quite too late.
(has_translations): Move to...
* src/symtab.c: here.
(symbols_pack): Use it to enable translation for special symbols.
2020-04-19 15:40:12 +02:00
Akim Demaille 2831bd376f news: fix typo
Reported by Frank Heckenbach.
2020-04-19 08:20:57 +02:00
Akim Demaille 1d0e3ee896 tests: beware of portability issues with wc
On macOS, wc -l always prepends the result with a tab, even when fed
by stdin.  But anyway, we should have used `grep -c -v`, which appears
to be portable according to Autoconf's "Limitations of Usual Tools"
section.
Reported by Denis Excoffier.
https://lists.gnu.org/r/bug-bison/2020-04/msg00009.html

* tests/calc.at (_AT_CHECK_CALC): Use grep's -c instead.
2020-04-19 08:12:31 +02:00
Akim Demaille 0a64b76430 maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2020-04-18 10:59:05 +02:00
87 changed files with 2439 additions and 1137 deletions
+1 -1
View File
@@ -1 +1 @@
3.5.4 3.6.2
+58 -40
View File
@@ -46,7 +46,7 @@ jobs:
- ./bootstrap - ./bootstrap
- ./configure --enable-gcc-warnings || { cat config.log && false; } - ./configure --enable-gcc-warnings || { cat config.log && false; }
- make -j2 - make -j2
- make -j2 dist - make -j2 dist-xz
# Can help understanding why we get "dirty" tarballs. # Can help understanding why we get "dirty" tarballs.
- git status - git status
- dist=$(echo bison*.xz) - dist=$(echo bison*.xz)
@@ -69,53 +69,53 @@ jobs:
# Start with three completely different environments, to get errors asap. # Start with three completely different environments, to get errors asap.
- name: "GCC 9 -O3" - name: "GCC 10 -O3"
stage: check stage: check
os: linux os: linux
dist: bionic dist: bionic
addons: &gcc9 addons: &gcc10
apt: apt:
sources: sources:
# See https://github.com/travis-ci/apt-source-safelist/issues/410. # See https://github.com/travis-ci/apt-source-safelist/issues/410.
- sourceline: 'ppa:ubuntu-toolchain-r/test' - sourceline: 'ppa:ubuntu-toolchain-r/test'
packages: g++-9 packages: g++-10
env: env:
- CC=gcc-9 - CC=gcc-10
- CXX=g++-9 - CXX=g++-10
- CONFIGUREFLAGS='CPPFLAGS=-DNDEBUG CFLAGS=-O3 CXXFLAGS=-O3' - CONFIGUREFLAGS='CPPFLAGS=-DNDEBUG CFLAGS=-O3 CXXFLAGS=-O3'
# ASAN is time consuming, and we timeout the 50min granted by # ASAN is time consuming, and we timeout the 50min granted by
# Travis if we run all the tests in one go. Run in two parts. # Travis if we run all the tests in one go. Run in two parts.
- name: "Clang 9 libc++ and ASAN part 1" - name: "Clang 10 libc++ and ASAN part 1"
stage: check stage: check
os: linux os: linux
dist: bionic dist: bionic
addons: &clang9 addons: &clang10
apt: apt:
sources: sources:
# See https://github.com/travis-ci/apt-source-safelist/issues/410. # See https://github.com/travis-ci/apt-source-safelist/issues/410.
- sourceline: 'ppa:ubuntu-toolchain-r/test' - sourceline: 'ppa:ubuntu-toolchain-r/test'
- sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main' - sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key' key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
packages: packages:
- clang-9 - clang-10
- libc++-9-dev - libc++-10-dev
- libc++abi-9-dev - libc++abi-10-dev
env: env:
# Do not use ASAN with ubuntu's libc++: https://bugs.llvm.org/show_bug.cgi?id=17379 # Do not use ASAN with ubuntu's libc++: https://bugs.llvm.org/show_bug.cgi?id=17379
- CC='clang-9 -fsanitize=address' - CC='clang-10 -fsanitize=address'
- CXX='clang++-9 -fsanitize=address -stdlib=libc++' - CXX='clang++-10 -fsanitize=address -stdlib=libc++'
- PART=1 - PART=1
- name: "Clang 9 libc++ and ASAN part 2" - name: "Clang 10 libc++ and ASAN part 2"
stage: check stage: check
os: linux os: linux
dist: bionic dist: bionic
addons: *clang9 addons: *clang10
env: env:
# Do not use ASAN with ubuntu's libc++: https://bugs.llvm.org/show_bug.cgi?id=17379 # Do not use ASAN with ubuntu's libc++: https://bugs.llvm.org/show_bug.cgi?id=17379
- CC='clang-9 -fsanitize=address' - CC='clang-10 -fsanitize=address'
- CXX='clang++-9 -fsanitize=address -stdlib=libc++' - CXX='clang++-10 -fsanitize=address -stdlib=libc++'
- PART=2 - PART=2
- name: "ICC" - name: "ICC"
@@ -135,46 +135,41 @@ jobs:
packages: packages:
- intel-oneapi-icc - intel-oneapi-icc
## ------- ## - name: "ARM64: GCC 10 -O3 part 1"
## First. ##
## ------- ##
# Start with three completely different environments, to get
# errors asap.
- name: "ARM64: GCC 9 -O3 part 1"
stage: check stage: check
os: linux os: linux
arch: arm64 arch: arm64
dist: bionic dist: bionic
addons: *gcc9 addons: *gcc10
env: env:
- CC=gcc-9 - CC=gcc-10
- CXX=g++-9 - CXX=g++-10
- CONFIGUREFLAGS='CPPFLAGS=-DNDEBUG CFLAGS=-O3 CXXFLAGS=-O3' - CONFIGUREFLAGS='CPPFLAGS=-DNDEBUG CFLAGS=-O3 CXXFLAGS=-O3'
- PART=1 - PART=1
# GCC10 on PPC seems to be buggy.
# E.g., https://travis-ci.org/github/akimd/bison/jobs/687812428.
- name: "PPC64le: GCC 9 part 1" - name: "PPC64le: GCC 9 part 1"
stage: check stage: check
os: linux os: linux
arch: ppc64le arch: ppc64le
dist: bionic dist: bionic
addons: *gcc9 addons: *gcc10
env: env:
- CC=gcc-9 - CC=gcc-9
- CXX=g++-9 - CXX=g++-9
- CONFIGUREFLAGS='CFLAGS=-O3 CXXFLAGS=-O3' - CONFIGUREFLAGS='CFLAGS=-O3 CXXFLAGS=-O3'
- PART=1 - PART=1
- name: "s390x: GCC 9 part 1" - name: "s390x: GCC 10 part 1"
stage: check stage: check
os: linux os: linux
arch: s390x arch: s390x
dist: bionic dist: bionic
addons: *gcc9 addons: *gcc10
env: env:
- CC=gcc-9 - CC=gcc-10
- CXX=g++-9 - CXX=g++-10
- CONFIGUREFLAGS='CFLAGS=-O3 CXXFLAGS=-O3' - CONFIGUREFLAGS='CFLAGS=-O3 CXXFLAGS=-O3'
- PART=1 - PART=1
@@ -182,15 +177,19 @@ jobs:
## GCC. ## ## GCC. ##
## ----- ## ## ----- ##
- name: "GCC 8 with sanitizers part 1" - name: "GCC 9 with sanitizers part 1"
stage: check
os: linux os: linux
dist: bionic dist: bionic
addons: addons:
apt: apt:
packages: g++-8 sources:
# See https://github.com/travis-ci/apt-source-safelist/issues/410.
- sourceline: 'ppa:ubuntu-toolchain-r/test'
packages: g++-9
env: env:
- CC='gcc-8 -fsanitize=undefined,address -fno-omit-frame-pointer' - CC='gcc-9 -fsanitize=undefined,address -fno-omit-frame-pointer'
- CXX='g++-8 -fsanitize=undefined,address -fno-omit-frame-pointer' - CXX='g++-9 -fsanitize=undefined,address -fno-omit-frame-pointer'
- CONFIGUREFLAGS='CFLAGS=-O1 CXXFLAGS=-O1' - CONFIGUREFLAGS='CFLAGS=-O1 CXXFLAGS=-O1'
- PART=1 - PART=1
@@ -292,7 +291,27 @@ jobs:
## Clang. ## ## Clang. ##
## ------- ## ## ------- ##
- name: "Clang 8 -O3" - name: "Clang 9 -O3"
stage: check
os: linux
dist: bionic
addons:
apt:
sources:
# See https://github.com/travis-ci/apt-source-safelist/issues/410.
- sourceline: 'ppa:ubuntu-toolchain-r/test'
- sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
packages:
- clang-9
- libc++-9-dev
- libc++abi-9-dev
env:
- CC='clang-9'
- CXX='clang++-9 -stdlib=libc++'
- CONFIGUREFLAGS='CPPFLAGS=-DNDEBUG CFLAGS=-O3 CXXFLAGS=-O3'
- name: "Clang 8"
stage: check stage: check
os: linux os: linux
dist: bionic dist: bionic
@@ -305,7 +324,6 @@ jobs:
env: env:
- CC=clang-8 - CC=clang-8
- CXX='clang++-8 -stdlib=libc++' - CXX='clang++-8 -stdlib=libc++'
- CONFIGUREFLAGS='CPPFLAGS=-DNDEBUG CFLAGS=-O3 CXXFLAGS=-O3'
- name: "Clang 7" - name: "Clang 7"
stage: check stage: check
+4
View File
@@ -127,3 +127,7 @@ gen-ChangeLog:
--since=$(gen_start_date) > $$cl.tmp && \ --since=$(gen_start_date) > $$cl.tmp && \
mv -f $$cl.tmp $$cl; \ mv -f $$cl.tmp $$cl; \
fi fi
# Useful to debug.
.c.i:
$(CC) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -o $@ -E $<
+90 -36
View File
@@ -1,6 +1,42 @@
GNU Bison NEWS GNU Bison NEWS
* Noteworthy changes in release 3.5.90 (2020-04-18) [beta] * Noteworthy changes in release 3.6.3 (2020-06-03) [stable]
** Bug fixes
Incorrect comments in the generated parsers.
Warnings in push parsers (yacc.c).
Incorrect display of gotos in LAC traces (lalr1.cc).
* Noteworthy changes in release 3.6.2 (2020-05-17) [stable]
** Bug fixes
Some tests were fixed.
When token aliases contain comment delimiters:
%token FOO "/* foo */"
bison used to emit "nested" comments, which is invalid C.
* Noteworthy changes in release 3.6.1 (2020-05-10) [stable]
** Bug fixes
Restored ANSI-C compliance in yacc.c.
GNU readline portability issues.
In C++, yy::parser::symbol_name is now a public member, as was intended.
** New features
In C++, yy::parser::symbol_type now has a public name() member function.
* Noteworthy changes in release 3.6 (2020-05-08) [stable]
** Backward incompatible changes ** Backward incompatible changes
@@ -14,6 +50,12 @@ GNU Bison NEWS
(2013-07-25), "%error-verbose" is deprecated in favor of "%define (2013-07-25), "%error-verbose" is deprecated in favor of "%define
parse.error verbose". parse.error verbose".
** Deprecated features
The YYPRINT macro, which works only with yacc.c and only for tokens, was
obsoleted long ago by %printer, introduced in Bison 1.50 (November 2002).
It is deprecated and its support will be removed eventually.
** New features ** New features
*** Improved syntax error messages *** Improved syntax error messages
@@ -80,7 +122,7 @@ GNU Bison NEWS
PLUS "+" PLUS "+"
MINUS "-" MINUS "-"
<double> <double>
NUM _("double precision number") NUM _("number")
<symrec*> <symrec*>
FUN _("function") FUN _("function")
VAR _("variable") VAR _("variable")
@@ -99,6 +141,18 @@ GNU Bison NEWS
It makes little sense to use this feature without enabling LAC (lookahead It makes little sense to use this feature without enabling LAC (lookahead
correction). correction).
*** Returning the error token
When the scanner returns an invalid token or the undefined token
(YYUNDEF), the parser generates an error message and enters error
recovery. Because of that error message, most scanners that find lexical
errors generate an error message, and then ignore the invalid input
without entering the error-recovery.
The scanners may now return YYerror, the error token, to enter the
error-recovery mode without triggering an additional error message. See
the bistromathic for an example.
*** Deep overhaul of the symbol and token kinds *** Deep overhaul of the symbol and token kinds
To avoid the confusion with types in programming languages, we now refer To avoid the confusion with types in programming languages, we now refer
@@ -117,10 +171,10 @@ GNU Bison NEWS
"yytoken_kind_t". "yytoken_kind_t".
This type now also includes tokens that were previously hidden: YYEOF (end This type now also includes tokens that were previously hidden: YYEOF (end
of input), YYUNDEF (undefined token), and YYERRCODE (error token). They of input), YYUNDEF (undefined token), and YYerror (error token). They
now have string aliases, internationalized when internationalization is now have string aliases, internationalized when internationalization is
enabled. Therefore, by default, error messages now refer to "end of file" enabled. Therefore, by default, error messages now refer to "end of file"
(internationalized) rather than the cryptic "$end", or to "invaid token" (internationalized) rather than the cryptic "$end", or to "invalid token"
rather than "$undefined". rather than "$undefined".
Therefore in most cases it is now useless to define the end-of-line token Therefore in most cases it is now useless to define the end-of-line token
@@ -186,8 +240,8 @@ GNU Bison NEWS
*** Examples *** Examples
There are now two examples in examples/java: a very simple calculator, and There are now examples/java: a very simple calculator, and a more complete
one that tracks locations to provide accurate error messages. one (push-parser, location tracking, and debug traces).
The lexcalc example (a simple example in C based on Flex and Bison) now The lexcalc example (a simple example in C based on Flex and Bison) now
also demonstrates location tracking. also demonstrates location tracking.
@@ -2518,7 +2572,7 @@ GNU Bison NEWS
Running "make install-pdf" (or -dvi, -html, -info, and -ps) no longer Running "make install-pdf" (or -dvi, -html, -info, and -ps) no longer
halts in the middle of its course. halts in the middle of its course.
* Changes in version 2.5 (2011-05-14): * Noteworthy changes in release 2.5 (2011-05-14)
** Grammar symbol names can now contain non-initial dashes: ** Grammar symbol names can now contain non-initial dashes:
@@ -2873,7 +2927,7 @@ GNU Bison NEWS
This bug has been fixed. This bug has been fixed.
* Changes in version 2.4.3 (2010-08-05): * Noteworthy changes in release 2.4.3 (2010-08-05)
** Bison now obeys -Werror and --warnings=error for warnings about ** Bison now obeys -Werror and --warnings=error for warnings about
grammar rules that are useless in the parser due to conflicts. grammar rules that are useless in the parser due to conflicts.
@@ -2893,7 +2947,7 @@ GNU Bison NEWS
** Minor documentation fixes. ** Minor documentation fixes.
* Changes in version 2.4.2 (2010-03-20): * Noteworthy changes in release 2.4.2 (2010-03-20)
** Some portability problems that resulted in failures and livelocks ** Some portability problems that resulted in failures and livelocks
in the test suite on some versions of at least Solaris, AIX, HP-UX, in the test suite on some versions of at least Solaris, AIX, HP-UX,
@@ -2987,7 +3041,7 @@ GNU Bison NEWS
message translations were not installed although supported by the message translations were not installed although supported by the
host system. host system.
* Changes in version 2.4.1 (2008-12-11): * Noteworthy changes in release 2.4.1 (2008-12-11)
** In the GLR defines file, unexpanded M4 macros in the yylval and yylloc ** In the GLR defines file, unexpanded M4 macros in the yylval and yylloc
declarations have been fixed. declarations have been fixed.
@@ -3012,7 +3066,7 @@ GNU Bison NEWS
** A few minor improvements to the Bison manual. ** A few minor improvements to the Bison manual.
* Changes in version 2.4 (2008-11-02): * Noteworthy changes in release 2.4 (2008-11-02)
** %language is an experimental feature. ** %language is an experimental feature.
@@ -3027,7 +3081,7 @@ GNU Bison NEWS
** Several bugs in the C++ skeleton and the experimental Java skeleton have been ** Several bugs in the C++ skeleton and the experimental Java skeleton have been
fixed. fixed.
* Changes in version 2.3b (2008-05-27): * Noteworthy changes in release 2.3b (2008-05-27)
** The quotes around NAME that used to be required in the following directive ** The quotes around NAME that used to be required in the following directive
are now deprecated: are now deprecated:
@@ -3213,7 +3267,7 @@ GNU Bison NEWS
** The nonfunctional --no-parser, -n, and %no-parser options have been ** The nonfunctional --no-parser, -n, and %no-parser options have been
completely removed from Bison. completely removed from Bison.
* Changes in version 2.3a, 2006-09-13: * Noteworthy changes in release 2.3a (2006-09-13)
** Instead of %union, you can define and use your own union type ** Instead of %union, you can define and use your own union type
YYSTYPE if your grammar contains at least one <type> tag. YYSTYPE if your grammar contains at least one <type> tag.
@@ -3327,7 +3381,7 @@ GNU Bison NEWS
The old spelling still works, but is not documented and may be removed The old spelling still works, but is not documented and may be removed
in a future release. in a future release.
* Changes in version 2.3, 2006-06-05: * Noteworthy changes in release 2.3 (2006-06-05)
** GLR grammars should now use "YYRECOVERING ()" instead of "YYRECOVERING", ** GLR grammars should now use "YYRECOVERING ()" instead of "YYRECOVERING",
for compatibility with LALR(1) grammars. for compatibility with LALR(1) grammars.
@@ -3335,7 +3389,7 @@ GNU Bison NEWS
** It is now documented that any definition of YYSTYPE or YYLTYPE should ** It is now documented that any definition of YYSTYPE or YYLTYPE should
be to a type name that does not contain parentheses or brackets. be to a type name that does not contain parentheses or brackets.
* Changes in version 2.2, 2006-05-19: * Noteworthy changes in release 2.2 (2006-05-19)
** The distribution terms for all Bison-generated parsers now permit ** The distribution terms for all Bison-generated parsers now permit
using the parsers in nonfree programs. Previously, this permission using the parsers in nonfree programs. Previously, this permission
@@ -3417,7 +3471,7 @@ GNU Bison NEWS
** DJGPP support added. ** DJGPP support added.
* Changes in version 2.1, 2005-09-16: * Noteworthy changes in release 2.1 (2005-09-16)
** The C++ lalr1.cc skeleton supports %lex-param. ** The C++ lalr1.cc skeleton supports %lex-param.
@@ -3443,7 +3497,7 @@ GNU Bison NEWS
print 'syntax error, unexpected number' instead of 'syntax error, print 'syntax error, unexpected number' instead of 'syntax error,
unexpected "number"'. unexpected "number"'.
* Changes in version 2.0, 2004-12-25: * Noteworthy changes in release 2.0 (2004-12-25)
** Possibly-incompatible changes ** Possibly-incompatible changes
@@ -3506,7 +3560,7 @@ GNU Bison NEWS
- Semicolons are now allowed before "|" in grammar rules, as POSIX requires. - Semicolons are now allowed before "|" in grammar rules, as POSIX requires.
* Changes in version 1.875, 2003-01-01: * Noteworthy changes in release 1.875 (2003-01-01)
** The documentation license has been upgraded to version 1.2 ** The documentation license has been upgraded to version 1.2
of the GNU Free Documentation License. of the GNU Free Documentation License.
@@ -3626,7 +3680,7 @@ GNU Bison NEWS
ago, but nobody noticed until we recently asked someone to try ago, but nobody noticed until we recently asked someone to try
building Bison with a K&R C compiler. building Bison with a K&R C compiler.
* Changes in version 1.75, 2002-10-14: * Noteworthy changes in release 1.75 (2002-10-14)
** Bison should now work on 64-bit hosts. ** Bison should now work on 64-bit hosts.
@@ -3657,7 +3711,7 @@ GNU Bison NEWS
was incorrectly rejected: $1 is defined in the second midrule was incorrectly rejected: $1 is defined in the second midrule
action, and is equal to the $$ of the first midrule action. action, and is equal to the $$ of the first midrule action.
* Changes in version 1.50, 2002-10-04: * Noteworthy changes in release 1.50 (2002-10-04)
** GLR parsing ** GLR parsing
The declaration The declaration
@@ -3801,7 +3855,7 @@ GNU Bison NEWS
** GNU M4 is now required when using Bison. ** GNU M4 is now required when using Bison.
* Changes in version 1.35, 2002-03-25: * Noteworthy changes in release 1.35 (2002-03-25)
** C Skeleton ** C Skeleton
Some projects use Bison's C parser with C++ compilers, and define Some projects use Bison's C parser with C++ compilers, and define
@@ -3816,7 +3870,7 @@ GNU Bison NEWS
This kludge also addresses some C++ problems when the stack was This kludge also addresses some C++ problems when the stack was
extended. extended.
* Changes in version 1.34, 2002-03-12: * Noteworthy changes in release 1.34 (2002-03-12)
** File name clashes are detected ** File name clashes are detected
$ bison foo.y -d -o foo.x $ bison foo.y -d -o foo.x
@@ -3836,7 +3890,7 @@ GNU Bison NEWS
** Fix test suite portability problems. ** Fix test suite portability problems.
* Changes in version 1.33, 2002-02-07: * Noteworthy changes in release 1.33 (2002-02-07)
** Fix C++ issues ** Fix C++ issues
Groff could not be compiled for the definition of size_t was lacking Groff could not be compiled for the definition of size_t was lacking
@@ -3845,7 +3899,7 @@ GNU Bison NEWS
** Catch invalid @n ** Catch invalid @n
As is done with $n. As is done with $n.
* Changes in version 1.32, 2002-01-23: * Noteworthy changes in release 1.32 (2002-01-23)
** Fix Yacc output file names ** Fix Yacc output file names
@@ -3853,7 +3907,7 @@ GNU Bison NEWS
** Italian, Dutch translations ** Italian, Dutch translations
* Changes in version 1.31, 2002-01-14: * Noteworthy changes in release 1.31 (2002-01-14)
** Many Bug Fixes ** Many Bug Fixes
@@ -3940,7 +3994,7 @@ GNU Bison NEWS
** --output ** --output
New, aliasing "--output-file". New, aliasing "--output-file".
* Changes in version 1.30, 2001-10-26: * Noteworthy changes in release 1.30 (2001-10-26)
** "--defines" and "--graph" have now an optional argument which is the ** "--defines" and "--graph" have now an optional argument which is the
output file name. "-d" and "-g" do not change; they do not take any output file name. "-d" and "-g" do not change; they do not take any
@@ -3951,7 +4005,7 @@ GNU Bison NEWS
** Portability fixes. ** Portability fixes.
* Changes in version 1.29, 2001-09-07: * Noteworthy changes in release 1.29 (2001-09-07)
** The output file does not define const, as this caused problems when used ** The output file does not define const, as this caused problems when used
with common autoconfiguration schemes. If you still use ancient compilers with common autoconfiguration schemes. If you still use ancient compilers
@@ -3986,7 +4040,7 @@ GNU Bison NEWS
** @$ ** @$
Automatic location tracking. Automatic location tracking.
* Changes in version 1.28, 1999-07-06: * Noteworthy changes in release 1.28 (1999-07-06)
** Should compile better now with K&R compilers. ** Should compile better now with K&R compilers.
@@ -3996,12 +4050,12 @@ GNU Bison NEWS
** There is now a FAQ. ** There is now a FAQ.
* Changes in version 1.27: * Noteworthy changes in release 1.27
** The make rule which prevented bison.simple from being created on ** The make rule which prevented bison.simple from being created on
some systems has been fixed. some systems has been fixed.
* Changes in version 1.26: * Noteworthy changes in release 1.26
** Bison now uses Automake. ** Bison now uses Automake.
@@ -4018,7 +4072,7 @@ GNU Bison NEWS
** Generated parsers should now work even on operating systems which do ** Generated parsers should now work even on operating systems which do
not provide alloca(). not provide alloca().
* Changes in version 1.25, 1995-10-16: * Noteworthy changes in release 1.25 (1995-10-16)
** Errors in the input grammar are not fatal; Bison keeps reading ** Errors in the input grammar are not fatal; Bison keeps reading
the grammar file, and reports all the errors found in it. the grammar file, and reports all the errors found in it.
@@ -4043,7 +4097,7 @@ the parser engine; a project can now use its own parser engine.
The actions go into a separate file called NAME.act, in the form of The actions go into a separate file called NAME.act, in the form of
a switch statement body. a switch statement body.
* Changes in version 1.23: * Noteworthy changes in release 1.23
The user can define YYPARSE_PARAM as the name of an argument to be The user can define YYPARSE_PARAM as the name of an argument to be
passed into yyparse. The argument should have type void *. It should passed into yyparse. The argument should have type void *. It should
@@ -4052,11 +4106,11 @@ by casting it to the proper pointer type.
Line numbers in output file corrected. Line numbers in output file corrected.
* Changes in version 1.22: * Noteworthy changes in release 1.22
--help option added. --help option added.
* Changes in version 1.20: * Noteworthy changes in release 1.20
Output file does not redefine const for C++. Output file does not redefine const for C++.
@@ -4113,8 +4167,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
LocalWords: fsanitize Vogelsgesang lis redeclared stdint automata yytname LocalWords: fsanitize Vogelsgesang lis redeclared stdint automata yytname
LocalWords: yysymbol yytnamerr yyreport ctx ARGMAX yysyntax stderr LPAREN 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 LocalWords: autocompletion bistromathic submessages Cayuela lexcalc hoc
LocalWords: yytoken YYUNDEF YYERRCODE LocalWords: yytoken YYUNDEF YYerror
Local Variables: Local Variables:
ispell-dictionary: "american" ispell-dictionary: "american"
+39
View File
@@ -37,6 +37,14 @@ Only user visible strings are to be translated: error messages, bits of the
assert/abort), and all the --trace output which is meant for the maintainers assert/abort), and all the --trace output which is meant for the maintainers
only. only.
## Syntax highlighting
It's quite nice to be in C++ mode when editing lalr1.cc for instance.
However tools such as Emacs will be fooled by the fact that braces and
parens do not nest, as in `[[}]]`. As a consequence you might be misguided
by its visual pairing to parens. The m4-mode is safer. Unfortunately the
m4-mode is also fooled by `#` which is sees as a comment, stops pairing with
parens/brackets that are inside...
## Coding Style ## Coding Style
Do not add horizontal tab characters to any file in Bison's repository Do not add horizontal tab characters to any file in Bison's repository
except where required. For example, do not use tabs to format C code. except where required. For example, do not use tabs to format C code.
@@ -57,6 +65,31 @@ Actually, Bison has legacy code that we should replace with gnulib modules
### Skeletons ### Skeletons
We try to use the "typical" coding style for each language. We try to use the "typical" coding style for each language.
#### CPP
We indent the CPP directives this way:
```
#if FOO
# if BAR
# define BAZ
# endif
#endif
```
Don't indent with leading spaces in the skeletons (it's ok in the grammar
files though, e.g., in `%code {...}` blocks).
On occasions, use `cppi -c` to see where we stand. We don't aim at full
correctness: depending `-d`, some bits can be in the *.c file, or the *.h
file within the double-inclusion cpp-guards. In that case, favor the case
of the *.h file, but don't waste time on this.
Don't hesitate to leave a comment on the `#endif` (e.g., `#endif /* FOO
*/`), especially for long blocks.
There is no conistency on `! defined` vs. `!defined`. The day gnulib
decides, we'll follow them.
#### C/C++ #### C/C++
Follow the GNU Coding Standards. Follow the GNU Coding Standards.
@@ -370,6 +403,12 @@ again, since some early failures may stop latter tests from being run. Yet
at some point, you'll have to fix remaining issues by hand... at some point, you'll have to fix remaining issues by hand...
## Running Java parsers
Use the `javaexec.sh` script. For instance to run the parser of test case
504:
$ sh ./_build/javaexec.sh -cp ./_build/tests/testsuite.dir/504 Calc
## make maintainer-check-valgrind ## make maintainer-check-valgrind
This target uses valgrind both to check bison, and the generated parsers. This target uses valgrind both to check bison, and the generated parsers.
+4
View File
@@ -20,6 +20,7 @@ Anthony Heading [email protected]
Antonio Silva Correia [email protected] Antonio Silva Correia [email protected]
Arnold Robbins [email protected] Arnold Robbins [email protected]
Art Haas [email protected] Art Haas [email protected]
Arthur Schwarz [email protected]
Askar Safin [email protected] Askar Safin [email protected]
Balázs Scheidler [email protected] Balázs Scheidler [email protected]
Baron Schwartz [email protected] Baron Schwartz [email protected]
@@ -57,6 +58,7 @@ Derek M. Jones [email protected]
Di-an Jan [email protected] Di-an Jan [email protected]
Dick Streefland [email protected] Dick Streefland [email protected]
Didier Godefroy [email protected] Didier Godefroy [email protected]
Don Macpherson [email protected]
Efi Fogel [email protected] Efi Fogel [email protected]
Enrico Scholz [email protected] Enrico Scholz [email protected]
Eric Blake [email protected] Eric Blake [email protected]
@@ -154,11 +156,13 @@ Petr Machata [email protected]
Pho [email protected] Pho [email protected]
Piotr Gackiewicz [email protected] Piotr Gackiewicz [email protected]
Piotr Marcińczyk [email protected] Piotr Marcińczyk [email protected]
Pramod Kumbhar [email protected]
Quentin Hocquet [email protected] Quentin Hocquet [email protected]
Quoc Peyrot [email protected] Quoc Peyrot [email protected]
R Blake [email protected] R Blake [email protected]
Raja R Harinath [email protected] Raja R Harinath [email protected]
Ralf Wildenhues [email protected] Ralf Wildenhues [email protected]
Ryan [email protected]
Rich Wilson [email protected] Rich Wilson [email protected]
Richard Stallman [email protected] Richard Stallman [email protected]
Rici Lake [email protected] Rici Lake [email protected]
+115 -32
View File
@@ -1,4 +1,15 @@
* Bison 3.6 * Bison 3.7
** Bistromathic
- Hitting tab on a line with a syntax error is ugly
- Be robust to existing ~/.inputrc
- How about not evaluating incomplete lines when the text is not finished
(as shells do).
** Doc
*** api.header.include
** 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
@@ -7,6 +18,10 @@
- is there a migration path that would allow to use TokenKinds in - is there a migration path that would allow to use TokenKinds in
yylex? yylex?
- define the tokens as an enum too.
- promote YYEOF rather than EOF.
*** D *** D
- is there a way to attach yysymbol_name to the enum itself? As we did - is there a way to attach yysymbol_name to the enum itself? As we did
in Java. in Java.
@@ -14,17 +29,37 @@
- It would be better to have TokenKind as return value. Can we use - It would be better to have TokenKind as return value. Can we use
reflection to support both output types? reflection to support both output types?
** Documentation ** YYerror
- YYERRCODE, YYUNDEF, YYEOF https://git.savannah.gnu.org/gitweb/?p=gettext.git;a=blob;f=gettext-runtime/intl/plural.y;h=a712255af4f2f739c93336d4ff6556d932a426a5;hb=HEAD
- YYERRCODE and translation
should be updated to not use YYERRCODE. Returning an undef token is good
enough.
** Java ** Java
*** Examples
Have an example with a push parser. Use autocompletion in that case.
*** calc.at *** calc.at
Stop hard-coding "Calc". Adjust local.at (look for FIXME). Stop hard-coding "Calc". Adjust local.at (look for FIXME).
** Counter example generation
See https://github.com/akimd/bison/pull/15.
** Clean up
Rename user_token_number for tokens as "code". It's not a "user number",
it's the token code, and the user can control it, but this code always
exists.
See also USER_NUMBER_UNDEFINED and NUMBER_UNDEFINED.
Rename endtoken as eoftoken.
Also do it in data/skeletons.
Don't rename in Bison 3.6 (it would be logical to do so) because that
would probably create many conflicts in Vincent's work (see previous point).
** A dev warning for b4_
Maybe we should check for m4_ and b4_ leaking out of the m4 processing, as
Autoconf does. It would have caught overquotation issues.
** 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
generates tons of white space in the page, and may contribute to bad page generates tons of white space in the page, and may contribute to bad page
@@ -35,7 +70,7 @@ token vs terminal, variable vs non terminal.
** api.token.raw ** api.token.raw
The YYUNDEFTOK could be assigned a semantic value so that yyerror could be The YYUNDEFTOK could be assigned a semantic value so that yyerror could be
used to report invalid lexemes. See also the item "$undefined" below. used to report invalid lexemes.
** push parsers ** push parsers
Consider deprecating impure push parsers. They add a lot of complexity, for Consider deprecating impure push parsers. They add a lot of complexity, for
@@ -43,21 +78,74 @@ a bad feature. On the other hand, that would make it much harder to sit
push parsers on top of pull parser. Which is currently not relevant, since push parsers on top of pull parser. Which is currently not relevant, since
push parsers are measurably slower. push parsers are measurably slower.
* Bison 3.7 ** %define parse.error formatted
** Counter example generation How about pushing bistromathics' yyreport_syntax_error as another standard
See https://github.com/akimd/bison/pull/15. way to generate the error message, and leave to the user the task of
providing the message formats? Currently in bistro, it reads:
** Clean up const char *
Rename user_token_number for tokens as "code". It's not a "user number", error_format_string (int argc)
it's the token code, and the user can control it, but this code always {
exists. switch (argc)
{
default: /* Avoid compiler warnings. */
case 0: return _("%@: syntax error");
case 1: return _("%@: syntax error: unexpected %u");
// TRANSLATORS: '%@' is a location in a file, '%u' is an
// "unexpected token", and '%0e', '%1e'... are expected tokens
// at this point.
//
// For instance on the expression "1 + * 2", you'd get
//
// 1.5: syntax error: expected - or ( or number or function or variable before *
case 2: return _("%@: syntax error: expected %0e before %u");
case 3: return _("%@: syntax error: expected %0e or %1e before %u");
case 4: return _("%@: syntax error: expected %0e or %1e or %2e before %u");
case 5: return _("%@: syntax error: expected %0e or %1e or %2e or %3e before %u");
case 6: return _("%@: syntax error: expected %0e or %1e or %2e or %3e or %4e before %u");
case 7: return _("%@: syntax error: expected %0e or %1e or %2e or %3e or %4e or %5e before %u");
case 8: return _("%@: syntax error: expected %0e or %1e or %2e or %3e or %4e or %5e or %6e before %u");
}
}
Rename endtoken as eoftoken. The message would have to be generated in a string, and pushed to yyerror.
Which will be a pain in the neck in yacc.c.
Also do it in data/skeletons. If we want to do that, we should think very carefully about the syntax of
the format string.
Don't rename in Bison 3.6 (it would be logical to do so) because that ** yyclearin does not invoke the lookahead token's %destructor
would probably create many conflicts in Vincent's work (see previous point). https://lists.gnu.org/r/bug-bison/2018-02/msg00000.html
Rici:
> Modifying yyclearin so that it calls yydestruct seems like the simplest
> solution to this issue, but it is conceivable that such a change would
> break programs which already perform some kind of workaround in order to
> destruct the lookahead symbol. So it might be necessary to use some kind of
> compatibility %define, or to create a new replacement macro with a
> different name such as yydiscardin.
>
> At a minimum, the fact that yyclearin does not invoke the %destructor
> should be highlighted in the documentation, since it is not at all obvious.
** Issues in i18n
Les catégories d'avertissements incluent :
conflicts-sr conflits S/R (activé par défaut)
conflicts-rr conflits R/R (activé par défaut)
dangling-alias l'alias chaîne n'est pas attaché à un symbole
deprecated construction obsolète
empty-rule règle vide sans %empty
midrule-values valeurs de règle intermédiaire non définies ou inutilisées
precedence priorité et associativité inutiles
yacc incompatibilités avec POSIX Yacc
other tous les autres avertissements (activé par défaut)
all tous les avertissements sauf « dangling-alias » et « yacc »
no-CATEGORY désactiver les avertissements dans CATEGORIE
none désactiver tous les avertissements
error[=CATEGORY] traiter les avertissements comme des erreurs
Line -1 and -3 should mention CATEGORIE, not CATEGORY.
* Bison 3.8 * Bison 3.8
** Unit rules / Injection rules (Akim Demaille) ** Unit rules / Injection rules (Akim Demaille)
@@ -133,10 +221,10 @@ define it to the same type as the C ptrdiff_t type.
* Completion * Completion
Several features are not available in all the backends. Several features are not available in all the backends.
- push parsers: glr.c, glr.cc, lalr1.cc - lac: D, Java (easy)
- lac: D, Java - push parsers: glr.c, glr.cc, lalr1.cc (not very difficult)
- glr: D, Java - token constructors: Java, C, D (a bit difficult)
- token constructors: Java, C, D - glr: D, Java (super difficult)
* Bugs * Bugs
** Autotest has quotation issues ** Autotest has quotation issues
@@ -340,8 +428,12 @@ LORIA, INRIA Nancy - Grand Est, Nancy, France
** More languages? ** More languages?
Well, only if there is really some demand for it. Well, only if there is really some demand for it.
*** PHP
https://github.com/scfc/bison-php/blob/master/data/lalr1.php https://github.com/scfc/bison-php/blob/master/data/lalr1.php
*** Python
https://lists.gnu.org/r/bison-patches/2013-09/msg00000.html and following
** Multiple start symbols ** Multiple start symbols
Would be very useful when parsing closely related languages. The idea is to Would be very useful when parsing closely related languages. The idea is to
declare several start symbols, for instance declare several start symbols, for instance
@@ -460,15 +552,6 @@ move to partial orders (sounds like series/parallel orders to me).
This is a prerequisite for modules. This is a prerequisite for modules.
* $undefined
From Hans:
- If the Bison generated parser experiences an undefined number in the
character range, that character is written out in diagnostic messages, an
addition to the $undefined value.
Suggest: Change the name $undefined to undefined; looks better in outputs.
* Pre and post actions. * Pre and post actions.
From: Florian Krohm <[email protected]> From: Florian Krohm <[email protected]>
Subject: YYACT_EPILOGUE Subject: YYACT_EPILOGUE
+7
View File
@@ -73,6 +73,11 @@ def diff_to_re(match):
is_diff = True is_diff = True
to.append(l) to.append(l)
if is_diff: if is_diff:
# Do not run s//SOMETHING/g (with an emty pattern), that won't
# work well...
if frm == []:
trace("no from for", match.group(1))
return
frm = "\n".join(frm) frm = "\n".join(frm)
to = "\n".join(to) to = "\n".join(to)
subst[frm] = to subst[frm] = to
@@ -112,4 +117,6 @@ def process(logfile):
for logfile in args.logs: for logfile in args.logs:
trace("FILE:", logfile) trace("FILE:", logfile)
if os.path.isdir(logfile):
logfile = os.path.join(logfile, 'testsuite.log')
process(logfile) process(logfile)
+2 -2
View File
@@ -51,7 +51,7 @@ gnulib_dir = $(srcdir)/gnulib
bootstrap-tools = autoconf,automake,flex,gettext,gnulib bootstrap-tools = autoconf,automake,flex,gettext,gnulib
announcement_Cc_ = \ announcement_Cc_ = \
[email protected], [email protected], bison-patches@gnu.org, \ [email protected], bison-announce@gnu.org, \
[email protected] [email protected]
update-copyright: update-b4-copyright update-package-copyright-year update-copyright: update-b4-copyright update-package-copyright-year
@@ -156,7 +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$$ \
po_check=^(examples|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$$ \
prohibit_always-defined_macros=^data/skeletons/yacc.c$$ \ prohibit_always-defined_macros=^data/skeletons/yacc.c$$ \
+14 -7
View File
@@ -36,10 +36,8 @@ AC_DEFINE_UNQUOTED([PACKAGE_COPYRIGHT_YEAR], [$PACKAGE_COPYRIGHT_YEAR],
AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
# We use Automake 1.14's %D% and %C%.
#
# When we move to Automake 1.16, simplify examples/c/reccalc/local.mk. # When we move to Automake 1.16, simplify examples/c/reccalc/local.mk.
# Our CI runs on Xenial, which has only Automake 1.15. # Our CI build the packages on Bionic, which has only Automake 1.15.
# #
# We want gnits strictness only when rolling a stable release. For # We want gnits strictness only when rolling a stable release. For
# release candidates, we use version strings like 2.4.3_rc1, but gnits # release candidates, we use version strings like 2.4.3_rc1, but gnits
@@ -47,7 +45,7 @@ AC_CONFIG_MACRO_DIR([m4])
# releases, we want to be able run make dist without being required to # releases, we want to be able run make dist without being required to
# add a bogus NEWS entry. In that case, the version string # add a bogus NEWS entry. In that case, the version string
# automatically contains a dash, which we also let disable gnits. # automatically contains a dash, which we also let disable gnits.
AM_INIT_AUTOMAKE([1.14 dist-xz nostdinc AM_INIT_AUTOMAKE([1.15 dist-lzip dist-xz nostdinc
color-tests parallel-tests color-tests parallel-tests
silent-rules] silent-rules]
m4_bmatch(m4_defn([AC_PACKAGE_VERSION]), [[-_]], m4_bmatch(m4_defn([AC_PACKAGE_VERSION]), [[-_]],
@@ -137,7 +135,9 @@ if test "$enable_gcc_warnings" = yes; then
-Wpointer-arith -Wshadow -Wpointer-arith -Wshadow
-Wwrite-strings -Wwrite-strings
-wr188 -wr2259 -wr3179' -wr188 -wr2259 -wr3179'
warn_c='-Wbad-function-cast -Wstrict-prototypes' warn_c='-Wbad-function-cast
-Wmissing-prototypes
-Wstrict-prototypes'
warn_cxx='-Wextra-semi -Wnoexcept -Wold-style-cast -Wundefined-func-template warn_cxx='-Wextra-semi -Wnoexcept -Wold-style-cast -Wundefined-func-template
-Wweak-vtables' -Wweak-vtables'
# Warnings for the test suite only. # Warnings for the test suite only.
@@ -261,9 +261,9 @@ if ! "$LEX_IS_FLEX" || test "X$LEX" = X:; then
AC_MSG_WARN([bypassing lex because flex is required]) AC_MSG_WARN([bypassing lex because flex is required])
LEX=: LEX=:
fi fi
AM_CONDITIONAL([FLEX_WORKS], [$LEX_IS_FLEX]) AM_CONDITIONAL([FLEX_WORKS], [$LEX_IS_FLEX && $FLEX_SUPPORTS_HEADER_OPT])
AM_CONDITIONAL([FLEX_CXX_WORKS], AM_CONDITIONAL([FLEX_CXX_WORKS],
[$LEX_IS_FLEX && test $bison_cv_cxx_works = yes]) [$LEX_IS_FLEX && $FLEX_SUPPORTS_HEADER_OPT && test $bison_cv_cxx_works = yes])
AC_PROG_YACC AC_PROG_YACC
AC_PROG_RANLIB AC_PROG_RANLIB
AC_PROG_GNU_M4 AC_PROG_GNU_M4
@@ -332,6 +332,13 @@ AC_MSG_RESULT([$suppfile])
# Whether we cannot run the compiled bison. # Whether we cannot run the compiled bison.
AM_CONDITIONAL([CROSS_COMPILING], [test "$cross_compiling" = yes]) AM_CONDITIONAL([CROSS_COMPILING], [test "$cross_compiling" = yes])
# Build bistromathic if we have the lib and both readline/readline.h
# and readline/history.h.
AM_CONDITIONAL([ENABLE_BISTROMATHIC],
[test "$gl_cv_lib_readline" != no &&
test "$ac_cv_header_readline_readline_h" = yes &&
test "$ac_cv_header_readline_history_h" = yes])
AM_MISSING_PROG([AUTOM4TE], [autom4te]) AM_MISSING_PROG([AUTOM4TE], [autom4te])
# Needed by tests/atlocal.in. # Needed by tests/atlocal.in.
AC_SUBST([GCC]) AC_SUBST([GCC])
+1
View File
@@ -34,6 +34,7 @@ dist_skeletons_DATA = \
data/skeletons/lalr1.java \ data/skeletons/lalr1.java \
data/skeletons/location.cc \ data/skeletons/location.cc \
data/skeletons/stack.hh \ data/skeletons/stack.hh \
data/skeletons/traceon.m4 \
data/skeletons/variant.hh \ data/skeletons/variant.hh \
data/skeletons/yacc.c data/skeletons/yacc.c
+26 -3
View File
@@ -19,6 +19,27 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# m4_gsub(STRING, RE1, SUBST1, RE2, SUBST2, ...)
# ----------------------------------------------
# m4 equivalent of
#
# $_ = STRING;
# s/RE1/SUBST1/g;
# s/RE2/SUBST2/g;
# ...
#
# Really similar to m4_bpatsubsts, but behaves properly with quotes.
# See m4.at's "Generating Comments". Super inelegant, but so far, I
# did not find any better solution.
m4_define([b4_gsub],
[m4_bpatsubst(m4_bpatsubst(m4_bpatsubst([[[[$1]]]],
[$2], [$3]),
[$4], [$5]),
[$6], [$7])])
## ---------------- ## ## ---------------- ##
## Identification. ## ## Identification. ##
## ---------------- ## ## ---------------- ##
@@ -72,8 +93,9 @@ version 2.2 of Bison.])
# ------------- # -------------
# Issue a warning about private implementation details. # Issue a warning about private implementation details.
m4_define([b4_disclaimer], m4_define([b4_disclaimer],
[b4_comment([Undocumented macros, especially those whose name start with YY_, [b4_comment([DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
are private implementation details. Do not rely on them.]) especially those whose name start with YY_ or yy_. They are
private implementation details that can be changed or removed.])
]) ])
@@ -369,6 +391,7 @@ m4_define([b4_$3_if],
# Expand IF-TRUE, if FLAG is true, IF-FALSE otherwise. # Expand IF-TRUE, if FLAG is true, IF-FALSE otherwise.
b4_define_flag_if([defines]) # Whether headers are requested. b4_define_flag_if([defines]) # Whether headers are requested.
b4_define_flag_if([glr]) # Whether a GLR parser is requested. b4_define_flag_if([glr]) # Whether a GLR parser is requested.
b4_define_flag_if([has_translations]) # Whether some tokens are internationalized.
b4_define_flag_if([nondeterministic]) # Whether conflicts should be handled. b4_define_flag_if([nondeterministic]) # Whether conflicts should be handled.
b4_define_flag_if([token_table]) # Whether yytoken_table is demanded. b4_define_flag_if([token_table]) # Whether yytoken_table is demanded.
b4_define_flag_if([yacc]) # Whether POSIX Yacc is emulated. b4_define_flag_if([yacc]) # Whether POSIX Yacc is emulated.
@@ -425,7 +448,7 @@ m4_define([b4_symbol_kind],
m4_case([$1], m4_case([$1],
[-2], [[YYEMPTY]], [-2], [[YYEMPTY]],
[0], [[YYEOF]], [0], [[YYEOF]],
[1], [[YYERROR]], [1], [[YYerror]],
[2], [[YYUNDEF]], [2], [[YYUNDEF]],
[m4_case(b4_symbol([$1], [tag]), [m4_case(b4_symbol([$1], [tag]),
[$accept], [[YYACCEPT]], [$accept], [[YYACCEPT]],
+63 -28
View File
@@ -259,14 +259,14 @@ m4_define([b4_public_types_declare],
struct token struct token
{ {
]b4_token_enums[ ]b4_token_enums[
/// Backward compatibility alias. /// Backward compatibility alias (Bison 3.6).
typedef token_kind_type yytokentype; typedef token_kind_type yytokentype;
}; };
/// Token kind, as returned by yylex. /// Token kind, as returned by yylex.
typedef token::yytokentype token_kind_type; typedef token::yytokentype token_kind_type;
/// Backward compatibility alias. /// Backward compatibility alias (Bison 3.6).
typedef token_kind_type token_type; typedef token_kind_type token_type;
/// Symbol kinds. /// Symbol kinds.
@@ -352,12 +352,35 @@ m4_define([b4_symbol_type_define],
break; break;
} }
// Type destructor. // Value type destructor.
]b4_symbol_variant([[yykind]], [[value]], [[template destroy]])])[ ]b4_symbol_variant([[yykind]], [[value]], [[template destroy]])])[
Base::clear (); Base::clear ();
} }
/// Backward compatibility. ]b4_parse_error_bmatch(
[custom\|detailed],
[[ /// The user-facing name of this symbol.
const char *name () const YY_NOEXCEPT
{
return ]b4_parser_class[::symbol_name (this->kind ());
}]],
[simple],
[[#if ]b4_api_PREFIX[DEBUG || ]b4_token_table_flag[
/// The user-facing name of this symbol.
const char *name () const YY_NOEXCEPT
{
return ]b4_parser_class[::symbol_name (this->kind ());
}
#endif // #if ]b4_api_PREFIX[DEBUG || ]b4_token_table_flag[
]],
[verbose],
[[ /// The user-facing name of this symbol.
std::string name () const YY_NOEXCEPT
{
return ]b4_parser_class[::symbol_name (this->kind ());
}]])[
/// Backward compatibility (Bison 3.6).
symbol_kind_type type_get () const YY_NOEXCEPT; symbol_kind_type type_get () const YY_NOEXCEPT;
/// Whether empty. /// Whether empty.
@@ -380,45 +403,51 @@ m4_define([b4_symbol_type_define],
}; };
/// Type access provider for token (enum) based symbols. /// Type access provider for token (enum) based symbols.
struct by_type struct by_kind
{ {
/// Default constructor. /// Default constructor.
by_type (); by_kind ();
#if 201103L <= YY_CPLUSPLUS #if 201103L <= YY_CPLUSPLUS
/// Move constructor. /// Move constructor.
by_type (by_type&& that); by_kind (by_kind&& that);
#endif #endif
/// Copy constructor. /// Copy constructor.
by_type (const by_type& that); by_kind (const by_kind& that);
/// The symbol kind as needed by the constructor. /// The symbol kind as needed by the constructor.
typedef token_kind_type kind_type; typedef token_kind_type kind_type;
/// Constructor from (external) token numbers. /// Constructor from (external) token numbers.
by_type (kind_type t); by_kind (kind_type t);
/// Record that this symbol is empty. /// Record that this symbol is empty.
void clear (); void clear ();
/// Steal the symbol kind from \a that. /// Steal the symbol kind from \a that.
void move (by_type& that); void move (by_kind& that);
/// The (internal) type number (corresponding to \a type). /// The (internal) type number (corresponding to \a type).
/// \a empty when empty. /// \a empty when empty.
symbol_kind_type kind () const YY_NOEXCEPT; symbol_kind_type kind () const YY_NOEXCEPT;
/// Backward compatibility (Bison 3.6).
symbol_kind_type type_get () const YY_NOEXCEPT;
/// The symbol kind. /// The symbol kind.
/// \a ]b4_symbol_prefix[YYEMPTY when empty. /// \a ]b4_symbol_prefix[YYEMPTY when empty.
symbol_kind_type type; symbol_kind_type kind_;
}; };
/// Backward compatibility for a private implementation detail (Bison 3.6).
typedef by_kind by_type;
/// "External" symbols: returned by the scanner. /// "External" symbols: returned by the scanner.
struct symbol_type : basic_symbol<by_type> struct symbol_type : basic_symbol<by_kind>
{]b4_variant_if([[ {]b4_variant_if([[
/// Superclass. /// Superclass.
typedef basic_symbol<by_type> super_type; typedef basic_symbol<by_kind> super_type;
/// Empty symbol. /// Empty symbol.
symbol_type () {} symbol_type () {}
@@ -492,44 +521,50 @@ m4_define([b4_public_types_define],
location = YY_MOVE (s.location);])[ location = YY_MOVE (s.location);])[
} }
// by_type. // by_kind.
]b4_inline([$1])b4_parser_class[::by_type::by_type () ]b4_inline([$1])b4_parser_class[::by_kind::by_kind ()
: type (symbol_kind::]b4_symbol_prefix[YYEMPTY) : kind_ (symbol_kind::]b4_symbol_prefix[YYEMPTY)
{} {}
#if 201103L <= YY_CPLUSPLUS #if 201103L <= YY_CPLUSPLUS
]b4_inline([$1])b4_parser_class[::by_type::by_type (by_type&& that) ]b4_inline([$1])b4_parser_class[::by_kind::by_kind (by_kind&& that)
: type (that.type) : kind_ (that.kind_)
{ {
that.clear (); that.clear ();
} }
#endif #endif
]b4_inline([$1])b4_parser_class[::by_type::by_type (const by_type& that) ]b4_inline([$1])b4_parser_class[::by_kind::by_kind (const by_kind& that)
: type (that.type) : kind_ (that.kind_)
{} {}
]b4_inline([$1])b4_parser_class[::by_type::by_type (token_kind_type t) ]b4_inline([$1])b4_parser_class[::by_kind::by_kind (token_kind_type t)
: type (yytranslate_ (t)) : kind_ (yytranslate_ (t))
{} {}
]b4_inline([$1])[void ]b4_inline([$1])[void
]b4_parser_class[::by_type::clear () ]b4_parser_class[::by_kind::clear ()
{ {
type = symbol_kind::]b4_symbol_prefix[YYEMPTY; kind_ = symbol_kind::]b4_symbol_prefix[YYEMPTY;
} }
]b4_inline([$1])[void ]b4_inline([$1])[void
]b4_parser_class[::by_type::move (by_type& that) ]b4_parser_class[::by_kind::move (by_kind& that)
{ {
type = that.type; kind_ = that.kind_;
that.clear (); that.clear ();
} }
]b4_inline([$1])[]b4_parser_class[::symbol_kind_type ]b4_inline([$1])[]b4_parser_class[::symbol_kind_type
]b4_parser_class[::by_type::kind () const YY_NOEXCEPT ]b4_parser_class[::by_kind::kind () const YY_NOEXCEPT
{ {
return type; return kind_;
}
]b4_inline([$1])[]b4_parser_class[::symbol_kind_type
]b4_parser_class[::by_kind::type_get () const YY_NOEXCEPT
{
return this->kind ();
} }
]]) ]])
+7 -1
View File
@@ -17,15 +17,21 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# _b4_comment(TEXT, OPEN, CONTINUE, END) # _b4_comment(TEXT, OPEN, CONTINUE, END)
# -------------------------------------- # --------------------------------------
# Put TEXT in comment. Avoid trailing spaces: don't indent empty lines. # Put TEXT in comment. Avoid trailing spaces: don't indent empty lines.
# Avoid adding indentation to the first line, as the indentation comes # Avoid adding indentation to the first line, as the indentation comes
# from OPEN. That's why we don't patsubst([$1], [^\(.\)], [ \1]). # from OPEN. That's why we don't patsubst([$1], [^\(.\)], [ \1]).
# Turn "*/" in TEXT into "* /" so that we don't unexpectedly close
# the comments before its end.
# #
# Prefix all the output lines with PREFIX. # Prefix all the output lines with PREFIX.
m4_define([_b4_comment], m4_define([_b4_comment],
[$2[]m4_bpatsubst(m4_expand([[$1]]), [ [$2[]b4_gsub(m4_expand([$1]),
[[*]/], [*\\/],
[/[*]], [/\\*],
[
\(.\)], [ \(.\)], [
$3\1])$4]) $3\1])$4])
+60 -12
View File
@@ -205,7 +205,11 @@ m4_define([b4_c99_int_type],
# Define private types suitable for holding small integers in C99 or later. # Define private types suitable for holding small integers in C99 or later.
m4_define([b4_c99_int_type_define], m4_define([b4_c99_int_type_define],
[m4_copy_force([b4_c99_int_type], [b4_int_type])dnl [m4_copy_force([b4_c99_int_type], [b4_int_type])dnl
[/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure [#ifdef short
# undef short
#endif
/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure
<limits.h> and (if available) <stdint.h> are included <limits.h> and (if available) <stdint.h> are included
so that the code can choose integer types of a good width. */ so that the code can choose integer types of a good width. */
@@ -261,6 +265,50 @@ typedef int yytype_uint16;
#endif]]) #endif]])
# b4_sizes_types_define
# ---------------------
# Define YYPTRDIFF_T/YYPTRDIFF_MAXIMUM, YYSIZE_T/YYSIZE_MAXIMUM,
# and YYSIZEOF.
m4_define([b4_sizes_types_define],
[[#ifndef YYPTRDIFF_T
# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__
# define YYPTRDIFF_T __PTRDIFF_TYPE__
# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__
# elif defined PTRDIFF_MAX
# ifndef ptrdiff_t
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# endif
# define YYPTRDIFF_T ptrdiff_t
# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX
# else
# define YYPTRDIFF_T long
# define YYPTRDIFF_MAXIMUM LONG_MAX
# endif
#endif
#ifndef YYSIZE_T
# ifdef __SIZE_TYPE__
# define YYSIZE_T __SIZE_TYPE__
# elif defined size_t
# define YYSIZE_T size_t
# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# define YYSIZE_T size_t
# else
# define YYSIZE_T unsigned
# endif
#endif
#define YYSIZE_MAXIMUM \
YY_CAST (YYPTRDIFF_T, \
(YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \
? YYPTRDIFF_MAXIMUM \
: YY_CAST (YYSIZE_T, -1)))
#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X))
]])
# b4_int_type_for(NAME) # b4_int_type_for(NAME)
# --------------------- # ---------------------
# Return a narrow int type able to handle numbers ranging from # Return a narrow int type able to handle numbers ranging from
@@ -439,7 +487,7 @@ m4_define([b4_symbol(-2, tag)], [[No symbol.]])
m4_if(b4_symbol(0, id), [YYEOF], m4_if(b4_symbol(0, id), [YYEOF],
[m4_define([b4_symbol(0, id)], [b4_api_PREFIX[][EOF]])]) [m4_define([b4_symbol(0, id)], [b4_api_PREFIX[][EOF]])])
m4_define([b4_symbol(1, id)], [b4_api_PREFIX[][ERRCODE]]) m4_define([b4_symbol(1, id)], [b4_api_PREFIX[][error]])
m4_define([b4_symbol(2, id)], [b4_api_PREFIX[][UNDEF]]) m4_define([b4_symbol(2, id)], [b4_api_PREFIX[][UNDEF]])
@@ -965,8 +1013,8 @@ m4_define([b4_yy_location_print_define],
This macro was not mandated originally: define only if we know This macro was not mandated originally: define only if we know
we won't break user code: when these are the locations we know. */ we won't break user code: when these are the locations we know. */
#ifndef YY_LOCATION_PRINT # ifndef YY_LOCATION_PRINT
# if defined ]b4_api_PREFIX[LTYPE_IS_TRIVIAL && ]b4_api_PREFIX[LTYPE_IS_TRIVIAL # if defined ]b4_api_PREFIX[LTYPE_IS_TRIVIAL && ]b4_api_PREFIX[LTYPE_IS_TRIVIAL
/* Print *YYLOCP on YYO. Private, do not rely on its existence. */ /* Print *YYLOCP on YYO. Private, do not rely on its existence. */
@@ -996,17 +1044,17 @@ yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp)
return res; return res;
} }
# define YY_LOCATION_PRINT(File, Loc) \ # define YY_LOCATION_PRINT(File, Loc) \
yy_location_print_ (File, &(Loc)) yy_location_print_ (File, &(Loc))
# else # else
# define YY_LOCATION_PRINT(File, Loc) ((void) 0) # define YY_LOCATION_PRINT(File, Loc) ((void) 0)
# endif # endif
#endif]], # endif /* !defined YY_LOCATION_PRINT */]],
[[/* This macro is provided for backward compatibility. */ [[/* This macro is provided for backward compatibility. */
#ifndef YY_LOCATION_PRINT # ifndef YY_LOCATION_PRINT
# define YY_LOCATION_PRINT(File, Loc) ((void) 0) # define YY_LOCATION_PRINT(File, Loc) ((void) 0)
#endif]]) # endif]])
]) ])
# b4_yyloc_default # b4_yyloc_default
+85 -76
View File
@@ -249,6 +249,7 @@ static YYLTYPE yyloc_default][]b4_yyloc_default;])[
#include <string.h> #include <string.h>
]b4_c99_int_type_define[ ]b4_c99_int_type_define[
]b4_sizes_types_define[
#ifndef YY_ #ifndef YY_
# if defined YYENABLE_NLS && YYENABLE_NLS # if defined YYENABLE_NLS && YYENABLE_NLS
@@ -261,6 +262,11 @@ static YYLTYPE yyloc_default][]b4_yyloc_default;])[
# define YY_(Msgid) Msgid # define YY_(Msgid) Msgid
# endif # endif
#endif #endif
]b4_has_translations_if([
#ifndef N_
# define N_(Msgid) Msgid
#endif
])[
#ifndef YYFREE #ifndef YYFREE
# define YYFREE free # define YYFREE free
@@ -272,9 +278,6 @@ static YYLTYPE yyloc_default][]b4_yyloc_default;])[
# define YYREALLOC realloc # define YYREALLOC realloc
#endif #endif
#define YYSIZEMAX \
(PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : YY_CAST (ptrdiff_t, SIZE_MAX))
#ifdef __cplusplus #ifdef __cplusplus
typedef bool yybool; typedef bool yybool;
# define yytrue true # define yytrue true
@@ -329,10 +332,7 @@ static YYLTYPE yyloc_default][]b4_yyloc_default;])[
#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 number (for yychar). */
#define YYMAXUTOK ]b4_user_token_number_max[]b4_glr_cc_if([[ #define YYMAXUTOK ]b4_user_token_number_max[
/* YYFAULTYTOK -- Token number (for yychar) that denotes a
syntax_error thrown from the scanner. */
#define YYFAULTYTOK (YYMAXUTOK + 1)]])[
/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM /* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
as returned by yylex, with out-of-bounds checking. */ as returned by yylex, with out-of-bounds checking. */
@@ -505,7 +505,7 @@ struct yyGLRState {
/** Preceding state in this stack */ /** Preceding state in this stack */
yyGLRState* yypred; yyGLRState* yypred;
/** Source position of the last token produced by my symbol */ /** Source position of the last token produced by my symbol */
ptrdiff_t yyposn; YYPTRDIFF_T yyposn;
union { union {
/** First in a chain of alternative reductions producing the /** First in a chain of alternative reductions producing the
* nonterminal corresponding to this state, threaded through * nonterminal corresponding to this state, threaded through
@@ -525,8 +525,8 @@ struct yyGLRStateSet {
* operation, yylookaheadNeeds[0] is not maintained since it would merely * operation, yylookaheadNeeds[0] is not maintained since it would merely
* duplicate yychar != ]b4_symbol(-2, id)[. */ * duplicate yychar != ]b4_symbol(-2, id)[. */
yybool* yylookaheadNeeds; yybool* yylookaheadNeeds;
ptrdiff_t yysize; YYPTRDIFF_T yysize;
ptrdiff_t yycapacity; YYPTRDIFF_T yycapacity;
}; };
struct yySemanticOption { struct yySemanticOption {
@@ -566,7 +566,7 @@ struct yyGLRStack {
YYJMP_BUF yyexception_buffer; YYJMP_BUF yyexception_buffer;
yyGLRStackItem* yyitems; yyGLRStackItem* yyitems;
yyGLRStackItem* yynextFree; yyGLRStackItem* yynextFree;
ptrdiff_t yyspaceLeft; YYPTRDIFF_T yyspaceLeft;
yyGLRState* yysplitPoint; yyGLRState* yysplitPoint;
yyGLRState* yylastDeleted; yyGLRState* yylastDeleted;
yyGLRStateSet yytops; yyGLRStateSet yytops;
@@ -621,8 +621,8 @@ yysymbol_name (yysymbol_kind_t yysymbol)
static const char *const yy_sname[] = static const char *const yy_sname[] =
{ {
]b4_symbol_names[ ]b4_symbol_names[
};]m4_ifdef([b4_translatable], [[ };]b4_has_translations_if([[
/* YYTRANSLATABLE[SYMBOL-NUM] -- Whether YYTNAME[SYMBOL-NUM] is /* YYTRANSLATABLE[SYMBOL-NUM] -- Whether YY_SNAME[SYMBOL-NUM] is
internationalizable. */ internationalizable. */
static ]b4_int_type_for([b4_translatable])[ yytranslatable[] = static ]b4_int_type_for([b4_translatable])[ yytranslatable[] =
{ {
@@ -664,12 +664,12 @@ yysymbol_name (yysymbol_kind_t yysymbol)
]b4_yy_symbol_print_define[ ]b4_yy_symbol_print_define[
# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ # define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \
do { \ do { \
if (yydebug) \ if (yydebug) \
{ \ { \
YY_FPRINTF ((stderr, "%s ", Title)); \ YY_FPRINTF ((stderr, "%s ", Title)); \
yy_symbol_print (stderr, Type, Value]b4_locuser_args([Location])[); \ yy_symbol_print (stderr, Kind, Value]b4_locuser_args([Location])[); \
YY_FPRINTF ((stderr, "\n")); \ YY_FPRINTF ((stderr, "\n")); \
} \ } \
} while (0) } while (0)
@@ -678,7 +678,7 @@ yysymbol_name (yysymbol_kind_t yysymbol)
multiple parsers can coexist. */ multiple parsers can coexist. */
int yydebug; int yydebug;
static void yypstack (yyGLRStack* yystackp, ptrdiff_t yyk) static void yypstack (yyGLRStack* yystackp, YYPTRDIFF_T yyk)
YY_ATTRIBUTE_UNUSED; YY_ATTRIBUTE_UNUSED;
static void yypdumpstack (yyGLRStack* yystackp) static void yypdumpstack (yyGLRStack* yystackp)
YY_ATTRIBUTE_UNUSED; YY_ATTRIBUTE_UNUSED;
@@ -686,7 +686,7 @@ static void yypdumpstack (yyGLRStack* yystackp)
#else /* !]b4_api_PREFIX[DEBUG */ #else /* !]b4_api_PREFIX[DEBUG */
# define YY_DPRINTF(Args) do {} while (yyfalse) # define YY_DPRINTF(Args) do {} while (yyfalse)
# define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_SYMBOL_PRINT(Title, Kind, Value, Location)
#endif /* !]b4_api_PREFIX[DEBUG */ #endif /* !]b4_api_PREFIX[DEBUG */
@@ -694,7 +694,7 @@ static void yypdumpstack (yyGLRStack* yystackp)
[simple], [simple],
[[]], [[]],
[[#ifndef yystrlen [[#ifndef yystrlen
# define yystrlen(S) (YY_CAST (ptrdiff_t, strlen (S))) # define yystrlen(S) (YY_CAST (YYPTRDIFF_T, strlen (S)))
#endif #endif
]b4_parse_error_bmatch( ]b4_parse_error_bmatch(
@@ -729,12 +729,12 @@ yystpcpy (char *yydest, const char *yysrc)
backslash-backslash). YYSTR is taken from yytname. If YYRES is backslash-backslash). YYSTR is taken from yytname. If YYRES is
null, do not copy; instead, return the length of what the result null, do not copy; instead, return the length of what the result
would have been. */ would have been. */
static ptrdiff_t static YYPTRDIFF_T
yytnamerr (char *yyres, const char *yystr) yytnamerr (char *yyres, const char *yystr)
{ {
if (*yystr == '"') if (*yystr == '"')
{ {
ptrdiff_t yyn = 0; YYPTRDIFF_T yyn = 0;
char const *yyp = yystr; char const *yyp = yystr;
for (;;) for (;;)
@@ -825,7 +825,7 @@ yygetToken (int *yycharp][]b4_pure_if([, yyGLRStack* yystackp])[]b4_user_formals
// Map errors caught in the scanner to the undefined token, // Map errors caught in the scanner to the undefined token,
// so that error handling is started. However, record this // so that error handling is started. However, record this
// with this special value of yychar. // with this special value of yychar.
*yycharp = YYFAULTYTOK; *yycharp = ]b4_symbol(1, id)[;
} }
#endif // YY_EXCEPTIONS]], [[ #endif // YY_EXCEPTIONS]], [[
*yycharp = ]b4_lex[;]])[ *yycharp = ]b4_lex[;]])[
@@ -1030,8 +1030,14 @@ static inline int
yygetLRActions (yy_state_t yystate, yysymbol_kind_t yytoken, const short** yyconflicts) yygetLRActions (yy_state_t yystate, yysymbol_kind_t yytoken, const short** yyconflicts)
{ {
int yyindex = yypact[yystate] + yytoken; int yyindex = yypact[yystate] + yytoken;
if (yyisDefaultedState (yystate) if (yytoken == ]b4_symbol(1, kind)[)
|| yyindex < 0 || YYLAST < yyindex || yycheck[yyindex] != yytoken) {
// This is the error token.
*yyconflicts = yyconfl;
return 0;
}
else if (yyisDefaultedState (yystate)
|| yyindex < 0 || YYLAST < yyindex || yycheck[yyindex] != yytoken)
{ {
*yyconflicts = yyconfl; *yyconflicts = yyconfl;
return -yydefact[yystate]; return -yydefact[yystate];
@@ -1096,7 +1102,7 @@ yynewGLRStackItem (yyGLRStack* yystackp, yybool yyisState)
* alternative actions for YYSTATE. Assumes that YYRHS comes from * alternative actions for YYSTATE. Assumes that YYRHS comes from
* stack #YYK of *YYSTACKP. */ * stack #YYK of *YYSTACKP. */
static void static void
yyaddDeferredAction (yyGLRStack* yystackp, ptrdiff_t yyk, yyGLRState* yystate, yyaddDeferredAction (yyGLRStack* yystackp, YYPTRDIFF_T yyk, yyGLRState* yystate,
yyGLRState* yyrhs, yyRuleNum yyrule) yyGLRState* yyrhs, yyRuleNum yyrule)
{ {
yySemanticOption* yynewOption = yySemanticOption* yynewOption =
@@ -1128,14 +1134,14 @@ yyinitStateSet (yyGLRStateSet* yyset)
yyset->yycapacity = 16; yyset->yycapacity = 16;
yyset->yystates yyset->yystates
= YY_CAST (yyGLRState**, = YY_CAST (yyGLRState**,
YYMALLOC (YY_CAST (size_t, yyset->yycapacity) YYMALLOC (YY_CAST (YYSIZE_T, yyset->yycapacity)
* sizeof yyset->yystates[0])); * sizeof yyset->yystates[0]));
if (! yyset->yystates) if (! yyset->yystates)
return yyfalse; return yyfalse;
yyset->yystates[0] = YY_NULLPTR; yyset->yystates[0] = YY_NULLPTR;
yyset->yylookaheadNeeds yyset->yylookaheadNeeds
= YY_CAST (yybool*, = YY_CAST (yybool*,
YYMALLOC (YY_CAST (size_t, yyset->yycapacity) YYMALLOC (YY_CAST (YYSIZE_T, yyset->yycapacity)
* sizeof yyset->yylookaheadNeeds[0])); * sizeof yyset->yylookaheadNeeds[0]));
if (! yyset->yylookaheadNeeds) if (! yyset->yylookaheadNeeds)
{ {
@@ -1144,7 +1150,7 @@ yyinitStateSet (yyGLRStateSet* yyset)
} }
memset (yyset->yylookaheadNeeds, memset (yyset->yylookaheadNeeds,
0, 0,
YY_CAST (size_t, yyset->yycapacity) * sizeof yyset->yylookaheadNeeds[0]); YY_CAST (YYSIZE_T, yyset->yycapacity) * sizeof yyset->yylookaheadNeeds[0]);
return yytrue; return yytrue;
} }
@@ -1157,14 +1163,14 @@ static void yyfreeStateSet (yyGLRStateSet* yyset)
/** Initialize *YYSTACKP to a single empty stack, with total maximum /** Initialize *YYSTACKP to a single empty stack, with total maximum
* capacity for all stacks of YYSIZE. */ * capacity for all stacks of YYSIZE. */
static yybool static yybool
yyinitGLRStack (yyGLRStack* yystackp, ptrdiff_t yysize) yyinitGLRStack (yyGLRStack* yystackp, YYPTRDIFF_T yysize)
{ {
yystackp->yyerrState = 0; yystackp->yyerrState = 0;
yynerrs = 0; yynerrs = 0;
yystackp->yyspaceLeft = yysize; yystackp->yyspaceLeft = yysize;
yystackp->yyitems yystackp->yyitems
= YY_CAST (yyGLRStackItem*, = YY_CAST (yyGLRStackItem*,
YYMALLOC (YY_CAST (size_t, yysize) YYMALLOC (YY_CAST (YYSIZE_T, yysize)
* sizeof yystackp->yynextFree[0])); * sizeof yystackp->yynextFree[0]));
if (!yystackp->yyitems) if (!yystackp->yyitems)
return yyfalse; return yyfalse;
@@ -1190,9 +1196,9 @@ yyexpandGLRStack (yyGLRStack* yystackp)
{ {
yyGLRStackItem* yynewItems; yyGLRStackItem* yynewItems;
yyGLRStackItem* yyp0, *yyp1; yyGLRStackItem* yyp0, *yyp1;
ptrdiff_t yynewSize; YYPTRDIFF_T yynewSize;
ptrdiff_t yyn; YYPTRDIFF_T yyn;
ptrdiff_t yysize = yystackp->yynextFree - yystackp->yyitems; YYPTRDIFF_T yysize = yystackp->yynextFree - yystackp->yyitems;
if (YYMAXDEPTH - YYHEADROOM < yysize) if (YYMAXDEPTH - YYHEADROOM < yysize)
yyMemoryExhausted (yystackp); yyMemoryExhausted (yystackp);
yynewSize = 2*yysize; yynewSize = 2*yysize;
@@ -1200,7 +1206,7 @@ yyexpandGLRStack (yyGLRStack* yystackp)
yynewSize = YYMAXDEPTH; yynewSize = YYMAXDEPTH;
yynewItems yynewItems
= YY_CAST (yyGLRStackItem*, = YY_CAST (yyGLRStackItem*,
YYMALLOC (YY_CAST (size_t, yynewSize) YYMALLOC (YY_CAST (YYSIZE_T, yynewSize)
* sizeof yynewItems[0])); * sizeof yynewItems[0]));
if (! yynewItems) if (! yynewItems)
yyMemoryExhausted (yystackp); yyMemoryExhausted (yystackp);
@@ -1265,7 +1271,7 @@ yyupdateSplit (yyGLRStack* yystackp, yyGLRState* yys)
/** Invalidate stack #YYK in *YYSTACKP. */ /** Invalidate stack #YYK in *YYSTACKP. */
static inline void static inline void
yymarkStackDeleted (yyGLRStack* yystackp, ptrdiff_t yyk) yymarkStackDeleted (yyGLRStack* yystackp, YYPTRDIFF_T yyk)
{ {
if (yystackp->yytops.yystates[yyk] != YY_NULLPTR) if (yystackp->yytops.yystates[yyk] != YY_NULLPTR)
yystackp->yylastDeleted = yystackp->yytops.yystates[yyk]; yystackp->yylastDeleted = yystackp->yytops.yystates[yyk];
@@ -1289,7 +1295,7 @@ yyundeleteLastStack (yyGLRStack* yystackp)
static inline void static inline void
yyremoveDeletes (yyGLRStack* yystackp) yyremoveDeletes (yyGLRStack* yystackp)
{ {
ptrdiff_t yyi, yyj; YYPTRDIFF_T yyi, yyj;
yyi = yyj = 0; yyi = yyj = 0;
while (yyj < yystackp->yytops.yysize) while (yyj < yystackp->yytops.yysize)
{ {
@@ -1322,8 +1328,8 @@ yyremoveDeletes (yyGLRStack* yystackp)
* state YYLRSTATE, at input position YYPOSN, with (resolved) semantic * state YYLRSTATE, at input position YYPOSN, with (resolved) semantic
* value *YYVALP and source location *YYLOCP. */ * value *YYVALP and source location *YYLOCP. */
static inline void static inline void
yyglrShift (yyGLRStack* yystackp, ptrdiff_t yyk, yy_state_t yylrState, yyglrShift (yyGLRStack* yystackp, YYPTRDIFF_T yyk, yy_state_t yylrState,
ptrdiff_t yyposn, YYPTRDIFF_T yyposn,
YYSTYPE* yyvalp]b4_locations_if([, YYLTYPE* yylocp])[) YYSTYPE* yyvalp]b4_locations_if([, YYLTYPE* yylocp])[)
{ {
yyGLRState* yynewState = &yynewGLRStackItem (yystackp, yytrue)->yystate; yyGLRState* yynewState = &yynewGLRStackItem (yystackp, yytrue)->yystate;
@@ -1343,8 +1349,8 @@ yyglrShift (yyGLRStack* yystackp, ptrdiff_t yyk, yy_state_t yylrState,
* state YYLRSTATE, at input position YYPOSN, with the (unresolved) * state YYLRSTATE, at input position YYPOSN, with the (unresolved)
* semantic value of YYRHS under the action for YYRULE. */ * semantic value of YYRHS under the action for YYRULE. */
static inline void static inline void
yyglrShiftDefer (yyGLRStack* yystackp, ptrdiff_t yyk, yy_state_t yylrState, yyglrShiftDefer (yyGLRStack* yystackp, YYPTRDIFF_T yyk, yy_state_t yylrState,
ptrdiff_t yyposn, yyGLRState* yyrhs, yyRuleNum yyrule) YYPTRDIFF_T yyposn, yyGLRState* yyrhs, yyRuleNum yyrule)
{ {
yyGLRState* yynewState = &yynewGLRStackItem (yystackp, yytrue)->yystate; yyGLRState* yynewState = &yynewGLRStackItem (yystackp, yytrue)->yystate;
YY_ASSERT (yynewState->yyisState); YY_ASSERT (yynewState->yyisState);
@@ -1374,7 +1380,7 @@ yyglrShiftDefer (yyGLRStack* yystackp, ptrdiff_t yyk, yy_state_t yylrState,
`----------------------------------------------------------------------*/ `----------------------------------------------------------------------*/
static inline void static inline void
yy_reduce_print (yybool yynormal, yyGLRStackItem* yyvsp, ptrdiff_t yyk, yy_reduce_print (yybool yynormal, yyGLRStackItem* yyvsp, YYPTRDIFF_T yyk,
yyRuleNum yyrule]b4_user_formals[) yyRuleNum yyrule]b4_user_formals[)
{ {
int yynrhs = yyrhsLength (yyrule);]b4_locations_if([ int yynrhs = yyrhsLength (yyrule);]b4_locations_if([
@@ -1407,7 +1413,7 @@ yy_reduce_print (yybool yynormal, yyGLRStackItem* yyvsp, ptrdiff_t yyk,
* and *YYLOCP to the computed location (if any). Return value is as * and *YYLOCP to the computed location (if any). Return value is as
* for userAction. */ * for userAction. */
static inline YYRESULTTAG static inline YYRESULTTAG
yydoAction (yyGLRStack* yystackp, ptrdiff_t yyk, yyRuleNum yyrule, yydoAction (yyGLRStack* yystackp, YYPTRDIFF_T yyk, yyRuleNum yyrule,
YYSTYPE* yyvalp]b4_locuser_formals[) YYSTYPE* yyvalp]b4_locuser_formals[)
{ {
int yynrhs = yyrhsLength (yyrule); int yynrhs = yyrhsLength (yyrule);
@@ -1459,10 +1465,10 @@ yydoAction (yyGLRStack* yystackp, ptrdiff_t yyk, yyRuleNum yyrule,
* added to the options for the existing state's semantic value. * added to the options for the existing state's semantic value.
*/ */
static inline YYRESULTTAG static inline YYRESULTTAG
yyglrReduce (yyGLRStack* yystackp, ptrdiff_t yyk, yyRuleNum yyrule, yyglrReduce (yyGLRStack* yystackp, YYPTRDIFF_T yyk, yyRuleNum yyrule,
yybool yyforceEval]b4_user_formals[) yybool yyforceEval]b4_user_formals[)
{ {
ptrdiff_t yyposn = yystackp->yytops.yystates[yyk]->yyposn; YYPTRDIFF_T yyposn = yystackp->yytops.yystates[yyk]->yyposn;
if (yyforceEval || yystackp->yysplitPoint == YY_NULLPTR) if (yyforceEval || yystackp->yysplitPoint == YY_NULLPTR)
{ {
@@ -1484,7 +1490,7 @@ yyglrReduce (yyGLRStack* yystackp, ptrdiff_t yyk, yyRuleNum yyrule,
} }
else else
{ {
ptrdiff_t yyi; YYPTRDIFF_T yyi;
int yyn; int yyn;
yyGLRState* yys, *yys0 = yystackp->yytops.yystates[yyk]; yyGLRState* yys, *yys0 = yystackp->yytops.yystates[yyk];
yy_state_t yynewLRState; yy_state_t yynewLRState;
@@ -1526,8 +1532,8 @@ yyglrReduce (yyGLRStack* yystackp, ptrdiff_t yyk, yyRuleNum yyrule,
return yyok; return yyok;
} }
static ptrdiff_t static YYPTRDIFF_T
yysplitStack (yyGLRStack* yystackp, ptrdiff_t yyk) yysplitStack (yyGLRStack* yystackp, YYPTRDIFF_T yyk)
{ {
if (yystackp->yysplitPoint == YY_NULLPTR) if (yystackp->yysplitPoint == YY_NULLPTR)
{ {
@@ -1536,8 +1542,8 @@ yysplitStack (yyGLRStack* yystackp, ptrdiff_t yyk)
} }
if (yystackp->yytops.yycapacity <= yystackp->yytops.yysize) if (yystackp->yytops.yycapacity <= yystackp->yytops.yysize)
{ {
ptrdiff_t state_size = sizeof yystackp->yytops.yystates[0]; YYPTRDIFF_T state_size = YYSIZEOF (yystackp->yytops.yystates[0]);
ptrdiff_t half_max_capacity = YYSIZEMAX / 2 / state_size; YYPTRDIFF_T half_max_capacity = YYSIZE_MAXIMUM / 2 / state_size;
if (half_max_capacity < yystackp->yytops.yycapacity) if (half_max_capacity < yystackp->yytops.yycapacity)
yyMemoryExhausted (yystackp); yyMemoryExhausted (yystackp);
yystackp->yytops.yycapacity *= 2; yystackp->yytops.yycapacity *= 2;
@@ -1546,7 +1552,7 @@ yysplitStack (yyGLRStack* yystackp, ptrdiff_t yyk)
yyGLRState** yynewStates yyGLRState** yynewStates
= YY_CAST (yyGLRState**, = YY_CAST (yyGLRState**,
YYREALLOC (yystackp->yytops.yystates, YYREALLOC (yystackp->yytops.yystates,
(YY_CAST (size_t, yystackp->yytops.yycapacity) (YY_CAST (YYSIZE_T, yystackp->yytops.yycapacity)
* sizeof yynewStates[0]))); * sizeof yynewStates[0])));
if (yynewStates == YY_NULLPTR) if (yynewStates == YY_NULLPTR)
yyMemoryExhausted (yystackp); yyMemoryExhausted (yystackp);
@@ -1557,7 +1563,7 @@ yysplitStack (yyGLRStack* yystackp, ptrdiff_t yyk)
yybool* yynewLookaheadNeeds yybool* yynewLookaheadNeeds
= YY_CAST (yybool*, = YY_CAST (yybool*,
YYREALLOC (yystackp->yytops.yylookaheadNeeds, YYREALLOC (yystackp->yytops.yylookaheadNeeds,
(YY_CAST (size_t, yystackp->yytops.yycapacity) (YY_CAST (YYSIZE_T, yystackp->yytops.yycapacity)
* sizeof yynewLookaheadNeeds[0]))); * sizeof yynewLookaheadNeeds[0])));
if (yynewLookaheadNeeds == YY_NULLPTR) if (yynewLookaheadNeeds == YY_NULLPTR)
yyMemoryExhausted (yystackp); yyMemoryExhausted (yystackp);
@@ -1988,8 +1994,8 @@ yycompressStack (yyGLRStack* yystackp)
} }
static YYRESULTTAG static YYRESULTTAG
yyprocessOneStack (yyGLRStack* yystackp, ptrdiff_t yyk, yyprocessOneStack (yyGLRStack* yystackp, YYPTRDIFF_T yyk,
ptrdiff_t yyposn]b4_pure_formals[) YYPTRDIFF_T yyposn]b4_pure_formals[)
{ {
while (yystackp->yytops.yystates[yyk] != YY_NULLPTR) while (yystackp->yytops.yystates[yyk] != YY_NULLPTR)
{ {
@@ -2029,10 +2035,10 @@ yyprocessOneStack (yyGLRStack* yystackp, ptrdiff_t yyk,
const int yyaction = yygetLRActions (yystate, yytoken, &yyconflicts); const int yyaction = yygetLRActions (yystate, yytoken, &yyconflicts);
yystackp->yytops.yylookaheadNeeds[yyk] = yytrue; yystackp->yytops.yylookaheadNeeds[yyk] = yytrue;
while (*yyconflicts != 0) for (/* nothing */; *yyconflicts; yyconflicts += 1)
{ {
YYRESULTTAG yyflag; YYRESULTTAG yyflag;
ptrdiff_t yynewStack = yysplitStack (yystackp, yyk); YYPTRDIFF_T yynewStack = yysplitStack (yystackp, yyk);
YY_DPRINTF ((stderr, "Splitting off stack %ld from %ld.\n", YY_DPRINTF ((stderr, "Splitting off stack %ld from %ld.\n",
YY_CAST (long, yynewStack), YY_CAST (long, yyk))); YY_CAST (long, yynewStack), YY_CAST (long, yyk)));
yyflag = yyglrReduce (yystackp, yynewStack, yyflag = yyglrReduce (yystackp, yynewStack,
@@ -2048,7 +2054,6 @@ yyprocessOneStack (yyGLRStack* yystackp, ptrdiff_t yyk,
} }
else else
return yyflag; return yyflag;
yyconflicts += 1;
} }
if (yyisShiftAction (yyaction)) if (yyisShiftAction (yyaction))
@@ -2103,7 +2108,7 @@ yypcontext_expected_tokens (const yyGLRStack* yystackp,
int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
int yyx; int yyx;
for (yyx = yyxbegin; yyx < yyxend; ++yyx) for (yyx = yyxbegin; yyx < yyxend; ++yyx)
if (yycheck[yyx + yyn] == yyx && yyx != ]b4_symbol_prefix[YYERROR if (yycheck[yyx + yyn] == yyx && yyx != ]b4_symbol(1, kind)[
&& !yytable_value_is_error (yytable[yyx + yyn])) && !yytable_value_is_error (yytable[yyx + yyn]))
{ {
if (!yyarg) if (!yyarg)
@@ -2114,6 +2119,8 @@ yypcontext_expected_tokens (const yyGLRStack* yystackp,
yyarg[yycount++] = YY_CAST (yysymbol_kind_t, yyx); yyarg[yycount++] = YY_CAST (yysymbol_kind_t, yyx);
} }
} }
if (yyarg && yycount == 0 && 0 < yyargn)
yyarg[0] = ]b4_symbol(-2, kind)[;
return yycount; return yycount;
}]])[ }]])[
@@ -2221,7 +2228,7 @@ yyreportSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
one per "expected"). */ one per "expected"). */
yysymbol_kind_t yyarg[YYARGS_MAX]; yysymbol_kind_t yyarg[YYARGS_MAX];
/* Cumulated lengths of YYARG. */ /* Cumulated lengths of YYARG. */
ptrdiff_t yysize = 0; YYPTRDIFF_T yysize = 0;
/* Actual size of YYARG. */ /* Actual size of YYARG. */
int yycount int yycount
@@ -2252,11 +2259,11 @@ yyreportSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
int yyi; int yyi;
for (yyi = 0; yyi < yycount; ++yyi) for (yyi = 0; yyi < yycount; ++yyi)
{ {
ptrdiff_t yysz YYPTRDIFF_T yysz
= ]b4_parse_error_case( = ]b4_parse_error_case(
[verbose], [[yytnamerr (YY_NULLPTR, yytname[yyarg[yyi]])]], [verbose], [[yytnamerr (YY_NULLPTR, yytname[yyarg[yyi]])]],
[[yystrlen (yysymbol_name (yyarg[yyi]))]]);[ [[yystrlen (yysymbol_name (yyarg[yyi]))]]);[
if (YYSIZEMAX - yysize < yysz) if (YYSIZE_MAXIMUM - yysize < yysz)
yysize_overflow = yytrue; yysize_overflow = yytrue;
else else
yysize += yysz; yysize += yysz;
@@ -2264,7 +2271,7 @@ yyreportSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
} }
if (!yysize_overflow) if (!yysize_overflow)
yymsg = YY_CAST (char *, YYMALLOC (YY_CAST (size_t, yysize))); yymsg = YY_CAST (char *, YYMALLOC (YY_CAST (YYSIZE_T, yysize)));
if (yymsg) if (yymsg)
{ {
@@ -2341,7 +2348,7 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
/* Reduce to one stack. */ /* Reduce to one stack. */
{ {
ptrdiff_t yyk; YYPTRDIFF_T yyk;
for (yyk = 0; yyk < yystackp->yytops.yysize; yyk += 1) for (yyk = 0; yyk < yystackp->yytops.yysize; yyk += 1)
if (yystackp->yytops.yystates[yyk] != YY_NULLPTR) if (yystackp->yytops.yystates[yyk] != YY_NULLPTR)
break; break;
@@ -2361,8 +2368,8 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
int yyj = yypact[yys->yylrState]; int yyj = yypact[yys->yylrState];
if (! yypact_value_is_default (yyj)) if (! yypact_value_is_default (yyj))
{ {
yyj += ]b4_symbol_prefix[YYERROR; yyj += ]b4_symbol(1, kind)[;
if (0 <= yyj && yyj <= YYLAST && yycheck[yyj] == ]b4_symbol_prefix[YYERROR if (0 <= yyj && yyj <= YYLAST && yycheck[yyj] == ]b4_symbol(1, kind)[
&& yyisShiftAction (yytable[yyj])) && yyisShiftAction (yytable[yyj]))
{ {
/* Shift the error token. */ /* Shift the error token. */
@@ -2416,7 +2423,7 @@ yyparse (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[)
int yyresult; int yyresult;
yyGLRStack yystack; yyGLRStack yystack;
yyGLRStack* const yystackp = &yystack; yyGLRStack* const yystackp = &yystack;
ptrdiff_t yyposn; YYPTRDIFF_T yyposn;
YY_DPRINTF ((stderr, "Starting parse\n")); YY_DPRINTF ((stderr, "Starting parse\n"));
@@ -2445,7 +2452,7 @@ b4_dollar_popdef])[]dnl
/* For efficiency, we have two loops, the first of which is /* For efficiency, we have two loops, the first of which is
specialized to deterministic operation (single stack, no specialized to deterministic operation (single stack, no
potential ambiguity). */ potential ambiguity). */
/* Standard mode */ /* Standard mode. */
while (yytrue) while (yytrue)
{ {
yy_state_t yystate = yystack.yytops.yystates[0]->yylrState; yy_state_t yystate = yystack.yytops.yystates[0]->yylrState;
@@ -2468,7 +2475,8 @@ b4_dollar_popdef])[]dnl
yysymbol_kind_t yytoken = ]b4_yygetToken_call;[ yysymbol_kind_t yytoken = ]b4_yygetToken_call;[
const short* yyconflicts; const short* yyconflicts;
int yyaction = yygetLRActions (yystate, yytoken, &yyconflicts); int yyaction = yygetLRActions (yystate, yytoken, &yyconflicts);
if (*yyconflicts != 0) if (*yyconflicts)
/* Enter nondeterministic mode. */
break; break;
if (yyisShiftAction (yyaction)) if (yyisShiftAction (yyaction))
{ {
@@ -2481,11 +2489,11 @@ b4_dollar_popdef])[]dnl
} }
else if (yyisErrorAction (yyaction)) else if (yyisErrorAction (yyaction))
{]b4_locations_if([[ {]b4_locations_if([[
yystack.yyerror_range[1].yystate.yyloc = yylloc;]])[]b4_glr_cc_if([[ yystack.yyerror_range[1].yystate.yyloc = yylloc;]])[
/* Don't issue an error message again for exceptions /* Issue an error message unless the scanner already
thrown from the scanner. */ did. */
if (yychar != YYFAULTYTOK) if (yychar != ]b4_symbol(1, id)[)
]])[ yyreportSyntaxError (&yystack]b4_user_args[); yyreportSyntaxError (&yystack]b4_user_args[);
goto yyuser_error; goto yyuser_error;
} }
else else
@@ -2493,10 +2501,11 @@ b4_dollar_popdef])[]dnl
} }
} }
/* Nondeterministic mode. */
while (yytrue) while (yytrue)
{ {
yysymbol_kind_t yytoken_to_shift; yysymbol_kind_t yytoken_to_shift;
ptrdiff_t yys; YYPTRDIFF_T yys;
for (yys = 0; yys < yystack.yytops.yysize; yys += 1) for (yys = 0; yys < yystack.yytops.yysize; yys += 1)
yystackp->yytops.yylookaheadNeeds[yys] = yychar != ]b4_symbol(-2, id)[; yystackp->yytops.yylookaheadNeeds[yys] = yychar != ]b4_symbol(-2, id)[;
@@ -2603,8 +2612,8 @@ b4_dollar_popdef])[]dnl
yyGLRState** yystates = yystack.yytops.yystates; yyGLRState** yystates = yystack.yytops.yystates;
if (yystates) if (yystates)
{ {
ptrdiff_t yysize = yystack.yytops.yysize; YYPTRDIFF_T yysize = yystack.yytops.yysize;
ptrdiff_t yyk; YYPTRDIFF_T yyk;
for (yyk = 0; yyk < yysize; yyk += 1) for (yyk = 0; yyk < yysize; yyk += 1)
if (yystates[yyk]) if (yystates[yyk])
{ {
@@ -2651,7 +2660,7 @@ yypstates (yyGLRState* yyst)
} }
static void static void
yypstack (yyGLRStack* yystackp, ptrdiff_t yyk) yypstack (yyGLRStack* yystackp, YYPTRDIFF_T yyk)
{ {
yypstates (yystackp->yytops.yystates[yyk]); yypstates (yystackp->yytops.yystates[yyk]);
} }
@@ -2696,7 +2705,7 @@ yypdumpstack (yyGLRStack* yystackp)
YY_FPRINTF ((stderr, "Tops:")); YY_FPRINTF ((stderr, "Tops:"));
{ {
ptrdiff_t yyi; YYPTRDIFF_T yyi;
for (yyi = 0; yyi < yystackp->yytops.yysize; yyi += 1) for (yyi = 0; yyi < yystackp->yytops.yysize; yyi += 1)
YY_FPRINTF ((stderr, "%ld: %ld; ", YY_CAST (long, yyi), YY_FPRINTF ((stderr, "%ld: %ld; ", YY_CAST (long, yyi),
YYINDEX (yystackp->yytops.yystates[yyi]))); YYINDEX (yystackp->yytops.yystates[yyi])));
+11 -9
View File
@@ -167,7 +167,7 @@ m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
void void
]b4_parser_class[::yy_symbol_value_print_ (symbol_kind_type yykind, ]b4_parser_class[::yy_symbol_value_print_ (symbol_kind_type yykind,
const semantic_type* yyvaluep]b4_locations_if([[, const semantic_type* yyvaluep]b4_locations_if([[,
const location_type* yylocationp]])[) const location_type* yylocationp]])[) const
{]b4_locations_if([[ {]b4_locations_if([[
YYUSE (yylocationp);]])[ YYUSE (yylocationp);]])[
YYUSE (yyvaluep); YYUSE (yyvaluep);
@@ -181,7 +181,7 @@ m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
void void
]b4_parser_class[::yy_symbol_print_ (symbol_kind_type yykind, ]b4_parser_class[::yy_symbol_print_ (symbol_kind_type yykind,
const semantic_type* yyvaluep]b4_locations_if([[, const semantic_type* yyvaluep]b4_locations_if([[,
const location_type* yylocationp]])[) const location_type* yylocationp]])[) const
{ {
*yycdebug_ << (yykind < YYNTOKENS ? "token" : "nterm") *yycdebug_ << (yykind < YYNTOKENS ? "token" : "nterm")
<< ' ' << yytname[yykind] << " ("]b4_locations_if([[ << ' ' << yytname[yykind] << " ("]b4_locations_if([[
@@ -317,16 +317,16 @@ b4_percent_code_get([[requires]])[
/// \param yylocationp Its location.]])[ /// \param yylocationp Its location.]])[
virtual void yy_symbol_value_print_ (symbol_kind_type yykind, virtual void yy_symbol_value_print_ (symbol_kind_type yykind,
const semantic_type* yyvaluep]b4_locations_if([[, const semantic_type* yyvaluep]b4_locations_if([[,
const location_type* yylocationp]])[); const location_type* yylocationp]])[) const;
/// \brief Report a symbol on the debug stream. /// \brief Report a symbol on the debug stream.
/// \param yykind The symbol kind. /// \param yykind The symbol kind.
/// \param yyvaluep Its semantic value.]b4_locations_if([[ /// \param yyvaluep Its semantic value.]b4_locations_if([[
/// \param yylocationp Its location.]])[ /// \param yylocationp Its location.]])[
virtual void yy_symbol_print_ (symbol_kind_type yykind, virtual void yy_symbol_print_ (symbol_kind_type yykind,
const semantic_type* yyvaluep]b4_locations_if([[, const semantic_type* yyvaluep]b4_locations_if([[,
const location_type* yylocationp]])[); const location_type* yylocationp]])[) const;
private: private:
// Debugging. /// Debug stream.
std::ostream* yycdebug_; std::ostream* yycdebug_;
#endif #endif
@@ -344,6 +344,8 @@ b4_percent_define_flag_if([[global_tokens_and_yystype]],
#define ]b4_symbol(-2, [id])[ ]b4_namespace_ref[::]b4_parser_class[::token::]b4_symbol(-2, [id])[ #define ]b4_symbol(-2, [id])[ ]b4_namespace_ref[::]b4_parser_class[::token::]b4_symbol(-2, [id])[
#undef ]b4_symbol(0, [id])[ #undef ]b4_symbol(0, [id])[
#define ]b4_symbol(0, [id])[ ]b4_namespace_ref[::]b4_parser_class[::token::]b4_symbol(0, [id])[ #define ]b4_symbol(0, [id])[ ]b4_namespace_ref[::]b4_parser_class[::token::]b4_symbol(0, [id])[
#undef ]b4_symbol(1, [id])[
#define ]b4_symbol(1, [id])[ ]b4_namespace_ref[::]b4_parser_class[::token::]b4_symbol(1, [id])[
#ifndef ]b4_api_PREFIX[STYPE #ifndef ]b4_api_PREFIX[STYPE
# define ]b4_api_PREFIX[STYPE ]b4_namespace_ref[::]b4_parser_class[::semantic_type # define ]b4_api_PREFIX[STYPE ]b4_namespace_ref[::]b4_parser_class[::semantic_type
@@ -354,10 +356,10 @@ b4_percent_define_flag_if([[global_tokens_and_yystype]],
]m4_define([b4_declare_symbol_enum], ]m4_define([b4_declare_symbol_enum],
[[typedef ]b4_namespace_ref[::]b4_parser_class[::symbol_kind_type yysymbol_kind_t; [[typedef ]b4_namespace_ref[::]b4_parser_class[::symbol_kind_type yysymbol_kind_t;
#define ]b4_symbol_prefix[YYEMPTY ]b4_namespace_ref[::]b4_parser_class[::symbol_kind::]b4_symbol_prefix[YYEMPTY #define ]b4_symbol_prefix[YYEMPTY ]b4_namespace_ref[::]b4_parser_class[::symbol_kind::]b4_symbol_prefix[YYEMPTY
#define ]b4_symbol_prefix[YYERROR ]b4_namespace_ref[::]b4_parser_class[::symbol_kind::]b4_symbol_prefix[YYERROR #define ]b4_symbol_prefix[YYerror ]b4_namespace_ref[::]b4_parser_class[::symbol_kind::]b4_symbol_prefix[YYerror
#define ]b4_symbol_prefix[YYEOF ]b4_namespace_ref[::]b4_parser_class[::symbol_kind::]b4_symbol_prefix[YYEOF #define ]b4_symbol_prefix[YYEOF ]b4_namespace_ref[::]b4_parser_class[::symbol_kind::]b4_symbol_prefix[YYEOF
#define ]b4_symbol_prefix[YYUNDEF ]b4_namespace_ref[::]b4_parser_class[::symbol_kind::]b4_symbol_prefix[YYUNDEF #define ]b4_symbol_prefix[YYUNDEF ]b4_namespace_ref[::]b4_parser_class[::symbol_kind::]b4_symbol_prefix[YYUNDEF
]])[ ]])[
]b4_percent_code_get([[provides]])[ ]b4_percent_code_get([[provides]])[
]m4_popdef([b4_parse_param])dnl ]m4_popdef([b4_parse_param])dnl
+9 -4
View File
@@ -137,9 +137,14 @@ m4_define([b4_integral_parser_table_define],
# ------------------------ # ------------------------
# Output the definition of this token as an enum. # Output the definition of this token as an enum.
m4_define([b4_token_enum], m4_define([b4_token_enum],
[b4_token_format([ /** Token number, to be returned by the scanner. */ [b4_token_visible_if([$1],
static final int %s = %s; [m4_format([[ /** Token %s, to be returned by the scanner. */
], [$1])]) static final int %s = %s%s;
]],
b4_symbol([$1], [tag]),
b4_symbol([$1], [id]),
b4_symbol([$1], b4_api_token_raw_if([[number]], [[user_number]])))])])
# b4_token_enums # b4_token_enums
# -------------- # --------------
@@ -344,7 +349,7 @@ m4_define([b4_symbol_translate],
# ---------------- # ----------------
# Translate a string if i18n is enabled. Avoid collision with b4_translate. # Translate a string if i18n is enabled. Avoid collision with b4_translate.
m4_define([b4_trans], m4_define([b4_trans],
[m4_if(b4_has_translations, 0, [$1], [i18n($1)])]) [b4_has_translations_if([i18n($1)], [$1])])
+172 -118
View File
@@ -204,6 +204,13 @@ m4_define([b4_shared_declarations],
]b4_parser_class[ (]b4_parse_param_decl[); ]b4_parser_class[ (]b4_parse_param_decl[);
virtual ~]b4_parser_class[ (); virtual ~]b4_parser_class[ ();
#if 201103L <= YY_CPLUSPLUS
/// Non copyable.
]b4_parser_class[ (const ]b4_parser_class[&) = delete;
/// Non copyable.
]b4_parser_class[& operator= (const ]b4_parser_class[&) = delete;
#endif
/// Parse. An alias for parse (). /// Parse. An alias for parse ().
/// \returns 0 iff parsing succeeded. /// \returns 0 iff parsing succeeded.
int operator() (); int operator() ();
@@ -234,6 +241,23 @@ m4_define([b4_shared_declarations],
/// Report a syntax error. /// Report a syntax error.
void error (const syntax_error& err); void error (const syntax_error& err);
]b4_parse_error_bmatch(
[custom\|detailed],
[[ /// The user-facing name of the symbol whose (internal) number is
/// YYSYMBOL. No bounds checking.
static const char *symbol_name (symbol_kind_type yysymbol);]],
[simple],
[[#if ]b4_api_PREFIX[DEBUG || ]b4_token_table_flag[
/// The user-facing name of the symbol whose (internal) number is
/// YYSYMBOL. No bounds checking.
static const char *symbol_name (symbol_kind_type yysymbol);
#endif // #if ]b4_api_PREFIX[DEBUG || ]b4_token_table_flag[
]],
[verbose],
[[ /// The user-facing name of the symbol whose (internal) number is
/// YYSYMBOL. No bounds checking.
static std::string symbol_name (symbol_kind_type yysymbol);]])[
]b4_token_constructor_define[ ]b4_token_constructor_define[
]b4_parse_error_bmatch([custom\|detailed\|verbose], [[ ]b4_parse_error_bmatch([custom\|detailed\|verbose], [[
class context class context
@@ -255,10 +279,13 @@ m4_define([b4_shared_declarations],
}; };
]])[ ]])[
private: private:
/// This class is not copyable. #if YY_CPLUSPLUS < 201103L
/// Non copyable.
]b4_parser_class[ (const ]b4_parser_class[&); ]b4_parser_class[ (const ]b4_parser_class[&);
]b4_parser_class[& operator= (const ]b4_parser_class[&);]b4_lac_if([[ /// Non copyable.
]b4_parser_class[& operator= (const ]b4_parser_class[&);
#endif
]b4_lac_if([[
/// Check the lookahead yytoken. /// Check the lookahead yytoken.
/// \returns true iff the token will be eventually shifted. /// \returns true iff the token will be eventually shifted.
bool yy_lac_check_ (symbol_kind_type yytoken) const; bool yy_lac_check_ (symbol_kind_type yytoken) const;
@@ -305,35 +332,32 @@ m4_define([b4_shared_declarations],
/// In theory \a t should be a token_kind_type, but character literals /// In theory \a t should be a token_kind_type, but character literals
/// are valid, yet not members of the token_type enum. /// are valid, yet not members of the token_type enum.
static symbol_kind_type yytranslate_ (int t); static symbol_kind_type yytranslate_ (int t);
]b4_parse_error_bmatch([custom\|detailed], [[
/// The user-facing name of the symbol whose (internal) number is ]b4_parse_error_bmatch(
/// YYSYMBOL. No bounds checking. [simple],
static const char *symbol_name (symbol_kind_type yysymbol); [[#if ]b4_api_PREFIX[DEBUG || ]b4_token_table_flag[
/// For a symbol, its name in clear.
static const char* const yytname_[];
#endif // #if ]b4_api_PREFIX[DEBUG || ]b4_token_table_flag[
]],
[verbose],
[[ /// Convert the symbol name \a n to a form suitable for a diagnostic.
static std::string yytnamerr_ (const char *yystr);
/// For a symbol, its name in clear.
static const char* const yytname_[];
]])[ ]])[
// Tables. // Tables.
]b4_parser_tables_declare[ ]b4_parser_tables_declare[
]b4_parse_error_case([verbose], [[
/// Convert the symbol name \a n to a form suitable for a diagnostic.
static std::string yytnamerr_ (const char *n);
/// For a symbol, its name in clear.
static const char* const yytname_[];
]],
[b4_token_table_if([], [[
#if ]b4_api_PREFIX[DEBUG
/// For a symbol, its name in clear.
static const char* const yytname_[];
#endif
]])])[
#if ]b4_api_PREFIX[DEBUG #if ]b4_api_PREFIX[DEBUG
]b4_integral_parser_table_declare([rline], [b4_rline], ]b4_integral_parser_table_declare([rline], [b4_rline],
[[YYRLINE[YYN] -- Source line where rule number YYN was defined.]])[ [[YYRLINE[YYN] -- Source line where rule number YYN was defined.]])[
/// Report on the debug stream that the rule \a r is going to be reduced. /// Report on the debug stream that the rule \a r is going to be reduced.
virtual void yy_reduce_print_ (int r); virtual void yy_reduce_print_ (int r) const;
/// Print the state stack on the debug stream. /// Print the state stack on the debug stream.
virtual void yystack_print_ (); virtual void yy_stack_print_ () const;
/// Debugging level. /// Debugging level.
int yydebug_; int yydebug_;
@@ -455,6 +479,7 @@ m4_define([b4_shared_declarations],
}; };
]b4_parse_param_vars[ ]b4_parse_param_vars[
]b4_percent_code_get([[yy_bison_internal_hook]])[
}; };
]b4_token_ctor_if([b4_yytranslate_define([$1])[ ]b4_token_ctor_if([b4_yytranslate_define([$1])[
@@ -523,6 +548,11 @@ m4_if(b4_prefix, [yy], [],
# define YY_(msgid) msgid # define YY_(msgid) msgid
# endif # endif
#endif #endif
]b4_has_translations_if([
#ifndef N_
# define N_(Msgid) Msgid
#endif
])[
// Whether we are compiled with exception support. // Whether we are compiled with exception support.
#ifndef YY_EXCEPTIONS #ifndef YY_EXCEPTIONS
@@ -562,7 +592,7 @@ m4_if(b4_prefix, [yy], [],
# define YY_STACK_PRINT() \ # define YY_STACK_PRINT() \
do { \ do { \
if (yydebug_) \ if (yydebug_) \
yystack_print_ (); \ yy_stack_print_ (); \
} while (false) } while (false)
#else // !]b4_api_PREFIX[DEBUG #else // !]b4_api_PREFIX[DEBUG
@@ -582,71 +612,7 @@ m4_if(b4_prefix, [yy], [],
#define YYERROR goto yyerrorlab #define YYERROR goto yyerrorlab
#define YYRECOVERING() (!!yyerrstatus_) #define YYRECOVERING() (!!yyerrstatus_)
]b4_namespace_open[]b4_parse_error_bmatch([custom\|detailed], [[ ]b4_namespace_open[
/* The user-facing name of the symbol whose (internal) number is
YYSYMBOL. No bounds checking. */
const char *
]b4_parser_class[::symbol_name (symbol_kind_type yysymbol)
{
static const char *const yy_sname[] =
{
]b4_symbol_names[
};]m4_ifdef([b4_translatable], [[
/* YYTRANSLATABLE[SYMBOL-NUM] -- Whether YYTNAME[SYMBOL-NUM] is
internationalizable. */
static ]b4_int_type_for([b4_translatable])[ yytranslatable[] =
{
]b4_translatable[
};
return (yysymbol < YYNTOKENS && yytranslatable[yysymbol]
? _(yy_sname[yysymbol])
: yy_sname[yysymbol]);]], [[
return yy_sname[yysymbol];]])[
}
]])
b4_parse_error_case([verbose], [[
/* Return YYSTR after stripping away unnecessary quotes and
backslashes, so that it's suitable for yyerror. The heuristic is
that double-quoting is unnecessary unless the string contains an
apostrophe, a comma, or backslash (other than backslash-backslash).
YYSTR is taken from yytname. */
std::string
]b4_parser_class[::yytnamerr_ (const char *yystr)
{
if (*yystr == '"')
{
std::string yyr;
char const *yyp = yystr;
for (;;)
switch (*++yyp)
{
case '\'':
case ',':
goto do_not_strip_quotes;
case '\\':
if (*++yyp != '\\')
goto do_not_strip_quotes;
else
goto append;
append:
default:
yyr += *yyp;
break;
case '"':
return yyr;
}
do_not_strip_quotes: ;
}
return yystr;
}
]])[
/// Build a parser object. /// Build a parser object.
]b4_parser_class::b4_parser_class[ (]b4_parse_param_decl[) ]b4_parser_class::b4_parser_class[ (]b4_parse_param_decl[)
#if ]b4_api_PREFIX[DEBUG #if ]b4_api_PREFIX[DEBUG
@@ -725,7 +691,7 @@ b4_parse_error_case([verbose], [[
b4_symbol_variant([that.kind ()], b4_symbol_variant([that.kind ()],
[value], [move], [YY_MOVE (that.value)])])[ [value], [move], [YY_MOVE (that.value)])])[
// that is emptied. // that is emptied.
that.type = symbol_kind::]b4_symbol(-2, kind)[; that.kind_ = symbol_kind::]b4_symbol(-2, kind)[;
} }
#if YY_CPLUSPLUS < 201103L #if YY_CPLUSPLUS < 201103L
@@ -768,23 +734,21 @@ b4_parse_error_case([verbose], [[
#if ]b4_api_PREFIX[DEBUG #if ]b4_api_PREFIX[DEBUG
template <typename Base> template <typename Base>
void void
]b4_parser_class[::yy_print_ (std::ostream& yyo, ]b4_parser_class[::yy_print_ (std::ostream& yyo, const basic_symbol<Base>& yysym) const
const basic_symbol<Base>& yysym) const
{ {
std::ostream& yyoutput = yyo; std::ostream& yyoutput = yyo;
YYUSE (yyoutput); YYUSE (yyoutput);
symbol_kind_type yykind = yysym.kind ();
#if defined __GNUC__ && ! defined __clang__ && ! defined __ICC && __GNUC__ * 100 + __GNUC_MINOR__ <= 408
// Avoid a (spurious) G++ 4.8 warning about "array subscript is
// below array bounds".
if (yysym.empty ()) if (yysym.empty ())
std::abort (); yyo << "empty symbol";
#endif else
yyo << (yykind < YYNTOKENS ? "token" : "nterm") {
<< ' ' << yytname_[yykind] << " ("]b4_locations_if([ symbol_kind_type yykind = yysym.kind ();
<< yysym.location << ": "])[; yyo << (yykind < YYNTOKENS ? "token" : "nterm")
]b4_symbol_actions([printer])[ << ' ' << yysym.name () << " ("]b4_locations_if([
yyo << ')'; << yysym.location << ": "])[;
]b4_symbol_actions([printer])[
yyo << ')';
}
} }
#endif #endif
@@ -943,7 +907,7 @@ b4_dollar_popdef])[]dnl
{]b4_token_ctor_if([[ {]b4_token_ctor_if([[
symbol_type yylookahead (]b4_lex[); symbol_type yylookahead (]b4_lex[);
yyla.move (yylookahead);]], [[ yyla.move (yylookahead);]], [[
yyla.type = yytranslate_ (]b4_lex[);]])[ yyla.kind_ = yytranslate_ (]b4_lex[);]])[
} }
#if YY_EXCEPTIONS #if YY_EXCEPTIONS
catch (const syntax_error& yyexc) catch (const syntax_error& yyexc)
@@ -956,6 +920,16 @@ b4_dollar_popdef])[]dnl
} }
YY_SYMBOL_PRINT ("Next token is", yyla); YY_SYMBOL_PRINT ("Next token is", yyla);
if (yyla.kind () == ]symbol_kind::b4_symbol(1, kind)[)
{
// The scanner already issued an error message, process directly
// to error recovery. But do not keep the error token as
// lookahead, it is too special and may lead us to an endless
// loop in error recovery. */
yyla.kind_ = ]symbol_kind::b4_symbol(2, kind)[;
goto yyerrlab1;
}
/* If the proper action on seeing token YYLA.TYPE is to reduce or /* If the proper action on seeing token YYLA.TYPE is to reduce or
to detect an error, take that action. */ to detect an error, take that action. */
yyn += yyla.kind (); yyn += yyla.kind ();
@@ -1130,9 +1104,9 @@ b4_dollar_popdef])[]dnl
yyn = yypact_[+yystack_[0].state]; yyn = yypact_[+yystack_[0].state];
if (!yy_pact_value_is_default_ (yyn)) if (!yy_pact_value_is_default_ (yyn))
{ {
yyn += symbol_kind::]b4_symbol_prefix[YYERROR; yyn += symbol_kind::]b4_symbol(1, kind)[;
if (0 <= yyn && yyn <= yylast_ if (0 <= yyn && yyn <= yylast_
&& yycheck_[yyn] == symbol_kind::]b4_symbol_prefix[YYERROR) && yycheck_[yyn] == symbol_kind::]b4_symbol(1, kind)[)
{ {
yyn = yytable_[yyn]; yyn = yytable_[yyn];
if (0 < yyn) if (0 < yyn)
@@ -1222,8 +1196,86 @@ b4_dollar_popdef])[]dnl
{ {
error (]b4_join(b4_locations_if([yyexc.location]), error (]b4_join(b4_locations_if([yyexc.location]),
[[yyexc.what ()]])[); [[yyexc.what ()]])[);
}]b4_parse_error_bmatch([custom\|detailed\|verbose], [[ }
]b4_parse_error_bmatch([custom\|detailed],
[[ const char *
]b4_parser_class[::symbol_name (symbol_kind_type yysymbol)
{
static const char *const yy_sname[] =
{
]b4_symbol_names[
};]b4_has_translations_if([[
/* YYTRANSLATABLE[SYMBOL-NUM] -- Whether YY_SNAME[SYMBOL-NUM] is
internationalizable. */
static ]b4_int_type_for([b4_translatable])[ yytranslatable[] =
{
]b4_translatable[
};
return (yysymbol < YYNTOKENS && yytranslatable[yysymbol]
? _(yy_sname[yysymbol])
: yy_sname[yysymbol]);]], [[
return yy_sname[yysymbol];]])[
}
]],
[simple],
[[#if ]b4_api_PREFIX[DEBUG || ]b4_token_table_flag[
const char *
]b4_parser_class[::symbol_name (symbol_kind_type yysymbol)
{
return yytname_[yysymbol];
}
#endif // #if ]b4_api_PREFIX[DEBUG || ]b4_token_table_flag[
]],
[verbose],
[[ /* Return YYSTR after stripping away unnecessary quotes and
backslashes, so that it's suitable for yyerror. The heuristic is
that double-quoting is unnecessary unless the string contains an
apostrophe, a comma, or backslash (other than backslash-backslash).
YYSTR is taken from yytname. */
std::string
]b4_parser_class[::yytnamerr_ (const char *yystr)
{
if (*yystr == '"')
{
std::string yyr;
char const *yyp = yystr;
for (;;)
switch (*++yyp)
{
case '\'':
case ',':
goto do_not_strip_quotes;
case '\\':
if (*++yyp != '\\')
goto do_not_strip_quotes;
else
goto append;
append:
default:
yyr += *yyp;
break;
case '"':
return yyr;
}
do_not_strip_quotes: ;
}
return yystr;
}
std::string
]b4_parser_class[::symbol_name (symbol_kind_type yysymbol)
{
return yytnamerr_ (yytname_[yysymbol]);
}
]])[
]b4_parse_error_bmatch([custom\|detailed\|verbose], [[
// ]b4_parser_class[::context. // ]b4_parser_class[::context.
]b4_parser_class[::context::context (const ]b4_parser_class[& yyparser, const symbol_type& yyla) ]b4_parser_class[::context::context (const ]b4_parser_class[& yyparser, const symbol_type& yyla)
: yyparser_ (yyparser) : yyparser_ (yyparser)
@@ -1246,7 +1298,7 @@ b4_dollar_popdef])[]dnl
for (int yyx = 0; yyx < YYNTOKENS; ++yyx) for (int yyx = 0; yyx < YYNTOKENS; ++yyx)
{ {
symbol_kind_type yysym = YY_CAST (symbol_kind_type, yyx); symbol_kind_type yysym = YY_CAST (symbol_kind_type, yyx);
if (yysym != symbol_kind::]b4_symbol_prefix[YYERROR if (yysym != symbol_kind::]b4_symbol(1, kind)[
&& yysym != symbol_kind::]b4_symbol_prefix[YYUNDEF && yysym != symbol_kind::]b4_symbol_prefix[YYUNDEF
&& yyparser_.yy_lac_check_ (yysym)) && yyparser_.yy_lac_check_ (yysym))
{ {
@@ -1269,7 +1321,7 @@ b4_dollar_popdef])[]dnl
int yychecklim = yylast_ - yyn + 1; int yychecklim = yylast_ - yyn + 1;
int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
for (int yyx = yyxbegin; yyx < yyxend; ++yyx) for (int yyx = yyxbegin; yyx < yyxend; ++yyx)
if (yycheck_[yyx + yyn] == yyx && yyx != symbol_kind::]b4_symbol_prefix[YYERROR if (yycheck_[yyx + yyn] == yyx && yyx != symbol_kind::]b4_symbol(1, kind)[
&& !yy_table_value_is_error_ (yytable_[yyx + yyn])) && !yy_table_value_is_error_ (yytable_[yyx + yyn]))
{ {
if (!yyarg) if (!yyarg)
@@ -1281,6 +1333,8 @@ b4_dollar_popdef])[]dnl
} }
} }
]])[ ]])[
if (yyarg && yycount == 0 && 0 < yyargn)
yyarg[0] = symbol_kind::]b4_symbol(-2, kind)[;
return yycount; return yycount;
} }
@@ -1293,7 +1347,7 @@ b4_dollar_popdef])[]dnl
yylac_stack_.clear (); yylac_stack_.clear ();
// Reduce until we encounter a shift and thereby accept the token. // Reduce until we encounter a shift and thereby accept the token.
#if ]b4_api_PREFIX[DEBUG #if ]b4_api_PREFIX[DEBUG
YYCDEBUG << "LAC: checking lookahead " << yytname_[yytoken] << ':'; YYCDEBUG << "LAC: checking lookahead " << symbol_name (yytoken) << ':';
#endif #endif
std::ptrdiff_t lac_top = 0; std::ptrdiff_t lac_top = 0;
while (true) while (true)
@@ -1357,7 +1411,7 @@ b4_dollar_popdef])[]dnl
: yylac_stack_.back ()); : yylac_stack_.back ());
// Push the resulting state of the reduction. // Push the resulting state of the reduction.
state_type state = yy_lr_goto_state_ (top_state, yyr1_[yyrule]); state_type state = yy_lr_goto_state_ (top_state, yyr1_[yyrule]);
YYCDEBUG << " G" << state; YYCDEBUG << " G" << int (state);
yylac_stack_.push_back (state); yylac_stack_.push_back (state);
} }
} }
@@ -1393,7 +1447,7 @@ b4_dollar_popdef])[]dnl
{ {
#if ]b4_api_PREFIX[DEBUG #if ]b4_api_PREFIX[DEBUG
YYCDEBUG << "LAC: initial context established for " YYCDEBUG << "LAC: initial context established for "
<< yytname_[yytoken] << '\n'; << symbol_name (yytoken) << '\n';
#endif #endif
yy_lac_established_ = true; yy_lac_established_ = true;
return yy_lac_check_ (yytoken); return yy_lac_check_ (yytoken);
@@ -1502,9 +1556,7 @@ b4_dollar_popdef])[]dnl
for (char const* yyp = yyformat; *yyp; ++yyp) for (char const* yyp = yyformat; *yyp; ++yyp)
if (yyp[0] == '%' && yyp[1] == 's' && yyi < yycount) if (yyp[0] == '%' && yyp[1] == 's' && yyi < yycount)
{ {
yyres += ]b4_parse_error_case([verbose], yyres += symbol_name (yyarg[yyi++]);
[[yytnamerr_ (yytname_[yyarg[yyi++]])]],
[[symbol_name (yyarg[yyi++])]])[;
++yyp; ++yyp;
} }
else else
@@ -1519,7 +1571,8 @@ b4_dollar_popdef])[]dnl
]b4_parser_tables_define[ ]b4_parser_tables_define[
]b4_tname_if([], [[#if ]b4_api_PREFIX[DEBUG]])[ ]b4_parse_error_bmatch([simple\|verbose],
[[#if ]b4_api_PREFIX[DEBUG]b4_tname_if([[ || 1]])[
// YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. // YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
// First, the terminals, then, starting at \a YYNTOKENS, nonterminals. // First, the terminals, then, starting at \a YYNTOKENS, nonterminals.
const char* const char*
@@ -1527,13 +1580,14 @@ b4_dollar_popdef])[]dnl
{ {
]b4_tname[ ]b4_tname[
}; };
]b4_tname_if([], [[#endif]])[ #endif
]])[
#if ]b4_api_PREFIX[DEBUG][ #if ]b4_api_PREFIX[DEBUG][
]b4_integral_parser_table_define([rline], [b4_rline])[ ]b4_integral_parser_table_define([rline], [b4_rline])[
void void
]b4_parser_class[::yystack_print_ () ]b4_parser_class[::yy_stack_print_ () const
{ {
*yycdebug_ << "Stack now"; *yycdebug_ << "Stack now";
for (stack_type::const_iterator for (stack_type::const_iterator
@@ -1545,7 +1599,7 @@ b4_dollar_popdef])[]dnl
} }
void void
]b4_parser_class[::yy_reduce_print_ (int yyrule) ]b4_parser_class[::yy_reduce_print_ (int yyrule) const
{ {
int yylno = yyrline_[yyrule]; int yylno = yyrline_[yyrule];
int yynrhs = yyr2_[yyrule]; int yynrhs = yyr2_[yyrule];
+47 -33
View File
@@ -21,7 +21,7 @@ m4_include(b4_skeletonsdir/[d.m4])
b4_output_begin([b4_parser_file_name]) b4_output_begin([b4_parser_file_name])
b4_copyright([Skeleton implementation for Bison LALR(1) parsers in D], b4_copyright([Skeleton implementation for Bison LALR(1) parsers in D],
[2007-2012, 2019-2020])[ [2007-2012, 2019-2020])[
]b4_disclaimer[
]b4_percent_define_ifdef([package], [module b4_percent_define_get([package]); ]b4_percent_define_ifdef([package], [module b4_percent_define_get([package]);
])[ ])[
version(D_Version2) { version(D_Version2) {
@@ -509,39 +509,53 @@ m4_popdef([b4_at_dollar])])dnl
yytoken = yytranslate_ (yychar);]b4_parse_trace_if([[ yytoken = yytranslate_ (yychar);]b4_parse_trace_if([[
yy_symbol_print ("Next token is", yytoken, yylval]b4_locations_if([, yylloc])[);]])[ yy_symbol_print ("Next token is", yytoken, yylval]b4_locations_if([, yylloc])[);]])[
/* If the proper action on seeing token YYTOKEN is to reduce or to if (yytoken == SymbolKind.]b4_symbol(1, kind)[)
detect an error, take that action. */
yyn += yytoken;
if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yytoken)
label = YYDEFAULT;
/* <= 0 means reduce or error. */
else if ((yyn = yytable_[yyn]) <= 0)
{ {
if (yy_table_value_is_error_ (yyn)) // The scanner already issued an error message, process directly
label = YYERRLAB; // to error recovery. But do not keep the error token as
else // lookahead, it is too special and may lead us to an endless
{ // loop in error recovery. */
yyn = -yyn; yychar = TokenKind.YYUNDEF;
label = YYREDUCE; yytoken = SymbolKind.]b4_symbol_prefix[YYUNDEF;]b4_locations_if([[
} yyerrloc = yylloc;]])[
label = YYERRLAB1;
} }
else else
{ {
/* Shift the lookahead token. */]b4_parse_trace_if([[ /* If the proper action on seeing token YYTOKEN is to reduce or to
yy_symbol_print ("Shifting", yytoken, yylval]b4_locations_if([, yylloc])[);]])[ detect an error, take that action. */
yyn += yytoken;
if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yytoken)
label = YYDEFAULT;
/* Discard the token being shifted. */ /* <= 0 means reduce or error. */
yychar = TokenKind.YYEMPTY; else if ((yyn = yytable_[yyn]) <= 0)
{
if (yy_table_value_is_error_ (yyn))
label = YYERRLAB;
else
{
yyn = -yyn;
label = YYREDUCE;
}
}
else
{
/* Shift the lookahead token. */]b4_parse_trace_if([[
yy_symbol_print ("Shifting", yytoken, yylval]b4_locations_if([, yylloc])[);]])[
/* Count tokens shifted since error; after three, turn off error /* Discard the token being shifted. */
* status. */ yychar = TokenKind.YYEMPTY;
if (yyerrstatus_ > 0)
--yyerrstatus_;
yystate = yyn; /* Count tokens shifted since error; after three, turn off error
yystack.push (yystate, yylval]b4_locations_if([, yylloc])[); * status. */
label = YYNEWSTATE; if (yyerrstatus_ > 0)
--yyerrstatus_;
yystate = yyn;
yystack.push (yystate, yylval]b4_locations_if([, yylloc])[);
label = YYNEWSTATE;
}
} }
break; break;
@@ -577,8 +591,8 @@ m4_popdef([b4_at_dollar])])dnl
yytoken = SymbolKind.]b4_symbol(-2, kind)[; yytoken = SymbolKind.]b4_symbol(-2, kind)[;
yyerror (]b4_locations_if([yylloc, ])[yysyntax_error (yystate, yytoken)); yyerror (]b4_locations_if([yylloc, ])[yysyntax_error (yystate, yytoken));
} }
]b4_locations_if([
]b4_locations_if([ yyerrloc = yylloc;])[ yyerrloc = yylloc;])[
if (yyerrstatus_ == 3) if (yyerrstatus_ == 3)
{ {
/* If just tried and failed to reuse lookahead token after an /* If just tried and failed to reuse lookahead token after an
@@ -624,8 +638,8 @@ m4_popdef([b4_at_dollar])])dnl
yyn = yypact_[yystate]; yyn = yypact_[yystate];
if (!yy_pact_value_is_default_ (yyn)) if (!yy_pact_value_is_default_ (yyn))
{ {
yyn += SymbolKind.]b4_symbol_prefix[YYERROR; yyn += SymbolKind.]b4_symbol(1, kind)[;
if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == SymbolKind.]b4_symbol_prefix[YYERROR) if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == SymbolKind.]b4_symbol(1, kind)[)
{ {
yyn = yytable_[yyn]; yyn = yytable_[yyn];
if (0 < yyn) if (0 < yyn)
@@ -731,14 +745,14 @@ m4_popdef([b4_at_dollar])])dnl
int yyxend = yychecklim < yyntokens_ ? yychecklim : yyntokens_; int yyxend = yychecklim < yyntokens_ ? yychecklim : yyntokens_;
int count = 0; int count = 0;
for (int x = yyxbegin; x < yyxend; ++x) for (int x = yyxbegin; x < yyxend; ++x)
if (yycheck_[x + yyn] == x && x != SymbolKind.]b4_symbol_prefix[YYERROR if (yycheck_[x + yyn] == x && x != SymbolKind.]b4_symbol(1, kind)[
&& !yy_table_value_is_error_ (yytable_[x + yyn])) && !yy_table_value_is_error_ (yytable_[x + yyn]))
++count; ++count;
if (count < 5) if (count < 5)
{ {
count = 0; count = 0;
for (int x = yyxbegin; x < yyxend; ++x) for (int x = yyxbegin; x < yyxend; ++x)
if (yycheck_[x + yyn] == x && x != SymbolKind.]b4_symbol_prefix[YYERROR if (yycheck_[x + yyn] == x && x != SymbolKind.]b4_symbol(1, kind)[
&& !yy_table_value_is_error_ (yytable_[x + yyn])) && !yy_table_value_is_error_ (yytable_[x + yyn]))
{ {
res ~= count++ == 0 ? ", expecting " : " or "; res ~= count++ == 0 ? ", expecting " : " or ";
+144 -134
View File
@@ -78,6 +78,7 @@ m4_define([b4_define_state],[[
]b4_output_begin([b4_parser_file_name])[ ]b4_output_begin([b4_parser_file_name])[
]b4_copyright([Skeleton implementation for Bison LALR(1) parsers in Java], ]b4_copyright([Skeleton implementation for Bison LALR(1) parsers in Java],
[2007-2015, 2018-2020])[ [2007-2015, 2018-2020])[
]b4_disclaimer[
]b4_percent_define_ifdef([package], [package b4_percent_define_get([package]);[ ]b4_percent_define_ifdef([package], [package b4_percent_define_get([package]);[
]])[ ]])[
]b4_user_pre_prologue[ ]b4_user_pre_prologue[
@@ -120,7 +121,7 @@ import java.text.MessageFormat;
* Locations represent a part of the input through the beginning * Locations represent a part of the input through the beginning
* and ending positions. * and ending positions.
*/ */
public class ]b4_location_type[ { public static class ]b4_location_type[ {
/** /**
* The first, inclusive, position in the range. * The first, inclusive, position in the range.
*/ */
@@ -163,12 +164,12 @@ import java.text.MessageFormat;
} }
} }
private ]b4_location_type[ yylloc (YYStack rhs, int n) private ]b4_location_type[ yylloc(YYStack rhs, int n)
{ {
if (0 < n) if (0 < n)
return new ]b4_location_type[ (rhs.locationAt (n-1).begin, rhs.locationAt (0).end); return new ]b4_location_type[(rhs.locationAt(n-1).begin, rhs.locationAt(0).end);
else else
return new ]b4_location_type[ (rhs.locationAt (0).end); return new ]b4_location_type[(rhs.locationAt(0).end);
}]])[ }]])[
]b4_declare_symbol_enum[ ]b4_declare_symbol_enum[
@@ -179,27 +180,26 @@ import java.text.MessageFormat;
*/ */
public interface Lexer { public interface Lexer {
]b4_token_enums[ ]b4_token_enums[
/** Deprecated, use b4_symbol(0, id) instead. */ /** Deprecated, use ]b4_symbol(0, id)[ instead. */
public static final int EOF = ]b4_symbol(0, id)[; public static final int EOF = ]b4_symbol(0, id)[;
]b4_pull_if([b4_locations_if([[
]b4_locations_if([[
/** /**
* Method to retrieve the beginning position of the last scanned token. * Method to retrieve the beginning position of the last scanned token.
* @@return the position at which the last scanned token starts. * @@return the position at which the last scanned token starts.
*/ */
]b4_position_type[ getStartPos (); ]b4_position_type[ getStartPos();
/** /**
* Method to retrieve the ending position of the last scanned token. * Method to retrieve the ending position of the last scanned token.
* @@return the first position beyond the last scanned token. * @@return the first position beyond the last scanned token.
*/ */
]b4_position_type[ getEndPos ();]])[ ]b4_position_type[ getEndPos();]])[
/** /**
* Method to retrieve the semantic value of the last scanned token. * Method to retrieve the semantic value of the last scanned token.
* @@return the semantic value of the last scanned token. * @@return the semantic value of the last scanned token.
*/ */
]b4_yystype[ getLVal (); ]b4_yystype[ getLVal();
/** /**
* Entry point for the scanner. Returns the token identifier corresponding * Entry point for the scanner. Returns the token identifier corresponding
@@ -207,24 +207,25 @@ import java.text.MessageFormat;
* ]b4_locations_if([and beginning/ending positions ])[of the token. * ]b4_locations_if([and beginning/ending positions ])[of the token.
* @@return the token identifier corresponding to the next token. * @@return the token identifier corresponding to the next token.
*/ */
int yylex ()]b4_maybe_throws([b4_lex_throws])[; int yylex()]b4_maybe_throws([b4_lex_throws])[;
]])[
/** /**
* Entry point for error reporting. Emits an error * Emit an error]b4_locations_if([ referring to the given location])[in a user-defined way.
* ]b4_locations_if([referring to the given location ])[in a user-defined way.
* *
*]b4_locations_if([[ @@param loc The location of the element to which the *]b4_locations_if([[ @@param loc The location of the element to which the
* error message is related]])[ * error message is related.]])[
* @@param msg The string for the error message. * @@param msg The string for the error message.
*/ */
void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[String msg); void yyerror(]b4_locations_if([b4_location_type[ loc, ]])[String msg);
]b4_parse_error_bmatch( ]b4_parse_error_bmatch(
[custom], [[ [custom], [[
/** /**
* Build and emit a syntax error message. * Build and emit a "syntax error" message in a user-defined way.
*
* @@param ctx The context of the error.
*/ */
void reportSyntaxError (][Context yyctx); void reportSyntaxError (][Context ctx);
]])[ ]])[
} }
@@ -306,9 +307,8 @@ import java.text.MessageFormat;
*]b4_locations_if([[ Use a <code>null</code> location.]])[ *]b4_locations_if([[ Use a <code>null</code> location.]])[
* @@param msg The error message. * @@param msg The error message.
*/ */
public final void yyerror (String msg) public final void yyerror(String msg) {
{ yylexer.yyerror(]b4_locations_if([[(]b4_location_type[)null, ]])[msg);
yylexer.yyerror (]b4_locations_if([[(]b4_location_type[)null, ]])[msg);
} }
]b4_locations_if([[ ]b4_locations_if([[
/** /**
@@ -316,9 +316,8 @@ import java.text.MessageFormat;
* @@param loc The location associated with the message. * @@param loc The location associated with the message.
* @@param msg The error message. * @@param msg The error message.
*/ */
public final void yyerror (]b4_location_type[ loc, String msg) public final void yyerror(]b4_location_type[ loc, String msg) {
{ yylexer.yyerror(loc, msg);
yylexer.yyerror (loc, msg);
} }
/** /**
@@ -326,9 +325,8 @@ import java.text.MessageFormat;
* @@param pos The position associated with the message. * @@param pos The position associated with the message.
* @@param msg The error message. * @@param msg The error message.
*/ */
public final void yyerror (]b4_position_type[ pos, String msg) public final void yyerror(]b4_position_type[ pos, String msg) {
{ yylexer.yyerror(new ]b4_location_type[ (pos), msg);
yylexer.yyerror (new ]b4_location_type[ (pos), msg);
}]])[ }]])[
]b4_parse_trace_if([[ ]b4_parse_trace_if([[
protected final void yycdebug (String s) { protected final void yycdebug (String s) {
@@ -468,7 +466,7 @@ import java.text.MessageFormat;
return yydefgoto_[yysym - YYNTOKENS_]; return yydefgoto_[yysym - YYNTOKENS_];
} }
private int yyaction (int yyn, YYStack yystack, int yylen)]b4_maybe_throws([b4_throws])[ private int yyaction(int yyn, YYStack yystack, int yylen)]b4_maybe_throws([b4_throws])[
{ {
/* If YYLEN is nonzero, implement the default value of the action: /* If YYLEN is nonzero, implement the default value of the action:
'$$ = $1'. Otherwise, use the top of the stack. '$$ = $1'. Otherwise, use the top of the stack.
@@ -476,10 +474,10 @@ import java.text.MessageFormat;
Otherwise, the following line sets YYVAL to garbage. Otherwise, the following line sets YYVAL to garbage.
This behavior is undocumented and Bison This behavior is undocumented and Bison
users should not rely upon it. */ users should not rely upon it. */
]b4_yystype[ yyval = (0 < yylen) ? yystack.valueAt (yylen - 1) : yystack.valueAt (0);]b4_locations_if([[ ]b4_yystype[ yyval = (0 < yylen) ? yystack.valueAt(yylen - 1) : yystack.valueAt(0);]b4_locations_if([[
]b4_location_type[ yyloc = yylloc (yystack, yylen);]])[]b4_parse_trace_if([[ ]b4_location_type[ yyloc = yylloc(yystack, yylen);]])[]b4_parse_trace_if([[
yyReducePrint (yyn, yystack);]])[ yyReducePrint(yyn, yystack);]])[
switch (yyn) switch (yyn)
{ {
@@ -487,13 +485,13 @@ import java.text.MessageFormat;
default: break; default: break;
}]b4_parse_trace_if([[ }]b4_parse_trace_if([[
yySymbolPrint ("-> $$ =", SymbolKind.get (yyr1_[yyn]), yyval]b4_locations_if([, yyloc])[);]])[ yySymbolPrint("-> $$ =", SymbolKind.get(yyr1_[yyn]), yyval]b4_locations_if([, yyloc])[);]])[
yystack.pop (yylen); yystack.pop(yylen);
yylen = 0; yylen = 0;
/* Shift the result of the reduction. */ /* Shift the result of the reduction. */
int yystate = yyLRGotoState (yystack.stateAt (0), yyr1_[yyn]); int yystate = yyLRGotoState(yystack.stateAt(0), yyr1_[yyn]);
yystack.push (yystate, yyval]b4_locations_if([, yyloc])[); yystack.push(yystate, yyval]b4_locations_if([, yyloc])[);
return YYNEWSTATE; return YYNEWSTATE;
} }
@@ -503,13 +501,14 @@ import java.text.MessageFormat;
`--------------------------------*/ `--------------------------------*/
private void yySymbolPrint(String s, SymbolKind yykind, private void yySymbolPrint(String s, SymbolKind yykind,
]b4_yystype[ yyvalue]b4_locations_if([, ]b4_location_type[ yylocation])[) ]b4_yystype[ yyvalue]b4_locations_if([, ]b4_location_type[ yylocation])[) {
{ if (0 < yydebug) {
yycdebug (s yycdebug(s
+ (yykind.getCode() < YYNTOKENS_ ? " token " : " nterm ") + (yykind.getCode() < YYNTOKENS_ ? " token " : " nterm ")
+ yykind.getName() + " ("]b4_locations_if([ + yykind.getName() + " ("]b4_locations_if([
+ yylocation + ": "])[ + yylocation + ": "])[
+ (yyvalue == null ? "(null)" : yyvalue.toString()) + ")"); + (yyvalue == null ? "(null)" : yyvalue.toString()) + ")");
}
}]])[ }]])[
]b4_push_if([],[[ ]b4_push_if([],[[
@@ -520,7 +519,7 @@ import java.text.MessageFormat;
* @@return <tt>true</tt> if the parsing succeeds. Note that this does not * @@return <tt>true</tt> if the parsing succeeds. Note that this does not
* imply that there were no syntax errors. * imply that there were no syntax errors.
*/ */
public boolean parse ()]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[]])[ public boolean parse()]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[]])[
]b4_push_if([ ]b4_push_if([
/** /**
* Push Parse input from external lexer * Push Parse input from external lexer
@@ -531,7 +530,7 @@ import java.text.MessageFormat;
* *
* @@return <tt>YYACCEPT, YYABORT, YYPUSH_MORE</tt> * @@return <tt>YYACCEPT, YYABORT, YYPUSH_MORE</tt>
*/ */
public int push_parse (int yylextoken, b4_yystype yylexval[]b4_locations_if([, b4_location_type yylexloc]))b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])])[ public int push_parse(int yylextoken, b4_yystype yylexval[]b4_locations_if([, b4_location_type yylexloc]))b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])])[
{]b4_locations_if([[ {]b4_locations_if([[
/* @@$. */ /* @@$. */
]b4_location_type[ yyloc;]])[ ]b4_location_type[ yyloc;]])[
@@ -611,44 +610,58 @@ b4_dollar_popdef[]dnl
/* Convert token to internal form. */ /* Convert token to internal form. */
yytoken = yytranslate_ (yychar);]b4_parse_trace_if([[ yytoken = yytranslate_ (yychar);]b4_parse_trace_if([[
yySymbolPrint ("Next token is", yytoken, yySymbolPrint("Next token is", yytoken,
yylval]b4_locations_if([, yylloc])[);]])[ yylval]b4_locations_if([, yylloc])[);]])[
/* If the proper action on seeing token YYTOKEN is to reduce or to if (yytoken == SymbolKind.]b4_symbol_prefix[YYerror)
detect an error, take that action. */
yyn += yytoken.getCode ();
if (yyn < 0 || YYLAST_ < yyn || yycheck_[yyn] != yytoken.getCode ())
label = YYDEFAULT;
/* <= 0 means reduce or error. */
else if ((yyn = yytable_[yyn]) <= 0)
{ {
if (yyTableValueIsError (yyn)) // The scanner already issued an error message, process directly
label = YYERRLAB; // to error recovery. But do not keep the error token as
else // lookahead, it is too special and may lead us to an endless
{ // loop in error recovery. */
yyn = -yyn; yychar = Lexer.]b4_percent_define_get([api.token.prefix])[YYUNDEF;
label = YYREDUCE; yytoken = SymbolKind.]b4_symbol_prefix[YYUNDEF;]b4_locations_if([[
} yyerrloc = yylloc;]])[
label = YYERRLAB1;
} }
else else
{ {
/* Shift the lookahead token. */]b4_parse_trace_if([[ /* If the proper action on seeing token YYTOKEN is to reduce or to
yySymbolPrint ("Shifting", yytoken, detect an error, take that action. */
yylval]b4_locations_if([, yylloc])[); yyn += yytoken.getCode ();
if (yyn < 0 || YYLAST_ < yyn || yycheck_[yyn] != yytoken.getCode ())
label = YYDEFAULT;
/* <= 0 means reduce or error. */
else if ((yyn = yytable_[yyn]) <= 0)
{
if (yyTableValueIsError (yyn))
label = YYERRLAB;
else
{
yyn = -yyn;
label = YYREDUCE;
}
}
else
{
/* Shift the lookahead token. */]b4_parse_trace_if([[
yySymbolPrint("Shifting", yytoken,
yylval]b4_locations_if([, yylloc])[);
]])[ ]])[
/* Discard the token being shifted. */ /* Discard the token being shifted. */
yychar = YYEMPTY_; yychar = YYEMPTY_;
/* Count tokens shifted since error; after three, turn off error /* Count tokens shifted since error; after three, turn off error
status. */ status. */
if (yyerrstatus_ > 0) if (yyerrstatus_ > 0)
--yyerrstatus_; --yyerrstatus_;
yystate = yyn; yystate = yyn;
yystack.push (yystate, yylval]b4_locations_if([, yylloc])[); yystack.push (yystate, yylval]b4_locations_if([, yylloc])[);
label = YYNEWSTATE; label = YYNEWSTATE;
}
} }
break; break;
@@ -668,7 +681,7 @@ b4_dollar_popdef[]dnl
`-----------------------------*/ `-----------------------------*/
case YYREDUCE: case YYREDUCE:
yylen = yyr2_[yyn]; yylen = yyr2_[yyn];
label = yyaction (yyn, yystack, yylen); label = yyaction(yyn, yystack, yylen);
yystate = yystack.stateAt (0); yystate = yystack.stateAt (0);
break; break;
@@ -684,7 +697,6 @@ b4_dollar_popdef[]dnl
yytoken = null; yytoken = null;
yyreportSyntaxError (new Context (yystack, yytoken]b4_locations_if([[, yylloc]])[)); yyreportSyntaxError (new Context (yystack, yytoken]b4_locations_if([[, yylloc]])[));
} }
]b4_locations_if([[ ]b4_locations_if([[
yyerrloc = yylloc;]])[ yyerrloc = yylloc;]])[
if (yyerrstatus_ == 3) if (yyerrstatus_ == 3)
@@ -732,9 +744,9 @@ b4_dollar_popdef[]dnl
yyn = yypact_[yystate]; yyn = yypact_[yystate];
if (!yyPactValueIsDefault (yyn)) if (!yyPactValueIsDefault (yyn))
{ {
yyn += SymbolKind.]b4_symbol_prefix[YYERROR.getCode (); yyn += SymbolKind.]b4_symbol(1, kind)[.getCode ();
if (0 <= yyn && yyn <= YYLAST_ if (0 <= yyn && yyn <= YYLAST_
&& yycheck_[yyn] == SymbolKind.]b4_symbol_prefix[YYERROR.getCode ()) && yycheck_[yyn] == SymbolKind.]b4_symbol(1, kind)[.getCode ())
{ {
yyn = yytable_[yyn]; yyn = yytable_[yyn];
if (0 < yyn) if (0 < yyn)
@@ -767,8 +779,8 @@ b4_dollar_popdef[]dnl
yystack.pop (2);]])[ yystack.pop (2);]])[
/* Shift the error token. */]b4_parse_trace_if([[ /* Shift the error token. */]b4_parse_trace_if([[
yySymbolPrint ("Shifting", SymbolKind.get (yystos_[yyn]), yySymbolPrint("Shifting", SymbolKind.get (yystos_[yyn]),
yylval]b4_locations_if([, yyloc])[);]])[ yylval]b4_locations_if([, yyloc])[);]])[
yystate = yyn; yystate = yyn;
yystack.push (yyn, yylval]b4_locations_if([, yyloc])[); yystack.push (yyn, yylval]b4_locations_if([, yyloc])[);
@@ -819,7 +831,7 @@ b4_dollar_popdef[]dnl
this.push_parse_initialized = true; this.push_parse_initialized = true;
} }
]b4_locations_if([ ]b4_locations_if([[
/** /**
* Push parse given input from an external lexer. * Push parse given input from an external lexer.
* *
@@ -829,36 +841,32 @@ b4_dollar_popdef[]dnl
* *
* @@return <tt>YYACCEPT, YYABORT, YYPUSH_MORE</tt> * @@return <tt>YYACCEPT, YYABORT, YYPUSH_MORE</tt>
*/ */
public int push_parse (int yylextoken, b4_yystype yylexval, b4_position_type yylexpos)b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])]) public int push_parse(int yylextoken, ]b4_yystype[ yylexval, ]b4_position_type[ yylexpos)]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[ {
{ return push_parse(yylextoken, yylexval, new ]b4_location_type[(yylexpos));
return push_parse (yylextoken, yylexval, new b4_location_type (yylexpos));
} }
])[]])[ ]])])[
]b4_both_if([[ ]b4_both_if([[
/** /**
* Parse input from the scanner that was specified at object construction * Parse input from the scanner that was specified at object construction
* time. Return whether the end of the input was reached successfully. * time. Return whether the end of the input was reached successfully.
* This version of parse () is defined only when api.push-push=both. * This version of parse() is defined only when api.push-push=both.
* *
* @@return <tt>true</tt> if the parsing succeeds. Note that this does not * @@return <tt>true</tt> if the parsing succeeds. Note that this does not
* imply that there were no syntax errors. * imply that there were no syntax errors.
*/ */
public boolean parse ()]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[ public boolean parse()]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[ {
{ if (yylexer == null)
if (yylexer == null) throw new NullPointerException("Null Lexer");
throw new NullPointerException("Null Lexer"); int status;
int status; do {
do { int token = yylexer.yylex();
int token = yylexer.yylex(); ]b4_yystype[ lval = yylexer.getLVal();]b4_locations_if([[
]b4_yystype[ lval = yylexer.getLVal(); ]b4_location_type[ yyloc = new ]b4_location_type[(yylexer.getStartPos(), yylexer.getEndPos());
]b4_locations_if([dnl status = push_parse(token, lval, yyloc);]], [[
b4_location_type yyloc = new b4_location_type (yylexer.getStartPos (), status = push_parse(token, lval);]])[
yylexer.getEndPos ());])[]b4_locations_if([[ } while (status == YYPUSH_MORE);
status = push_parse(token,lval,yyloc);]], [[ return status == YYACCEPT;
status = push_parse(token,lval);]])[
} while (status == YYPUSH_MORE);
return (status == YYACCEPT);
} }
]])[ ]])[
@@ -925,7 +933,7 @@ b4_dollar_popdef[]dnl
int yychecklim = YYLAST_ - yyn + 1; int yychecklim = YYLAST_ - yyn + 1;
int yyxend = yychecklim < NTOKENS ? yychecklim : NTOKENS; int yyxend = yychecklim < NTOKENS ? yychecklim : NTOKENS;
for (int yyx = yyxbegin; yyx < yyxend; ++yyx) for (int yyx = yyxbegin; yyx < yyxend; ++yyx)
if (yycheck_[yyx + yyn] == yyx && yyx != SymbolKind.]b4_symbol_prefix[YYERROR.getCode () if (yycheck_[yyx + yyn] == yyx && yyx != SymbolKind.]b4_symbol(1, kind)[.getCode ()
&& !yyTableValueIsError (yytable_[yyx + yyn])) && !yyTableValueIsError (yytable_[yyx + yyn]))
{ {
if (yyarg == null) if (yyarg == null)
@@ -936,6 +944,8 @@ b4_dollar_popdef[]dnl
yyarg[yycount++] = SymbolKind.get (yyx); yyarg[yycount++] = SymbolKind.get (yyx);
} }
} }
if (yyarg != null && yycount == yyoffset && yyoffset < yyargn)
yyarg[yycount] = null;
return yycount - yyoffset; return yycount - yyoffset;
} }
} }
@@ -982,39 +992,39 @@ b4_dollar_popdef[]dnl
} }
]])[ ]])[
/** /**
* Report a syntax error. * Build and emit a "syntax error" message in a user-defined way.
*
* @@param ctx The context of the error.
*/ */
private void yyreportSyntaxError (Context yyctx) private void yyreportSyntaxError(Context yyctx) {]b4_parse_error_bmatch(
{]b4_parse_error_bmatch(
[custom], [[ [custom], [[
yylexer.reportSyntaxError (yyctx);]], yylexer.reportSyntaxError(yyctx);]],
[detailed\|verbose], [[ [detailed\|verbose], [[
if (yyErrorVerbose) if (yyErrorVerbose) {
{ final int argmax = 5;
final int argmax = 5; SymbolKind[] yyarg = new SymbolKind[argmax];
SymbolKind[] yyarg = new SymbolKind[argmax]; int yycount = yysyntaxErrorArguments(yyctx, yyarg, argmax);
int yycount = yysyntaxErrorArguments (yyctx, yyarg, argmax); String[] yystr = new String[yycount];
String[] yystr = new String[yycount]; for (int yyi = 0; yyi < yycount; ++yyi) {
for (int yyi = 0; yyi < yycount; ++yyi) yystr[yyi] = yyarg[yyi].getName();
yystr[yyi] = yyarg[yyi].getName();
String yyformat;
switch (yycount)
{
default:
case 0: yyformat = ]b4_trans(["syntax error"])[; break;
case 1: yyformat = ]b4_trans(["syntax error, unexpected {0}"])[; break;
case 2: yyformat = ]b4_trans(["syntax error, unexpected {0}, expecting {1}"])[; break;
case 3: yyformat = ]b4_trans(["syntax error, unexpected {0}, expecting {1} or {2}"])[; break;
case 4: yyformat = ]b4_trans(["syntax error, unexpected {0}, expecting {1} or {2} or {3}"])[; break;
case 5: yyformat = ]b4_trans(["syntax error, unexpected {0}, expecting {1} or {2} or {3} or {4}"])[; break;
} }
yyerror (]b4_locations_if([[yyctx.yylocation, ]])[new MessageFormat (yyformat).format (yystr)); String yyformat;
return; switch (yycount) {
} default:
yyerror (]b4_locations_if([[yyctx.yylocation, ]])["syntax error");]], case 0: yyformat = ]b4_trans(["syntax error"])[; break;
case 1: yyformat = ]b4_trans(["syntax error, unexpected {0}"])[; break;
case 2: yyformat = ]b4_trans(["syntax error, unexpected {0}, expecting {1}"])[; break;
case 3: yyformat = ]b4_trans(["syntax error, unexpected {0}, expecting {1} or {2}"])[; break;
case 4: yyformat = ]b4_trans(["syntax error, unexpected {0}, expecting {1} or {2} or {3}"])[; break;
case 5: yyformat = ]b4_trans(["syntax error, unexpected {0}, expecting {1} or {2} or {3} or {4}"])[; break;
}
yyerror(]b4_locations_if([[yyctx.yylocation, ]])[new MessageFormat(yyformat).format(yystr));
} else {
yyerror(]b4_locations_if([[yyctx.yylocation, ]])[]b4_trans(["syntax error"])[);
}]],
[simple], [[ [simple], [[
yyerror (]b4_locations_if([[yyctx.yylocation, ]])["syntax error");]])[ yyerror(]b4_locations_if([[yyctx.yylocation, ]])[]b4_trans(["syntax error"])[);]])[
} }
/** /**
@@ -1060,10 +1070,10 @@ b4_dollar_popdef[]dnl
/* The symbols being reduced. */ /* The symbols being reduced. */
for (int yyi = 0; yyi < yynrhs; yyi++) for (int yyi = 0; yyi < yynrhs; yyi++)
yySymbolPrint (" $" + (yyi + 1) + " =", yySymbolPrint(" $" + (yyi + 1) + " =",
SymbolKind.get (yystos_[yystack.stateAt (yynrhs - (yyi + 1))]), SymbolKind.get (yystos_[yystack.stateAt (yynrhs - (yyi + 1))]),
]b4_rhs_data(yynrhs, yyi + 1)b4_locations_if([, ]b4_rhs_data(yynrhs, yyi + 1)b4_locations_if([,
b4_rhs_location(yynrhs, yyi + 1)])[); b4_rhs_location(yynrhs, yyi + 1)])[);
}]])[ }]])[
/* YYTRANSLATE_(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM /* YYTRANSLATE_(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
+11
View File
@@ -41,6 +41,13 @@ m4_define([b4_stack_define],
: seq_ (n) : seq_ (n)
{} {}
#if 201103L <= YY_CPLUSPLUS
/// Non copyable.
stack (const stack&) = delete;
/// Non copyable.
stack& operator= (const stack&) = delete;
#endif
/// Random access. /// Random access.
/// ///
/// Index 0 returns the topmost element. /// Index 0 returns the topmost element.
@@ -126,8 +133,12 @@ m4_define([b4_stack_define],
}; };
private: private:
#if YY_CPLUSPLUS < 201103L
/// Non copyable.
stack (const stack&); stack (const stack&);
/// Non copyable.
stack& operator= (const stack&); stack& operator= (const stack&);
#endif
/// The wrapped container. /// The wrapped container.
S seq_; S seq_;
}; };
+2
View File
@@ -0,0 +1,2 @@
dnl GNU M4 treats -dV in a position-independent manner.
m4_debugmode(V)m4_traceon()dnl
+12 -2
View File
@@ -115,6 +115,13 @@ m4_define([b4_value_type_declare],
new (yyas_<T> ()) T (YY_MOVE (t)); new (yyas_<T> ()) T (YY_MOVE (t));
} }
#if 201103L <= YY_CPLUSPLUS
/// Non copyable.
semantic_type (const self_type&) = delete;
/// Non copyable.
self_type& operator= (const self_type&) = delete;
#endif
/// 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([
@@ -258,9 +265,12 @@ m4_define([b4_value_type_declare],
} }
private: private:
/// Prohibit blind copies. #if YY_CPLUSPLUS < 201103L
self_type& operator= (const self_type&); /// Non copyable.
semantic_type (const self_type&); semantic_type (const self_type&);
/// Non copyable.
self_type& operator= (const self_type&);
#endif
/// Accessor to raw memory as \a T. /// Accessor to raw memory as \a T.
template <typename T> template <typename T>
+50 -71
View File
@@ -132,6 +132,7 @@ m4_define([b4_rhs_value],
# b4_lhs_location() # b4_lhs_location()
# ----------------- # -----------------
# Expansion of @$. # Expansion of @$.
# Overparenthetized to avoid obscure problems with "foo$$bar = foo$1bar".
m4_define([b4_lhs_location], m4_define([b4_lhs_location],
[(yyloc)]) [(yyloc)])
@@ -140,6 +141,7 @@ m4_define([b4_lhs_location],
# --------------------------------- # ---------------------------------
# Expansion of @POS, where the current rule has RULE-LENGTH symbols # Expansion of @POS, where the current rule has RULE-LENGTH symbols
# on RHS. # on RHS.
# Overparenthetized to avoid obscure problems with "foo$$bar = foo$1bar".
m4_define([b4_rhs_location], m4_define([b4_rhs_location],
[(yylsp@{b4_subtract([$2], [$1])@})]) [(yylsp@{b4_subtract([$2], [$1])@})])
@@ -358,6 +360,7 @@ b4_output_begin([b4_parser_file_name])[
/* C LALR(1) parser skeleton written by Richard Stallman, by /* C LALR(1) parser skeleton written by Richard Stallman, by
simplifying the original so-called "semantic" parser. */ simplifying the original so-called "semantic" parser. */
]b4_disclaimer[
/* All symbols defined below should begin with yy or YY, to avoid /* All symbols defined below should begin with yy or YY, to avoid
infringing on user name space. This should be done even for local infringing on user name space. This should be done even for local
variables, as they might otherwise be expanded by user macros. variables, as they might otherwise be expanded by user macros.
@@ -365,7 +368,6 @@ b4_output_begin([b4_parser_file_name])[
define necessary library symbols; they are noted "INFRINGES ON define necessary library symbols; they are noted "INFRINGES ON
USER NAME SPACE" below. */ USER NAME SPACE" below. */
]b4_disclaimer[
]b4_identification[ ]b4_identification[
]b4_percent_code_get([[top]])[]dnl ]b4_percent_code_get([[top]])[]dnl
m4_if(b4_api_prefix, [yy], [], m4_if(b4_api_prefix, [yy], [],
@@ -401,50 +403,10 @@ m4_if(b4_api_prefix, [yy], [],
]b4_declare_symbol_enum[ ]b4_declare_symbol_enum[
]b4_user_post_prologue[ ]b4_user_post_prologue[
]b4_percent_code_get[]dnl ]b4_percent_code_get[
[#ifdef short
# undef short
#endif
]b4_c99_int_type_define[ ]b4_c99_int_type_define[
#ifndef YYPTRDIFF_T ]b4_sizes_types_define[
# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__
# define YYPTRDIFF_T __PTRDIFF_TYPE__
# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__
# elif defined PTRDIFF_MAX
# ifndef ptrdiff_t
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# endif
# define YYPTRDIFF_T ptrdiff_t
# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX
# else
# define YYPTRDIFF_T long
# define YYPTRDIFF_MAXIMUM LONG_MAX
# endif
#endif
#ifndef YYSIZE_T
# ifdef __SIZE_TYPE__
# define YYSIZE_T __SIZE_TYPE__
# elif defined size_t
# define YYSIZE_T size_t
# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# define YYSIZE_T size_t
# else
# define YYSIZE_T unsigned
# endif
#endif
#define YYSIZE_MAXIMUM \
YY_CAST (YYPTRDIFF_T, \
(YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \
? YYPTRDIFF_MAXIMUM \
: YY_CAST (YYSIZE_T, -1)))
#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X))
/* Stored state numbers (used for stacks). */ /* Stored state numbers (used for stacks). */
typedef ]b4_int_type(0, m4_eval(b4_states_number - 1))[ yy_state_t; typedef ]b4_int_type(0, m4_eval(b4_states_number - 1))[ yy_state_t;
@@ -463,6 +425,11 @@ typedef int yy_state_fast_t;
# define YY_(Msgid) Msgid # define YY_(Msgid) Msgid
# endif # endif
#endif #endif
]b4_has_translations_if([
#ifndef N_
# define N_(Msgid) Msgid
#endif
])[
]b4_attribute_define[ ]b4_attribute_define[
@@ -542,7 +509,7 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
# endif # endif
# endif]b4_lac_if([[ # endif]b4_lac_if([[
# define YYCOPY_NEEDED 1]])[ # define YYCOPY_NEEDED 1]])[
#endif]b4_lac_if([], [b4_parse_error_case([simple], [[/* !defined yyoverflow */]])])[ #endif /* ]b4_lac_if([[1]], [b4_parse_error_case([simple], [[!defined yyoverflow]], [[1]])])[ */
#if (! defined yyoverflow \ #if (! defined yyoverflow \
&& (! defined __cplusplus \ && (! defined __cplusplus \
@@ -676,8 +643,8 @@ yysymbol_name (yysymbol_kind_t yysymbol)
static const char *const yy_sname[] = static const char *const yy_sname[] =
{ {
]b4_symbol_names[ ]b4_symbol_names[
};]m4_ifdef([b4_translatable], [[ };]b4_has_translations_if([[
/* YYTRANSLATABLE[SYMBOL-NUM] -- Whether YYTNAME[SYMBOL-NUM] is /* YYTRANSLATABLE[SYMBOL-NUM] -- Whether YY_SNAME[SYMBOL-NUM] is
internationalizable. */ internationalizable. */
static ]b4_int_type_for([b4_translatable])[ yytranslatable[] = static ]b4_int_type_for([b4_translatable])[ yytranslatable[] =
{ {
@@ -690,14 +657,14 @@ yysymbol_name (yysymbol_kind_t yysymbol)
}]])[ }]])[
#endif #endif
# ifdef YYPRINT #ifdef YYPRINT
/* YYTOKNUM[NUM] -- (External) token number corresponding to the /* YYTOKNUM[NUM] -- (External) token number corresponding to the
(internal) symbol number NUM (which must be that of a token). */ (internal) symbol number NUM (which must be that of a token). */
static const ]b4_int_type_for([b4_toknum])[ yytoknum[] = static const ]b4_int_type_for([b4_toknum])[ yytoknum[] =
{ {
]b4_toknum[ ]b4_toknum[
}; };
# endif #endif
#define YYPACT_NINF (]b4_pact_ninf[) #define YYPACT_NINF (]b4_pact_ninf[)
@@ -741,6 +708,9 @@ enum { YYENOMEM = -2 };
} \ } \
while (0) while (0)
/* Backward compatibility with an undocumented macro.
Use ]b4_symbol(1, id)[ or ]b4_symbol(2, id)[. */
#define YYERRCODE ]b4_symbol(2, id)[
]b4_locations_if([[ ]b4_locations_if([[
]b4_yylloc_default_define[ ]b4_yylloc_default_define[
#define YYRHSLOC(Rhs, K) ((Rhs)[K]) #define YYRHSLOC(Rhs, K) ((Rhs)[K])
@@ -762,13 +732,13 @@ do { \
]b4_yy_location_print_define[ ]b4_yy_location_print_define[
# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ # define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \
do { \ do { \
if (yydebug) \ if (yydebug) \
{ \ { \
YYFPRINTF (stderr, "%s ", Title); \ YYFPRINTF (stderr, "%s ", Title); \
yy_symbol_print (stderr, \ yy_symbol_print (stderr, \
Type, Value]b4_locations_if([, Location])[]b4_user_args[); \ Kind, Value]b4_locations_if([, Location])[]b4_user_args[); \
YYFPRINTF (stderr, "\n"); \ YYFPRINTF (stderr, "\n"); \
} \ } \
} while (0) } while (0)
@@ -818,9 +788,8 @@ yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp,]b4_locations_if([[ YYLTYPE *
YYFPRINTF (stderr, " $%d = ", yyi + 1); YYFPRINTF (stderr, " $%d = ", yyi + 1);
yy_symbol_print (stderr, yy_symbol_print (stderr,
YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]), YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]),
&]b4_rhs_value(yynrhs, yyi + 1)[ &]b4_rhs_value(yynrhs, yyi + 1)[]b4_locations_if([,
]b4_locations_if([, &]b4_rhs_location(yynrhs, yyi + 1))[]dnl &]b4_rhs_location(yynrhs, yyi + 1))[]b4_user_args[);
b4_user_args[);
YYFPRINTF (stderr, "\n"); YYFPRINTF (stderr, "\n");
} }
} }
@@ -836,7 +805,7 @@ do { \
int yydebug; int yydebug;
#else /* !]b4_api_PREFIX[DEBUG */ #else /* !]b4_api_PREFIX[DEBUG */
# define YYDPRINTF(Args) ((void) 0) # define YYDPRINTF(Args) ((void) 0)
# define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_SYMBOL_PRINT(Title, Kind, Value, Location)
# define YY_STACK_PRINT(Bottom, Top) # define YY_STACK_PRINT(Bottom, Top)
# define YY_REDUCE_PRINT(Rule) # define YY_REDUCE_PRINT(Rule)
#endif /* !]b4_api_PREFIX[DEBUG */ #endif /* !]b4_api_PREFIX[DEBUG */
@@ -1149,7 +1118,7 @@ yypcontext_expected_tokens (const yypcontext_t *yyctx,
for (yyx = 0; yyx < YYNTOKENS; ++yyx) for (yyx = 0; yyx < YYNTOKENS; ++yyx)
{ {
yysymbol_kind_t yysym = YY_CAST (yysymbol_kind_t, yyx); yysymbol_kind_t yysym = YY_CAST (yysymbol_kind_t, yyx);
if (yysym != ]b4_symbol_prefix[YYERROR && yysym != ]b4_symbol_prefix[YYUNDEF) if (yysym != ]b4_symbol(1, kind)[ && yysym != ]b4_symbol_prefix[YYUNDEF)
switch (yy_lac (]b4_push_if([[yyps->yyesa, &yyps->yyes, &yyps->yyes_capacity, yyps->yyssp, yysym]], switch (yy_lac (]b4_push_if([[yyps->yyesa, &yyps->yyes, &yyps->yyes_capacity, yyps->yyssp, yysym]],
[[yyctx->yyesa, yyctx->yyes, yyctx->yyes_capacity, yyctx->yyssp, yysym]])[)) [[yyctx->yyesa, yyctx->yyes, yyctx->yyes_capacity, yyctx->yyssp, yysym]])[))
{ {
@@ -1178,7 +1147,7 @@ yypcontext_expected_tokens (const yypcontext_t *yyctx,
int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
int yyx; int yyx;
for (yyx = yyxbegin; yyx < yyxend; ++yyx) for (yyx = yyxbegin; yyx < yyxend; ++yyx)
if (yycheck[yyx + yyn] == yyx && yyx != ]b4_symbol_prefix[YYERROR if (yycheck[yyx + yyn] == yyx && yyx != ]b4_symbol(1, kind)[
&& !yytable_value_is_error (yytable[yyx + yyn])) && !yytable_value_is_error (yytable[yyx + yyn]))
{ {
if (!yyarg) if (!yyarg)
@@ -1189,6 +1158,8 @@ yypcontext_expected_tokens (const yypcontext_t *yyctx,
yyarg[yycount++] = YY_CAST (yysymbol_kind_t, yyx); yyarg[yycount++] = YY_CAST (yysymbol_kind_t, yyx);
} }
}]])[ }]])[
if (yyarg && yycount == 0 && 0 < yyargn)
yyarg[0] = ]b4_symbol(-2, kind)[;
return yycount; return yycount;
} }
@@ -1400,10 +1371,10 @@ yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg,
switch (yycount) switch (yycount)
{ {
# define YYCASE_(N, S) \ #define YYCASE_(N, S) \
case N: \ case N: \
yyformat = S; \ yyformat = S; \
break break
default: /* Avoid compiler warnings. */ default: /* Avoid compiler warnings. */
YYCASE_(0, YY_("syntax error")); YYCASE_(0, YY_("syntax error"));
YYCASE_(1, YY_("syntax error, unexpected %s")); YYCASE_(1, YY_("syntax error, unexpected %s"));
@@ -1411,7 +1382,7 @@ yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg,
YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
# undef YYCASE_ #undef YYCASE_
} }
/* Compute error message size. Don't count the "%s"s, but reserve /* Compute error message size. Don't count the "%s"s, but reserve
@@ -1509,7 +1480,7 @@ yypull_parse (yypstate *yyps]b4_user_formals[)
]b4_parse_state_variable_macros([b4_pstate_macro_define])[ ]b4_parse_state_variable_macros([b4_pstate_macro_define])[
/* Initialize the parser data structure. */ /* Initialize the parser data structure. */
void static void
yypstate_clear (yypstate *yyps) yypstate_clear (yypstate *yyps)
{ {
]b4_initialize_parser_state_variables[ ]b4_initialize_parser_state_variables[
@@ -1693,7 +1664,7 @@ yysetstate:
YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyss_alloc, yyss);
YYSTACK_RELOCATE (yyvs_alloc, yyvs);]b4_locations_if([ YYSTACK_RELOCATE (yyvs_alloc, yyvs);]b4_locations_if([
YYSTACK_RELOCATE (yyls_alloc, yyls);])[ YYSTACK_RELOCATE (yyls_alloc, yyls);])[
# undef YYSTACK_RELOCATE # undef YYSTACK_RELOCATE
if (yyss1 != yyssa) if (yyss1 != yyssa)
YYSTACK_FREE (yyss1); YYSTACK_FREE (yyss1);
} }
@@ -1765,6 +1736,17 @@ yyread_pushed_token:]])[
yytoken = ]b4_symbol(0, [kind])[; yytoken = ]b4_symbol(0, [kind])[;
YYDPRINTF ((stderr, "Now at end of input.\n")); YYDPRINTF ((stderr, "Now at end of input.\n"));
} }
else if (yychar == ]b4_symbol(1, [id])[)
{
/* The scanner already issued an error message, process directly
to error recovery. But do not keep the error token as
lookahead, it is too special and may lead us to an endless
loop in error recovery. */
yychar = ]b4_symbol(2, [id])[;
yytoken = ]b4_symbol(1, [kind])[;]b4_locations_if([[
yyerror_range[1] = yylloc;]])[
goto yyerrlab1;
}
else else
{ {
yytoken = YYTRANSLATE (yychar); yytoken = YYTRANSLATE (yychar);
@@ -1947,9 +1929,8 @@ yyerrlab:
goto yyexhaustedlab; goto yyexhaustedlab;
}]])[ }]])[
} }
]b4_locations_if([[
]b4_locations_if([[ yyerror_range[1] = yylloc;]])[ yyerror_range[1] = yylloc;]])[
if (yyerrstatus == 3) if (yyerrstatus == 3)
{ {
/* If just tried and failed to reuse lookahead token after an /* If just tried and failed to reuse lookahead token after an
@@ -1998,14 +1979,14 @@ yyerrorlab:
yyerrlab1: yyerrlab1:
yyerrstatus = 3; /* Each real token shifted decrements this. */ yyerrstatus = 3; /* Each real token shifted decrements this. */
// Pop stack until we find a state that shifts the error token. /* Pop stack until we find a state that shifts the error token. */
for (;;) for (;;)
{ {
yyn = yypact[yystate]; yyn = yypact[yystate];
if (!yypact_value_is_default (yyn)) if (!yypact_value_is_default (yyn))
{ {
yyn += ]b4_symbol_prefix[YYERROR; yyn += ]b4_symbol(1, kind)[;
if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == ]b4_symbol_prefix[YYERROR) if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == ]b4_symbol(1, kind)[)
{ {
yyn = yytable[yyn]; yyn = yytable[yyn];
if (0 < yyn) if (0 < yyn)
@@ -2034,10 +2015,8 @@ yyerrlab1:
YY_IGNORE_MAYBE_UNINITIALIZED_END YY_IGNORE_MAYBE_UNINITIALIZED_END
]b4_locations_if([[ ]b4_locations_if([[
yyerror_range[2] = yylloc; yyerror_range[2] = yylloc;
/* Using YYLLOC is tempting, but would change the location of ++yylsp;
the lookahead. YYLOC is available though. */ YYLLOC_DEFAULT (*yylsp, yyerror_range, 2);]])[
YYLLOC_DEFAULT (yyloc, yyerror_range, 2);
*++yylsp = yyloc;]])[
/* Shift the error token. */ /* Shift the error token. */
YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp); YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp);
+218 -96
View File
@@ -300,10 +300,7 @@ Bison Declarations
Parser C-Language Interface Parser C-Language Interface
* Parser Function:: How to call @code{yyparse} and what it returns. * Parser Function:: How to call @code{yyparse} and what it returns.
* Push Parser Function:: How to call @code{yypush_parse} and what it returns. * Push Parser Interface:: How to create, use, and destroy push parsers.
* Pull Parser Function:: How to call @code{yypull_parse} and what it returns.
* Parser Create Function:: How to call @code{yypstate_new} and what it returns.
* Parser Delete Function:: How to call @code{yypstate_delete} and what it returns.
* Lexical:: You must supply a function @code{yylex} * Lexical:: You must supply a function @code{yylex}
which reads tokens. which reads tokens.
* Error Reporting:: Passing error messages to the user. * Error Reporting:: Passing error messages to the user.
@@ -314,6 +311,7 @@ Parser C-Language Interface
The Lexical Analyzer Function @code{yylex} The Lexical Analyzer Function @code{yylex}
* Calling Convention:: How @code{yyparse} calls @code{yylex}. * Calling Convention:: How @code{yyparse} calls @code{yylex}.
* Special Tokens:: Signaling end-of-file and errors to the parser.
* Tokens from Literals:: Finding token kinds from string aliases. * Tokens from Literals:: Finding token kinds from string aliases.
* Token Values:: How @code{yylex} must return the semantic value * Token Values:: How @code{yylex} must return the semantic value
of the token it has read. of the token it has read.
@@ -1881,6 +1879,7 @@ Here is the code for the lexical analyzer:
and tabs, and returns 0 for end-of-input. */ and tabs, and returns 0 for end-of-input. */
#include <ctype.h> #include <ctype.h>
#include <stdlib.h>
@end group @end group
@group @group
@@ -1897,7 +1896,8 @@ yylex (void)
if (c == '.' || isdigit (c)) if (c == '.' || isdigit (c))
@{ @{
ungetc (c, stdin); ungetc (c, stdin);
scanf ("%lf", &yylval); if (scanf ("%lf", &yylval) != 1)
abort ();
return NUM; return NUM;
@} @}
@end group @end group
@@ -2368,9 +2368,9 @@ yylex (void)
@end group @end group
@end example @end example
Basically, the lexical analyzer performs the same processing as before: Basically, the lexical analyzer performs the same processing as before: it
it skips blanks and tabs, and reads numbers or single-character tokens. skips blanks and tabs, and reads numbers or single-character tokens. In
In addition, it updates @code{yylloc}, the global variable (of type addition, it updates @code{yylloc}, the global variable (of type
@code{YYLTYPE}) containing the token's location. @code{YYLTYPE}) containing the token's location.
Now, each time this function returns a token, the parser has its kind as Now, each time this function returns a token, the parser has its kind as
@@ -2730,7 +2730,8 @@ yylex (void)
if (c == '.' || isdigit (c)) if (c == '.' || isdigit (c))
@{ @{
ungetc (c, stdin); ungetc (c, stdin);
scanf ("%lf", &yylval.NUM); if (scanf ("%lf", &yylval.NUM) != 1)
abort ();
return NUM; return NUM;
@} @}
@end group @end group
@@ -2757,10 +2758,10 @@ Bison generated a definition of @code{YYSTYPE} with a member named
if (bufsize <= i) if (bufsize <= i)
@{ @{
bufsize = 2 * bufsize + 40; bufsize = 2 * bufsize + 40;
symbuf = realloc (symbuf, bufsize); symbuf = realloc (symbuf, (size_t) bufsize);
@} @}
/* Add this character to the buffer. */ /* Add this character to the buffer. */
symbuf[i++] = c; symbuf[i++] = (char) c;
/* Get another character. */ /* Get another character. */
c = getchar (); c = getchar ();
@} @}
@@ -4504,12 +4505,17 @@ typedef struct YYLTYPE
@} YYLTYPE; @} YYLTYPE;
@end example @end example
While default locations represent a range in the source file(s), this is not
a requirement. It could be a single point or just a line number, or even
more complex structures.
When @code{YYLTYPE} is not defined, at the beginning of the parsing, Bison When @code{YYLTYPE} is not defined, at the beginning of the parsing, Bison
initializes all these fields to 1 for @code{yylloc}. To initialize initializes all these fields to 1 for @code{yylloc}. To initialize
@code{yylloc} with a custom location type (or to chose a different @code{yylloc} with a custom location type (or to chose a different
initialization), use the @code{%initial-action} directive. @xref{Initial initialization), use the @code{%initial-action} directive. @xref{Initial
Action Decl}. Action Decl}.
@node Actions and Locations @node Actions and Locations
@subsection Actions and Locations @subsection Actions and Locations
@cindex location actions @cindex location actions
@@ -6131,7 +6137,7 @@ the @code{full} value was introduced in Bison 2.7
@deffn Directive {%define api.push-pull} @var{kind} @deffn Directive {%define api.push-pull} @var{kind}
@itemize @bullet @itemize @bullet
@item Language(s): C (deterministic parsers only) @item Language(s): C (deterministic parsers only), Java
@item Purpose: Request a pull parser, a push parser, or both. @item Purpose: Request a pull parser, a push parser, or both.
@xref{Push Decl}. @xref{Push Decl}.
@@ -6921,10 +6927,7 @@ in the grammar file, you are likely to run into trouble.
@menu @menu
* Parser Function:: How to call @code{yyparse} and what it returns. * Parser Function:: How to call @code{yyparse} and what it returns.
* Push Parser Function:: How to call @code{yypush_parse} and what it returns. * Push Parser Interface:: How to create, use, and destroy push parsers.
* Pull Parser Function:: How to call @code{yypull_parse} and what it returns.
* Parser Create Function:: How to call @code{yypstate_new} and what it returns.
* Parser Delete Function:: How to call @code{yypstate_delete} and what it returns.
* Lexical:: You must supply a function @code{yylex} * Lexical:: You must supply a function @code{yylex}
which reads tokens. which reads tokens.
* Error Reporting:: Passing error messages to the user. * Error Reporting:: Passing error messages to the user.
@@ -7027,16 +7030,40 @@ void yyerror (YYLTYPE *llocp, int *randomness, const char *msg);
int yyparse (int *randomness); int yyparse (int *randomness);
@end example @end example
@node Push Parser Function @node Push Parser Interface
@section The Push Parser Function @code{yypush_parse} @section Push Parser Interface
@findex yypush_parse
You call the function @code{yypush_parse} to parse a single token. This @findex yypstate_new
You call the function @code{yypstate_new} to create a new parser instance.
This function is available if either the @samp{%define api.push-pull push}
or @samp{%define api.push-pull both} declaration is used. @xref{Push Decl}.
@deftypefun {yypstate*} yypstate_new (@code{void})
@anchor{yypstate_new}
Return a valid parser instance if there is memory available, 0 otherwise.
In impure mode, it will also return 0 if a parser instance is currently
allocated.
@end deftypefun
@findex yypstate_delete
You call the function @code{yypstate_delete} to delete a parser instance.
function is available if either the @samp{%define api.push-pull push} or function is available if either the @samp{%define api.push-pull push} or
@samp{%define api.push-pull both} declaration is used. @samp{%define api.push-pull both} declaration is used.
@xref{Push Decl}. @xref{Push Decl}.
@deftypefun void yypstate_delete (@code{yypstate *}@var{yyps})
@anchor{yypstate_delete}
Reclaim the memory associated with a parser instance. After this call, you
should no longer attempt to use the parser instance.
@end deftypefun
@findex yypush_parse
You call the function @code{yypush_parse} to parse a single token. This
function is available if either the @samp{%define api.push-pull push} or
@samp{%define api.push-pull both} declaration is used. @xref{Push Decl}.
@deftypefun int yypush_parse (@code{yypstate *}@var{yyps}) @deftypefun int yypush_parse (@code{yypstate *}@var{yyps})
@anchor{yypush_parse}
The value returned by @code{yypush_parse} is the same as for @code{yyparse} The value returned by @code{yypush_parse} is the same as for @code{yyparse}
with the following exception: it returns @code{YYPUSH_MORE} if more input is with the following exception: it returns @code{YYPUSH_MORE} if more input is
required to finish parsing the grammar. required to finish parsing the grammar.
@@ -7050,50 +7077,35 @@ reuse. For example, a calculator application which parses each input line
as an expression can just keep reusing the same @code{yyps} even if an input as an expression can just keep reusing the same @code{yyps} even if an input
was invalid. was invalid.
@node Pull Parser Function
@section The Pull Parser Function @code{yypull_parse}
@findex yypull_parse
You call the function @code{yypull_parse} to parse the rest of the input You call the function @code{yypull_parse} to parse the rest of the input
stream. This function is available if the @samp{%define api.push-pull both} stream. This function is available if the @samp{%define api.push-pull both}
declaration is used. declaration is used. @xref{Push Decl}.
@xref{Push Decl}.
@deftypefun int yypull_parse (@code{yypstate *}@var{yyps}) @deftypefun int yypull_parse (@code{yypstate *}@var{yyps})
@anchor{yypull_parse}
The value returned by @code{yypull_parse} is the same as for @code{yyparse}. The value returned by @code{yypull_parse} is the same as for @code{yyparse}.
The parser instance @code{yyps} may be reused for new parses. The parser instance @code{yyps} may be reused for new parses.
@end deftypefun @end deftypefun
@node Parser Create Function @deftypefun int yypstate_expected_tokens (@code{const yypstate *}yyps, @code{yysymbol_kind_t} @var{argv}@code{[]}, @code{int} @var{argc})
@section The Parser Create Function @code{yystate_new} Fill @var{argv} with the expected tokens, which never includes
@findex yypstate_new @code{YYSYMBOL_YYEMPTY}, @code{YYSYMBOL_YYerror}, or
@code{YYSYMBOL_YYUNDEF}.
You call the function @code{yypstate_new} to create a new parser instance. Never put more than @var{argc} elements into @var{argv}, and on success
This function is available if either the @samp{%define api.push-pull push} or return the number of tokens stored in @var{argv}. If there are more
@samp{%define api.push-pull both} declaration is used. expected tokens than @var{argc}, fill @var{argv} up to @var{argc} and return
@xref{Push Decl}. 0. If there are no expected tokens, also return 0, but set @code{argv[0]}
to @code{YYSYMBOL_YYEMPTY}.
@deftypefun {yypstate*} yypstate_new (@code{void}) When LAC is enabled, may return a negative number on errors,
The function will return a valid parser instance if there was memory available such as @code{YYENOMEM} on memory exhaustion.
or 0 if no memory was available.
In impure mode, it will also return 0 if a parser instance is currently If @var{argv} is null, return the size needed to store all the possible
allocated. values, which is always less than @code{YYNTOKENS}.
@end deftypefun @end deftypefun
@node Parser Delete Function
@section The Parser Delete Function @code{yystate_delete}
@findex yypstate_delete
You call the function @code{yypstate_delete} to delete a parser instance.
function is available if either the @samp{%define api.push-pull push} or
@samp{%define api.push-pull both} declaration is used.
@xref{Push Decl}.
@deftypefun void yypstate_delete (@code{yypstate *}@var{yyps})
This function will reclaim the memory associated with a parser instance.
After this call, you should no longer attempt to use the parser instance.
@end deftypefun
@node Lexical @node Lexical
@section The Lexical Analyzer Function @code{yylex} @section The Lexical Analyzer Function @code{yylex}
@@ -7115,6 +7127,7 @@ that need it. @xref{Invocation}.
@menu @menu
* Calling Convention:: How @code{yyparse} calls @code{yylex}. * Calling Convention:: How @code{yyparse} calls @code{yylex}.
* Special Tokens:: Signaling end-of-file and errors to the parser.
* Tokens from Literals:: Finding token kinds from string aliases. * Tokens from Literals:: Finding token kinds from string aliases.
* Token Values:: How @code{yylex} must return the semantic value * Token Values:: How @code{yylex} must return the semantic value
of the token it has read. of the token it has read.
@@ -7168,6 +7181,49 @@ This interface has been designed so that the output from the @code{lex}
utility can be used without change as the definition of @code{yylex}. utility can be used without change as the definition of @code{yylex}.
@node Special Tokens
@subsection Special Tokens
In addition to the user defined tokens, Bison generates a few special tokens
that @code{yylex} may return.
The @code{YYEOF} token denotes the end of file, and signals to the parser
that there is nothing left afterwards. @xref{Calling Convention}, for an
example.
Returning @code{YYUNDEF} tells the parser that some lexical error was found.
It will emit an error message about an ``invalid token'', and enter
error-recovery (@pxref{Error Recovery}). Returning an unknown token kind
results in the exact same behavior.
Returning @code{YYerror} requires the parser to enter error-recovery
@emph{without} emitting an error message. This way the lexical analyzer can
produce an accurate error messages about the invalid input (something the
parser cannot do), and yet benefit from the error-recovery features of the
parser.
@example
int
yylex (void)
@{
@dots{}
switch (c)
@{
@dots{}
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
@dots{}
return TOK_NUM;
@dots{}
case EOF:
return YYEOF;
default:
yyerror ("syntax error: invalid character: %c", c);
return YYerror;
@}
@}
@end example
@node Tokens from Literals @node Tokens from Literals
@subsection Finding Tokens by String Literals @subsection Finding Tokens by String Literals
@@ -7471,7 +7527,7 @@ enum yysymbol_kind_t
@{ @{
YYSYMBOL_YYEMPTY = -2, /* No symbol. */ YYSYMBOL_YYEMPTY = -2, /* No symbol. */
YYSYMBOL_YYEOF = 0, /* "end of file" */ YYSYMBOL_YYEOF = 0, /* "end of file" */
YYSYMBOL_YYERROR = 1, /* error */ YYSYMBOL_YYerror = 1, /* error */
YYSYMBOL_YYUNDEF = 2, /* "invalid token" */ YYSYMBOL_YYUNDEF = 2, /* "invalid token" */
YYSYMBOL_PLUS = 3, /* "+" */ YYSYMBOL_PLUS = 3, /* "+" */
YYSYMBOL_MINUS = 4, /* "-" */ YYSYMBOL_MINUS = 4, /* "-" */
@@ -7497,24 +7553,31 @@ The location of the syntax error (that of the unexpected token).
@deftypefun int yypcontext_expected_tokens (@code{const yypcontext_t *}ctx, @code{yysymbol_kind_t} @var{argv}@code{[]}, @code{int} @var{argc}) @deftypefun int yypcontext_expected_tokens (@code{const yypcontext_t *}ctx, @code{yysymbol_kind_t} @var{argv}@code{[]}, @code{int} @var{argc})
Fill @var{argv} with the expected tokens, which never includes Fill @var{argv} with the expected tokens, which never includes
@code{YYSYMBOL_YYEMPTY}, @code{YYSYMBOL_YYERROR}, or @code{YYSYMBOL_YYEMPTY}, @code{YYSYMBOL_YYerror}, or
@code{YYSYMBOL_YYUNDEF}. @code{YYSYMBOL_YYUNDEF}.
Never put more than @var{argc} elements into @var{argv}, and on success Never put more than @var{argc} elements into @var{argv}, and on success
return the effective number of tokens stored in @var{argv}. Return 0 if return the number of tokens stored in @var{argv}. If there are more
there are more than @var{argc} expected tokens, yet fill @var{argv} up to expected tokens than @var{argc}, fill @var{argv} up to @var{argc} and return
@var{argc}. When LAC is enabled, may return a negative number on errors, 0. If there are no expected tokens, also return 0, but set @code{argv[0]}
to @code{YYSYMBOL_YYEMPTY}.
When LAC is enabled, may return a negative number on errors,
such as @code{YYENOMEM} on memory exhaustion. such as @code{YYENOMEM} on memory exhaustion.
If @var{argv} is null, return the size needed to store all the possible If @var{argv} is null, return the size needed to store all the possible
values, which is always less than @code{YYNTOKENS}. values, which is always less than @code{YYNTOKENS}.
@end deftypefun @end deftypefun
@deftypefun {const char *} yysymbol_name (@code{symbol_kind_t} @var{symbol}) @deftypefun {@r{string type}} yysymbol_name (@code{symbol_kind_t} @var{symbol})
The name of the symbol whose kind is @var{symbol}, possibly translated. The name of the symbol whose kind is @var{symbol}, possibly translated.
Depending on the options, may return a @code{const char*} or a
@code{std::string}.
@end deftypefun @end deftypefun
A custom syntax error function looks as follows. A custom syntax error function looks as follows. This implementation is
inappropriate for internationalization, see the @file{c/bistromathic}
example for a better alternative.
@example @example
int int
@@ -7606,11 +7669,11 @@ recovery.
In either case, the rest of the action is not executed. In either case, the rest of the action is not executed.
@end deffn @end deffn
@deffn {Macro} YYEMPTY @deffn {Value} YYEMPTY
Value stored in @code{yychar} when there is no lookahead token. Value stored in @code{yychar} when there is no lookahead token.
@end deffn @end deffn
@deffn {Macro} YYEOF @deffn {Value} YYEOF
Value stored in @code{yychar} when the lookahead is the end of the input Value stored in @code{yychar} when the lookahead is the end of the input
stream. stream.
@end deffn @end deffn
@@ -7802,7 +7865,7 @@ or @code{detailed}, token aliases can be internationalized:
%token %token
'\n' _("end of line") '\n' _("end of line")
<double> <double>
NUM _("double precision number") NUM _("number")
<symrec*> <symrec*>
FUN _("function") FUN _("function")
VAR _("variable") VAR _("variable")
@@ -8253,7 +8316,7 @@ the lookahead token has no precedence, then the default is to shift.
@subsection Using Precedence For Non Operators @subsection Using Precedence For Non Operators
Using properly precedence and associativity directives can help fixing Using properly precedence and associativity directives can help fixing
shift/reduce conflicts that do not involve arithmetics-like operators. For shift/reduce conflicts that do not involve arithmetic-like operators. For
instance, the ``dangling @code{else}'' problem (@pxref{Shift/Reduce}) can be instance, the ``dangling @code{else}'' problem (@pxref{Shift/Reduce}) can be
solved elegantly in two different ways. solved elegantly in two different ways.
@@ -9596,10 +9659,10 @@ and understand the parser run-time traces (@pxref{Tracing}).
@node Understanding @node Understanding
@section Understanding Your Parser @section Understanding Your Parser
As documented elsewhere (@pxref{Algorithm}) As documented elsewhere (@pxref{Algorithm}) Bison parsers are
Bison parsers are @dfn{shift/reduce automata}. In some cases (much more @dfn{shift/reduce automata}. In some cases (much more frequent than one
frequent than one would hope), looking at this automaton is required to would hope), looking at this automaton is required to tune or simply fix a
tune or simply fix a parser. parser.
The textual file is generated when the options @option{--report} or The textual file is generated when the options @option{--report} or
@option{--verbose} are specified, see @ref{Invocation}. Its name is made by @option{--verbose} are specified, see @ref{Invocation}. Its name is made by
@@ -10555,6 +10618,26 @@ For compatibility with POSIX, the standard Bison distribution also contains
a shell script called @command{yacc} that invokes Bison with the @option{-y} a shell script called @command{yacc} that invokes Bison with the @option{-y}
option. option.
@sp 1
The exit status of @command{bison} is:
@table @asis
@item 0 (success)
when there were no errors. Warnings, which are diagnostics about dubious
constructs, do not change the exit status, unless they are turned into
errors (@pxref{-Werror,,@option{-Werror}}).
@item 1 (failure)
when there were errors. No file was generated (except the reports generated
by @option{--verbose}, etc.). In particular, the output files that possibly
existed were not changed.
@item 63 (mismatch)
when @command{bison} does not meet the version requirements of the grammar
file. @xref{Require Decl}. No file was generated or changed.
@end table
@menu @menu
* Bison Options:: All the options described in detail, * Bison Options:: All the options described in detail,
in alphabetical order by short options. in alphabetical order by short options.
@@ -10601,7 +10684,7 @@ Print the version number of Bison and exit.
Print the name of the directory containing locale-dependent data. Print the name of the directory containing locale-dependent data.
@item --print-datadir @item --print-datadir
Print the name of the directory containing skeletons and XSLT. Print the name of the directory containing skeletons, CSS and XSLT.
@item -u @item -u
@item --update @item --update
@@ -10948,6 +11031,7 @@ instance, @option{-Wno-yacc} will hide the warnings about
POSIX Yacc incompatibilities. POSIX Yacc incompatibilities.
@item -Werror @item -Werror
@anchor{-Werror}
Turn enabled warnings for every @var{category} into errors, unless they are Turn enabled warnings for every @var{category} into errors, unless they are
explicitly disabled by @option{-Wno-error=@var{category}}. explicitly disabled by @option{-Wno-error=@var{category}}.
@@ -11545,7 +11629,7 @@ struct token
@{ @{
YYEMPTY = -2, // No token. YYEMPTY = -2, // No token.
YYEOF = 0, // "end of file" YYEOF = 0, // "end of file"
YYERRCODE = 256, // error YYerror = 256, // error
YYUNDEF = 257, // "invalid token" YYUNDEF = 257, // "invalid token"
PLUS = 258, // "+" PLUS = 258, // "+"
MINUS = 259, // "-" MINUS = 259, // "-"
@@ -12062,9 +12146,10 @@ Fill @var{argv} with the expected tokens, which never includes
@code{symbol_kind::S_YYUNDEF}. @code{symbol_kind::S_YYUNDEF}.
Never put more than @var{argc} elements into @var{argv}, and on success Never put more than @var{argc} elements into @var{argv}, and on success
return the effective number of tokens stored in @var{argv}. Return 0 if return the number of tokens stored in @var{argv}. If there are more
there are more than @var{argc} expected tokens, yet fill @var{argv} up to expected tokens than @var{argc}, fill @var{argv} up to @var{argc} and return
@var{argc}. 0. If there are no expected tokens, also return 0, but set @code{argv[0]}
to @code{symbol_kind::S_YYEMPTY}.
If @var{argv} is null, return the size needed to store all the possible If @var{argv} is null, return the size needed to store all the possible
values, which is always less than @code{YYNTOKENS}. values, which is always less than @code{YYNTOKENS}.
@@ -12072,9 +12157,13 @@ values, which is always less than @code{YYNTOKENS}.
@deftypemethod {parser} {const char *} symbol_name (@code{symbol_kind_t} @var{symbol}) @code{const} @deftypemethod {parser} {const char *} symbol_name (@code{symbol_kind_t} @var{symbol}) @code{const}
The name of the symbol whose kind is @var{symbol}, possibly translated. The name of the symbol whose kind is @var{symbol}, possibly translated.
Returns a @code{std::string} when @code{parse.error} is @code{verbose}.
@end deftypemethod @end deftypemethod
A custom syntax error function looks as follows. A custom syntax error function looks as follows. This implementation is
inappropriate for internationalization, see the @file{c/bistromathic}
example for a better alternative.
@example @example
void void
@@ -12202,6 +12291,12 @@ applicable) location.
The kind of this symbol. The kind of this symbol.
@end deftypemethod @end deftypemethod
@deftypemethod {symbol_type} {const char *} name () @code{const}
The name of the kind of this symbol.
Returns a @code{std::string} when @code{parse.error} is @code{verbose}.
@end deftypemethod
@sp 1 @sp 1
For each token kind, Bison generates named constructors as follows. For each token kind, Bison generates named constructors as follows.
@@ -12330,7 +12425,7 @@ interactions. A hand-written scanner is actually easier to interface with.
@node Calc++ --- C++ Calculator @node Calc++ --- C++ Calculator
@subsubsection Calc++ --- C++ Calculator @subsubsection Calc++ --- C++ Calculator
Of course the grammar is dedicated to arithmetics, a single expression, Of course the grammar is dedicated to arithmetic, a single expression,
possibly preceded by variable assignments. An environment containing possibly preceded by variable assignments. An environment containing
possibly predefined variables such as @code{one} and @code{two}, is possibly predefined variables such as @code{one} and @code{two}, is
exchanged with the parser. An example of valid input follows. exchanged with the parser. An example of valid input follows.
@@ -12950,9 +13045,6 @@ of the parser is always local to an instance of the parser class.
Therefore, all Java parsers are ``pure'', and the @code{%define api.pure} Therefore, all Java parsers are ``pure'', and the @code{%define api.pure}
directive does nothing when used in Java. directive does nothing when used in Java.
Push parsers are currently unsupported in Java and @code{%define
api.push-pull} have no effect.
GLR parsers are currently unsupported in Java. Do not use the GLR parsers are currently unsupported in Java. Do not use the
@code{glr-parser} directive. @code{glr-parser} directive.
@@ -13224,9 +13316,10 @@ Fill @var{argv} with the expected tokens, which never includes
@code{SymbolKind.S_YYERROR}, or @code{SymbolKind.S_YYUNDEF}. @code{SymbolKind.S_YYERROR}, or @code{SymbolKind.S_YYUNDEF}.
Never put more than @var{argc} elements into @var{argv}, and on success Never put more than @var{argc} elements into @var{argv}, and on success
return the effective number of tokens stored in @var{argv}. Return 0 if return the number of tokens stored in @var{argv}. If there are more
there are more than @var{argc} expected tokens, yet fill @var{argv} up to expected tokens than @var{argc}, fill @var{argv} up to @var{argc} and return
@var{argc}. 0. If there are no expected tokens, also return 0, but set @code{argv[0]}
to @code{null}.
If @var{argv} is null, return the size needed to store all the possible If @var{argv} is null, return the size needed to store all the possible
values, which is always less than @code{YYNTOKENS}. values, which is always less than @code{YYNTOKENS}.
@@ -13267,9 +13360,9 @@ changed using @code{%define api.location.type @{@var{class-name}@}}.
@end deftypemethod @end deftypemethod
@deftypemethod {Lexer} {int} yylex () @deftypemethod {Lexer} {int} yylex ()
Return the next token. Its type is the return value, its semantic Return the next token. Its type is the return value, its semantic value and
value and location are saved and returned by the their methods in the location are saved and returned by the their methods in the interface. Not
interface. needed for push-only parsers.
Use @samp{%define lex_throws} to specify any uncaught exceptions. Use @samp{%define lex_throws} to specify any uncaught exceptions.
Default is @code{java.io.IOException}. Default is @code{java.io.IOException}.
@@ -13279,7 +13372,7 @@ Default is @code{java.io.IOException}.
@deftypemethodx {Lexer} {Position} getEndPos () @deftypemethodx {Lexer} {Position} getEndPos ()
Return respectively the first position of the last token that @code{yylex} Return respectively the first position of the last token that @code{yylex}
returned, and the first position beyond it. These methods are not needed returned, and the first position beyond it. These methods are not needed
unless location tracking is active. unless location tracking and pull parsing are active.
They should return new objects for each call, to avoid that all the symbol They should return new objects for each call, to avoid that all the symbol
share the same Position boundaries. share the same Position boundaries.
@@ -13289,7 +13382,8 @@ The return type can be changed using @code{%define api.position.type
@end deftypemethod @end deftypemethod
@deftypemethod {Lexer} {Object} getLVal () @deftypemethod {Lexer} {Object} getLVal ()
Return the semantic value of the last token that yylex returned. Return the semantic value of the last token that yylex returned. Not needed
for push-only parsers.
The return type can be changed using @samp{%define api.value.type The return type can be changed using @samp{%define api.value.type
@{@var{class-name}@}}. @{@var{class-name}@}}.
@@ -13327,6 +13421,10 @@ public void reportSyntaxError(YYParser.Context ctx) @{
System.err.println(""); System.err.println("");
@} @}
@end example @end example
@noindent
This implementation is inappropriate for internationalization, see the
@file{c/bistromathic} example for a better alternative.
@end deftypemethod @end deftypemethod
@node Java Action Features @node Java Action Features
@@ -14613,6 +14711,14 @@ is given a nonzero value, the parser will output information on input
symbols and parser action. @xref{Tracing}. symbols and parser action. @xref{Tracing}.
@end deffn @end deffn
@deffn {Value} YYEMPTY
The pseudo token kind when there is no lookahead token.
@end deffn
@deffn {Value} YYEOF
The token kind denoting is the end of the input stream.
@end deffn
@deffn {Macro} yyerrok @deffn {Macro} yyerrok
Macro to cause parser to recover immediately to its normal mode Macro to cause parser to recover immediately to its normal mode
after a syntax error. @xref{Error Recovery}. after a syntax error. @xref{Error Recovery}.
@@ -14662,8 +14768,8 @@ In semantic actions, it stores the location of the lookahead token.
@end deffn @end deffn
@deffn {Type} YYLTYPE @deffn {Type} YYLTYPE
Data type of @code{yylloc}; by default, a structure with four Data type of @code{yylloc}. By default in C, a structure with four members
members. @xref{Location Type}. (start/end line/column). @xref{Location Type}.
@end deffn @end deffn
@deffn {Variable} yylval @deffn {Variable} yylval
@@ -14702,24 +14808,26 @@ Deprecated, use @code{%printer} instead (@pxref{Printer Decl}).
@deffn {Function} yypstate_delete @deffn {Function} yypstate_delete
The function to delete a parser instance, produced by Bison in push mode; The function to delete a parser instance, produced by Bison in push mode;
call this function to delete the memory associated with a parser. call this function to delete the memory associated with a parser.
@xref{Parser Delete Function}. Does nothing when called with a null pointer. @xref{yypstate_delete,,@code{yypstate_delete}}. Does nothing when called
with a null pointer.
@end deffn @end deffn
@deffn {Function} yypstate_new @deffn {Function} yypstate_new
The function to create a parser instance, produced by Bison in push mode; The function to create a parser instance, produced by Bison in push mode;
call this function to create a new parser. call this function to create a new parser.
@xref{Parser Create Function}. @xref{yypstate_new,,@code{yypstate_new}}.
@end deffn @end deffn
@deffn {Function} yypull_parse @deffn {Function} yypull_parse
The parser function produced by Bison in push mode; call this function to The parser function produced by Bison in push mode; call this function to
parse the rest of the input stream. parse the rest of the input stream.
@xref{Pull Parser Function}. @xref{yypull_parse,,@code{yypull_parse}}.
@end deffn @end deffn
@deffn {Function} yypush_parse @deffn {Function} yypush_parse
The parser function produced by Bison in push mode; call this function to The parser function produced by Bison in push mode; call this function to
parse a single token. @xref{Push Parser Function}. parse a single token.
@xref{yypush_parse,,@code{yypush_parse}}.
@end deffn @end deffn
@deffn {Macro} YYRECOVERING @deffn {Macro} YYRECOVERING
@@ -14767,6 +14875,10 @@ should not be confused with the @emph{symbol kinds}, used internally by the
parser. parser.
@end deffn @end deffn
@deffn {Value} YYUNDEF
The token kind denoting an unknown token.
@end deffn
@node Glossary @node Glossary
@appendix Glossary @appendix Glossary
@@ -14853,12 +14965,21 @@ A continuous flow of data between devices or programs.
@item Kind @item Kind
``Token'' and ``symbol'' are each overloaded to mean either a grammar symbol ``Token'' and ``symbol'' are each overloaded to mean either a grammar symbol
(kind) or all parse info (kind, value, location) associated with occurrences (kind) or all parse info (kind, value, location) associated with occurrences
of that grammar symbol from the input. To disambiguate, we use ``token of that grammar symbol from the input. To disambiguate,
kind'' and ``symbol kind'' to mean both grammar symbols and the types that
represent them in a base programming language (C, C++, etc.). However, we @itemize
use ``token'' and ``symbol'' without the word ``kind'' to mean parsed @item
we use ``token kind'' and ``symbol kind'' to mean both grammar symbols and
the values that represent them in a base programming language (C, C++,
etc.). The names of the types of these values are typically
@code{token_kind_t}, or @code{token_kind_type}, or @code{TokenKind},
depending on the programming language.
@item
we use ``token'' and ``symbol'' without the word ``kind'' to mean parsed
occurrences, and we append the word ``type'' to refer to the types that occurrences, and we append the word ``type'' to refer to the types that
represent them in a base programming language. represent them in a base programming language.
@end itemize
In summary: When you see ``kind'', interpret ``symbol'' or ``token'' to mean In summary: When you see ``kind'', interpret ``symbol'' or ``token'' to mean
a @emph{grammar symbol}. When you don't see ``kind'' (including when you a @emph{grammar symbol}. When you don't see ``kind'' (including when you
@@ -15116,7 +15237,7 @@ London, Department of Computer Science, TR-00-12 (December 2000).
@c LocalWords: redeclare automata Dparse localedir datadir XSLT midrule Wno @c LocalWords: redeclare automata Dparse localedir datadir XSLT midrule Wno
@c LocalWords: multitable headitem hh basename Doxygen fno filename gdef de @c LocalWords: multitable headitem hh basename Doxygen fno filename gdef de
@c LocalWords: doxygen ival sval deftypemethod deallocate pos deftypemethodx @c LocalWords: doxygen ival sval deftypemethod deallocate pos deftypemethodx
@c LocalWords: Ctor defcv defcvx arg accessors arithmetics CPP ifndef CALCXX @c LocalWords: Ctor defcv defcvx arg accessors CPP ifndef CALCXX YYerror
@c LocalWords: lexer's calcxx bool LPAREN RPAREN deallocation cerrno climits @c LocalWords: lexer's calcxx bool LPAREN RPAREN deallocation cerrno climits
@c LocalWords: cstdlib Debian undef yywrap unput noyywrap nounput zA yyleng @c LocalWords: cstdlib Debian undef yywrap unput noyywrap nounput zA yyleng
@c LocalWords: errno strtol ERANGE str strerror iostream argc argv Javadoc PSLR @c LocalWords: errno strtol ERANGE str strerror iostream argc argv Javadoc PSLR
@@ -15150,7 +15271,8 @@ London, Department of Computer Science, TR-00-12 (December 2000).
@c LocalWords: Wdangling yytoken erreur syntaxe inattendu attendait nombre @c LocalWords: Wdangling yytoken erreur syntaxe inattendu attendait nombre
@c LocalWords: YYUNDEF SymbolKind yypcontext YYENOMEM TOKENMAX getBundle @c LocalWords: YYUNDEF SymbolKind yypcontext YYENOMEM TOKENMAX getBundle
@c LocalWords: ResourceBundle myResources getString getName getToken @c LocalWords: ResourceBundle myResources getString getName getToken
@c LocalWords: getLocation getExpectedTokens reportSyntaxError @c LocalWords: getLocation getExpectedTokens reportSyntaxError bistromathic
@c LocalWords: TokenKind
@c Local Variables: @c Local Variables:
@c ispell-dictionary: "american" @c ispell-dictionary: "american"
+24 -10
View File
@@ -131,7 +131,7 @@ dist_man_MANS = $(top_srcdir)/%D%/bison.1
EXTRA_DIST += $(dist_man_MANS:.1=.x) EXTRA_DIST += $(dist_man_MANS:.1=.x)
MAINTAINERCLEANFILES += $(dist_man_MANS) MAINTAINERCLEANFILES += $(dist_man_MANS)
# Differences to ignore when comparing the man page (the date). # Differences to ignore when comparing man pages (the date).
remove_time_stamp = \ remove_time_stamp = \
sed 's/^\(\.TH[^"]*"[^"]*"[^"]*\)"[^"]*"/\1/' sed 's/^\(\.TH[^"]*"[^"]*"[^"]*\)"[^"]*"/\1/'
@@ -140,17 +140,31 @@ if ! CROSS_COMPILING
MAN_DEPS = %D%/bison.help %D%/bison.x $(top_srcdir)/configure MAN_DEPS = %D%/bison.help %D%/bison.x $(top_srcdir)/configure
endif endif
# If we don't have help2man, just touch the target. Maintainers must
# have the real thing, so if there's a .git directory, fail hard.
#
# We shouldn't need this, but on some OS the timestamps in the tarball
# leave us no choice. See
# https://lists.gnu.org/r/bug-bison/2020-05/msg00055.html.
$(top_srcdir)/%D%/bison.1: $(MAN_DEPS) $(top_srcdir)/%D%/bison.1: $(MAN_DEPS)
$(AM_V_GEN)$(HELP2MAN) \ $(AM_V_GEN)if $(HELP2MAN) --version >/dev/null 2>&1; then \
--include=$(top_srcdir)/%D%/bison.x \ $(HELP2MAN) \
--output=$@.tmp tests/bison --include=$(top_srcdir)/%D%/bison.x \
$(AM_V_at)if $(remove_time_stamp) $@ >$@a.tmp 2>/dev/null && \ --output=$@.tmp tests/bison && \
$(remove_time_stamp) $@.tmp | cmp $@a.tmp - >/dev/null 2>&1; then \ { $(remove_time_stamp) $@ >$@a.tmp || true; } && \
touch $@; \ $(remove_time_stamp) $@.tmp >$@b.tmp && \
else \ if diff $@a.tmp $@b.tmp >/dev/null 2>&1; then \
mv $@.tmp $@; \ touch $@; \
else \
mv $@.tmp $@; \
fi && \
rm -f $@*.tmp; \
elif test -d $(srcdir)/.git; then \
echo >&2 "ERROR: $@: help2man is needed"; \
exit 1; \
else \
touch $@; \
fi fi
$(AM_V_at)rm -f $@*.tmp
if ENABLE_YACC if ENABLE_YACC
nodist_man_MANS = %D%/yacc.1 nodist_man_MANS = %D%/yacc.1
+26 -16
View File
@@ -252,7 +252,6 @@ sub generate_grammar_triangular ($$@)
my $out = new IO::File ">$base.y" my $out = new IO::File ">$base.y"
or die; or die;
print $out <<EOF; print $out <<EOF;
%define parse.error detailed
%{ %{
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -388,7 +387,6 @@ sub generate_grammar_calc ($$@)
%} %}
%define api.value.type union %define api.value.type union
%define parse.error detailed
$directives $directives
%{ %{
@@ -812,7 +810,8 @@ sub compile ($)
my ($base) = @_; my ($base) = @_;
my $compiler = compiler ($base); my $compiler = compiler ($base);
my $my_bison = `sed -ne '/%bison "\\(.*\\)"/{s//\\1/;p;q;}' $base.y`; my $my_bison = `sed -ne '/[/][/] %bison "\\(.*\\)"/{s//\\1/;p;q;}' $base.y`;
chop $my_bison;
run ((length $my_bison ? $my_bison : $bison) . " $base.y -o $base.c"); run ((length $my_bison ? $my_bison : $bison) . " $base.y -o $base.c");
if ($gbench) if ($gbench)
{ {
@@ -902,8 +901,13 @@ directive list.
sub bench_with_gbenchmark ($@) sub bench_with_gbenchmark ($@)
{ {
my ($grammar, @directive) = @_; my ($grammar, @directive) = @_;
my $compiler = compiler ("y0");
my $readme = new IO::File ">README.md"; my $readme = new IO::File ">README.md";
print $readme <<EOF;
compiler: $compiler $cflags
EOF
my @obj = (); my @obj = ();
for my $i (0 .. $#directive) for my $i (0 .. $#directive)
{ {
@@ -923,7 +927,6 @@ sub bench_with_gbenchmark ($@)
BENCHMARK_MAIN(); BENCHMARK_MAIN();
EOF EOF
my $compiler = compiler ("y0");
run "$compiler -o main $cflags main.c @obj -lbenchmark"; run "$compiler -o main $cflags main.c @obj -lbenchmark";
run "./main | tee -a README.md"; run "./main | tee -a README.md";
} }
@@ -1121,7 +1124,7 @@ sub parse_dir ()
elsif ($token[0] eq '%b') elsif ($token[0] eq '%b')
{ {
shift @token; shift @token;
@res = ("/*\n%bison \"$token[0]\"\\\n*/"); @res = ("// %bison \"$token[0]\"");
} }
else else
{ {
@@ -1160,19 +1163,26 @@ sub getopt ()
getopt; getopt;
my $basedir = 'benches';
# Create the directory we work in. # Create the directory we work in.
mkdir "benches" or die "cannot create benches" mkdir $basedir or die "cannot create directory $basedir"
unless -d "benches"; unless -d $basedir;
my $count = 1;
++$count my $count = 0;
while -d "benches/$count"; my $dir;
my $dir = "benches/$count"; while (!$dir || -d $dir)
{
++$count;
$dir = sprintf "%s/%03d", $basedir, $count;
}
mkdir $dir mkdir $dir
or die "cannot create $dir"; or die "cannot create directory $dir";
unlink "benches/latest"
or die "cannot unlink benches/latest" unlink "$basedir/latest"
if -l "benches/latest"; or die "cannot unlink $basedir/latest"
symlink $count, "benches/latest" if -l "$basedir/latest";
symlink sprintf("%03d", $count), "$basedir/latest"
or die "cannot create symlink"; or die "cannot create symlink";
chdir $dir chdir $dir
or die "cannot chdir $dir"; or die "cannot chdir $dir";
+4 -4
View File
@@ -13,8 +13,8 @@ semantic value.
Run as `./simple`. Run as `./simple`.
Extracted from the documentation: "A Simple C++ Example". Extracted from the documentation: [A Simple C++
https://www.gnu.org/software/bison/manual/html_node/A-Simple-C_002b_002b-Example.html Example](https://www.gnu.org/software/bison/manual/html_node/A-Simple-C_002b_002b-Example.html).
## variant.yy - Self-contained example in C++98 ## variant.yy - Self-contained example in C++98
A variation of simple.yy, in C++98. A variation of simple.yy, in C++98.
@@ -36,8 +36,8 @@ starting point for a clean parser in C++. The previous examples are better
introductory examples, and the C examples are also useful introductory introductory examples, and the C examples are also useful introductory
examples. examples.
Extracted from the documentation: "A Complete C++ Example". Extracted from the documentation: [A Complete C++
https://www.gnu.org/software/bison/manual/html_node/A-Complete-C_002b_002b-Example.html Example](https://www.gnu.org/software/bison/manual/html_node/A-Complete-C_002b_002b-Example.html).
<!--- <!---
+3 -3
View File
@@ -5,9 +5,9 @@ saw the traditional implementation in C, please first read
examples/c/lexcalc, which can be seen as a C precursor of this example. examples/c/lexcalc, which can be seen as a C precursor of this example.
Read the corresponding chapter in the documentation: "A Complete C++ Read the corresponding chapter in the documentation: "A Complete C++
Example". It is also available on line (maybe with a different version of Example". It is also available [on
Bison): line](https://www.gnu.org/software/bison/manual/html_node/A-Complete-C_002b_002b-Example.html)
https://www.gnu.org/software/bison/manual/html_node/A-Complete-C_002b_002b-Example.html (maybe with a different version of Bison).
To use it, copy this directory into some work directory, and run `make` to To use it, copy this directory into some work directory, and run `make` to
compile the executable, and try it. It is a simple calculator which accepts compile the executable, and try it. It is a simple calculator which accepts
+1 -1
View File
@@ -139,7 +139,7 @@ namespace yy
int int
main (int argc, const char *argv[]) main (int argc, const char *argv[])
{ {
if (2 <= argc && isdigit (*argv[1])) if (2 <= argc && isdigit (static_cast<unsigned char> (*argv[1])))
{ {
auto maxl = strtol (argv[1], nullptr, 10); auto maxl = strtol (argv[1], nullptr, 10);
max = INT_MIN <= maxl && maxl <= INT_MAX ? int(maxl) : 4; max = INT_MIN <= maxl && maxl <= INT_MAX ? int(maxl) : 4;
+11 -8
View File
@@ -10,8 +10,8 @@ The first example is that of a simple double-precision Reverse Polish
Notation calculator (a calculator using postfix operators). This example Notation calculator (a calculator using postfix operators). This example
provides a good starting point, since operator precedence is not an issue. provides a good starting point, since operator precedence is not an issue.
Extracted from the documentation: "Reverse Polish Notation Calculator" Extracted from the documentation: [Reverse Polish Notation
https://www.gnu.org/software/bison/manual/html_node/RPN-Calc.html Calculator](https://www.gnu.org/software/bison/manual/html_node/RPN-Calc.html).
## calc - Simple Calculator ## calc - Simple Calculator
This example is slightly more complex than rpcalc: it features infix This example is slightly more complex than rpcalc: it features infix
@@ -24,18 +24,18 @@ A more complete C example: a multi-function calculator. More complex than
the previous example. Using precedence directives to support infix the previous example. Using precedence directives to support infix
operators. operators.
Extracted from the documentation: "Multi-Function Calculator: mfcalc". Extracted from the documentation: [Multi-Function Calculator:
https://www.gnu.org/software/bison/manual/html_node/Multi_002dfunction-Calc.html mfcalc](https://www.gnu.org/software/bison/manual/html_node/Multi_002dfunction-Calc.html).
## lexcalc - calculator with Flex and Bison ## lexcalc - calculator with Flex and Bison
The calculator with precedence directives and location tracking. It uses The calculator with precedence directives and location tracking. It uses
Flex to generate the scanner. Flex to generate the scanner.
## reccalc - recursive calculator with Flex and Bison ## reccalc - recursive calculator with Flex and Bison
The example builds on top of the previous one to provide a reentrant parser. This example builds on top of the previous one to provide a reentrant
Such parsers can be called concurrently in different threads, or even parser. Such parsers can be called concurrently in different threads, or
recursively. To demonstrate this feature, expressions in parentheses are even recursively. To demonstrate this feature, expressions in parentheses
tokenized as strings, and then recursively parsed from the parser. So are tokenized as strings, and then recursively parsed from the parser. So
`(((1)+(2))*((3)+(4)))` uses eight parsers, with a depth of four. `(((1)+(2))*((3)+(4)))` uses eight parsers, with a depth of four.
## pushcalc - calculator implemented with a push parser ## pushcalc - calculator implemented with a push parser
@@ -53,10 +53,13 @@ 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.
- 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
parser state, based on `yyexpected_tokens`. parser state, based on `yyexpected_tokens`.
- It uses Bison's standard catalogue for internationalization of generated
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.
- It supports debug traces with semantic values. - It supports debug traces with semantic values.
+14 -9
View File
@@ -3,20 +3,26 @@
BASE = bistromathic BASE = bistromathic
BISON = bison BISON = bison
FLEX = flex
XSLTPROC = xsltproc XSLTPROC = xsltproc
# We need to find the headers and libs for readline (and possibly intl).
# You probably need to customize this for your own environment.
CPPFLAGS = -I/opt/local/include
LDFLAGS = -L/opt/local/lib
# Find the translation catalogue for Bison's generated messagess.
BISON_LOCALEDIR = $(shell $(BISON) $(BISON_FLAGS) --print-localedir)
CPPFLAGS += -DENABLE_NLS -DBISON_LOCALEDIR='"$(BISON_LOCALEDIR)"'
LIBS = -lreadline -lm # In some environments, -lintl is needed.
all: $(BASE) all: $(BASE)
%.c %.h %.xml %.gv: %.y %.c %.h %.xml %.gv: %.y
$(BISON) $(BISONFLAGS) --defines --xml --graph=$*.gv -o $*.c $< $(BISON) $(BISONFLAGS) --defines --xml --graph=$*.gv -o $*.c $<
%.c: %.l $(BASE): parse.o
$(FLEX) $(FLEXFLAGS) -o$*.c $< $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)
scan.o: parse.h
$(BASE): parse.o scan.o
$(CC) $(CFLAGS) -o $@ $^
run: $(BASE) run: $(BASE)
@echo "Type bistromathic expressions. Quit with ctrl-d." @echo "Type bistromathic expressions. Quit with ctrl-d."
@@ -28,8 +34,7 @@ html: $(BASE).html
CLEANFILES = \ CLEANFILES = \
$(BASE) *.o \ $(BASE) *.o \
parse.[ch] parse.output parse.xml parse.html parse.gv \ parse.[ch] parse.output parse.xml parse.html parse.gv
scan.c
clean: clean:
rm -f $(CLEANFILES) rm -f $(CLEANFILES)
+6
View File
@@ -2,15 +2,21 @@
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.
- 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
parser state, based on `yyexpected_tokens`. parser state, based on `yyexpected_tokens`.
- It uses Bison's standard catalogue for internationalization of generated
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.
- 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.
To customize the interaction with bistromathic, see the GNU Readline user
manual (see `info rluserman`).
<!--- <!---
Local Variables: Local Variables:
fill-column: 76 fill-column: 76
+204 -27
View File
@@ -15,12 +15,47 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# macOS' version of readline does not repeat stdin on stdout in # Users may customize the behavior of readline, which might break our
# non-interactive mode. # expected results.
if ! echo '1-1' | prog | grep '1-1'; then INPUTRC=/dev/null
strip_prompt=true export INPUTRC
# Beware of portability issues of readline when not feeding it from a
# terminal.
#
# With recent versions of GNU Readline, input "1+2*3\n" gives
# "> 1+2*3\n7\n> \n"
#
# macOS' version does not display the prompt and does not repeat stdin
# on stdout, so input "1+2*3\n" gives "7\n" as output. Let's try to
# cope with this.
#
# On OpenBSD 6.5 the prompt is displayed, but the input is not
# repeated (!). So input "1+2*3\n" gives "> 7\n> \n" as output.
#
# On AIX, you get some escaping sequence before the prompt:
# "<ESC>[?1034h> 1+2*3". It appears to pass the terminfo capability
# "smm", to put the terminal in "meta mode": as if the user had hit
# META.
echo >perfect '> 0
0
> '
echo >ok '0'
echo '0' | prog >effective
echo "checking for readline output..."
if diff perfect effective; then
# Alles ist gut.
strip_prompt=false
elif diff ok effective; then
strip_prompt=true
else
skip "this is not the GNU Readline we expect"
fi fi
cat >input <<EOF cat >input <<EOF
1+2*3 1+2*3
EOF EOF
@@ -65,26 +100,159 @@ cat >input <<EOF
* *
EOF EOF
run 0 '> * run 0 '> *
> err: 1.1: syntax error: expected end of file or - or ( or exit or double precision number or function or variable before *' > ''
err: 1.1: syntax error: expected end of file or - or ( or exit or number or function etc., before *'
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 double precision number or function or variable before *' > ''
err: 1.9: syntax error: expected - or ( or number or function or variable before *'
cat >input <<EOF
100%
EOF
run 0 '> 100%
100
> err: 1.4: error: invalid character'
cat >input <<EOF cat >input <<EOF
1 / 0 1 / 0
EOF EOF
run 0 '> 1 / 0 run 0 '> 1 / 0
> err: 1.1-5: error: division by zero' > ''
err: 1.1-5: error: division by zero'
## ---------------- ##
## Error recovery. ##
## ---------------- ##
cat >input <<EOF
((1 ++ 2) ** 3)
(1 ++ 2) + (3 ** 4)
EOF
run 0 '> ((1 ++ 2) ** 3)
666
> (1 ++ 2) + (3 ** 4)
1332
> ''
err: 1.6: 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 *'
# The rule "( error )" should work even if there are no tokens between "(" and ")".
cat >input <<EOF
()
EOF
run 0 '> ()
666
> ''
err: 1.2: syntax error: expected - or ( or number or function or variable before )'
cat >input <<EOF
100% + 10
EOF
run 0 '> 100% + 10
> ''
err: 1.4: syntax error: invalid character: %'
# Traces. This allows to check the location of the error. If we
# forget to map YYerror to YYUNDEF, error recovery enters an endless
# loop with this input.
cat >input <<EOF
(+_)
EOF
run 0 '> (+_)
666
> ''
err: Starting parse
err: Entering state 0
err: Stack now 0
err: Reading a token
err: Next token is token ( (1.1: )
err: Shifting token ( (1.1: )
err: Entering state 2
err: Stack now 0 2
err: Return for a new token:
err: Reading a token
err: Next token is token + (1.2: )
err: LAC: initial context established for +
err: LAC: checking lookahead +: Err
err: LAC: checking lookahead end of file: Err
err: LAC: checking lookahead +: Err
err: LAC: checking lookahead -: S1
err: LAC: checking lookahead *: Err
err: LAC: checking lookahead /: Err
err: LAC: checking lookahead ^: Err
err: LAC: checking lookahead (: S2
err: LAC: checking lookahead ): Err
err: LAC: checking lookahead =: Err
err: LAC: checking lookahead exit: Err
err: LAC: checking lookahead number: S4
err: LAC: checking lookahead function: S5
err: LAC: checking lookahead variable: S6
err: LAC: checking lookahead NEG: Err
err: 1.2: syntax error: expected - or ( or number or function or variable before +
err: LAC: initial context discarded due to error recovery
err: Shifting token error (1.2: )
err: Entering state 10
err: Stack now 0 2 10
err: Next token is token + (1.2: )
err: LAC: initial context established for +
err: LAC: checking lookahead +: Err
err: Error: discarding token + (1.2: )
err: Error: popping token error (1.2: )
err: Stack now 0 2
err: LAC: initial context discarded due to error recovery
err: Shifting token error (1.2: )
err: Entering state 10
err: Stack now 0 2 10
err: Return for a new token:
err: 1.3: syntax error: invalid character: _
err: Reading a token
err: Error: popping token error (1.2: )
err: Stack now 0 2
err: Shifting token error (1.2-3: )
err: Entering state 10
err: Stack now 0 2 10
err: Next token is token invalid token (1.3: )
err: LAC: initial context established for invalid token
err: LAC: checking lookahead invalid token: Always Err
err: Error: discarding token invalid token (1.3: )
err: Error: popping token error (1.2-3: )
err: Stack now 0 2
err: LAC: initial context discarded due to error recovery
err: Shifting token error (1.2-3: )
err: Entering state 10
err: Stack now 0 2 10
err: Return for a new token:
err: Reading a token
err: Next token is token ) (1.4: )
err: Shifting token ) (1.4: )
err: Entering state 20
err: Stack now 0 2 10 20
err: Reducing stack by rule 15 (line 151):
err: $1 = token ( (1.1: )
err: $2 = token error (1.2-3: )
err: $3 = token ) (1.4: )
err: -> $$ = nterm exp (1.1-4: 666)
err: Entering state 7
err: Stack now 0 7
err: Return for a new token:
err: Reading a token
err: Now at end of input.
err: LAC: initial context established for end of file
err: LAC: checking lookahead end of file: R2 G8 S19
err: Reducing stack by rule 2 (line 126):
err: $1 = nterm exp (1.1-4: 666)
err: -> $$ = nterm input (1.1-4: )
err: Entering state 8
err: Stack now 0 8
err: Now at end of input.
err: Shifting token end of file (1.5: )
err: LAC: initial context discarded due to shift
err: Entering state 19
err: Stack now 0 8 19
err: Stack now 0 8 19
err: Cleanup: popping token end of file (1.5: )
err: Cleanup: popping nterm input (1.1-4: )' -p
## ------------ ## ## ------------ ##
@@ -94,38 +262,47 @@ run 0 '> 1 / 0
# From now on, the differences between versions of GNU Readline are # From now on, the differences between versions of GNU Readline are
# too painful to try to cope with. # too painful to try to cope with.
if $strip_prompt; then if $strip_prompt; then
echo "SKIP: this is not the GNU Readline we expect" echo "SKIP: this is not the GNU Readline we expect"
if $exit; then exit $status
exit 0
else
exit 1
fi
fi fi
# On Windows10/MSYS2 the ^G coming from <tab> completion is not
# emitted the same way
# (https://lists.gnu.org/r/bug-bison/2020-05/msg00076.html).
echo "checking for kernel name... $(uname -s)"
case $(uname -s) in
(MSYS*)
echo "SKIP: this is Windows/MSYS"
exit $status
;;
esac
# Check completion after an operator. # Check completion after an operator.
sed -e 's/\\t/ /g' >input <<EOF sed -e 's/\\t/ /g' >input <<EOF
(1+\t\t (1+\t\t
EOF EOF
run 0 '> (1+ run 0 '> (1+
( cos ln ( - atan cos exp ln number sin sqrt
- double precision number sin
atan exp sqrt
> (1+ > (1+
> err: 1.4: syntax error: expected - or ( or double precision 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'
# 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
(at\t\t (at\t\t
EOF EOF
run 0 '> (atan ( '' run 0 '> (atan ( ''
> err: 1.9: syntax error: expected - or ( or double precision 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'
# 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
e\t\t e\t\t
EOF EOF
run 0 '> e run -n 0 '> e
end of file exit exp '' end of file exit exp ''
> e > e
0 0
> err: ' > ''
err: '
+14 -7
View File
@@ -19,16 +19,23 @@ bistromathicdir = $(docdir)/%D%
## Bistromathics. ## ## Bistromathics. ##
## --------------- ## ## --------------- ##
check_PROGRAMS += %D%/bistromathic
TESTS += %D%/bistromathic.test
EXTRA_DIST += %D%/bistromathic.test
nodist_%C%_bistromathic_SOURCES = %D%/parse.y %D%/parse.h
%D%/parse.c: $(dependencies) %D%/parse.c: $(dependencies)
# Don't use gnulib's system headers. if ENABLE_BISTROMATHIC
%C%_bistromathic_CPPFLAGS = -I$(top_srcdir)/%D% -I$(top_builddir)/%D% check_PROGRAMS += %D%/bistromathic
%C%_bistromathic_LDADD = -lm -lreadline TESTS += %D%/bistromathic.test
nodist_%C%_bistromathic_SOURCES = %D%/parse.y
# Don't use gnulib's system headers.
%C%_bistromathic_CPPFLAGS = \
-DBISON_LOCALEDIR='"$(localdir)"' \
-DLOCALEDIR='"$(localdir)"' \
-I$(top_srcdir)/%D% -I$(top_builddir)/%D%
%C%_bistromathic_CFLAGS = $(TEST_CFLAGS)
%C%_bistromathic_LDADD = -lm $(LIBREADLINE) $(LIBINTL)
endif
EXTRA_DIST += %D%/bistromathic.test
dist_bistromathic_DATA = %D%/parse.y %D%/Makefile %D%/README.md dist_bistromathic_DATA = %D%/parse.y %D%/Makefile %D%/README.md
CLEANFILES += %D%/parse.[ch] %D%/parse.output CLEANFILES += %D%/parse.[ch] %D%/parse.output
CLEANDIRS += %D%/*.dSYM CLEANDIRS += %D%/*.dSYM
+170 -55
View File
@@ -2,14 +2,26 @@
%code top { %code top {
#include <ctype.h> // isdigit #include <ctype.h> // isdigit
#include <locale.h> // LC_ALL
#include <math.h> // cos, sin, etc. #include <math.h> // cos, sin, etc.
#include <stddef.h> // ptrdiff_t #include <stdarg.h> // va_start
#include <stdio.h> // printf #include <stdio.h> // printf
#include <stdlib.h> // calloc. #include <stdlib.h> // calloc
#include <string.h> // strcmp #include <string.h> // strcmp
#include <readline/readline.h> #include <readline/readline.h>
#include <readline/history.h> #include <readline/history.h>
#if defined ENABLE_NLS && ENABLE_NLS
// Unable the translation of Bison's generated messages.
# define YYENABLE_NLS 1
# include <libintl.h>
// Unless specified otherwise, we expect bistromathic's own
// catalogue to be installed in the same tree as Bison's catalogue.
# ifndef LOCALEDIR
# define LOCALEDIR BISON_LOCALEDIR
# endif
#endif
} }
%code requires { %code requires {
@@ -35,13 +47,22 @@
} }
%code provides { %code provides {
# ifndef __attribute__
# ifndef __GNUC__
# define __attribute__(Spec) /* empty */
# endif
# endif
int yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc); int yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc);
void yyerror (YYLTYPE *yylloc, char const *msg); void yyerror (YYLTYPE *loc, char const *format, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
} }
%code { %code {
#define N_ #if defined ENABLE_NLS && ENABLE_NLS
#define _ # define _(Msgid) gettext (Msgid)
#else
# define _(Msgid) (Msgid)
#endif
// Whether to quit. // Whether to quit.
int done = 0; int done = 0;
@@ -82,7 +103,7 @@
EQUAL "=" EQUAL "="
EXIT "exit" EXIT "exit"
<double> <double>
NUM _("double precision number") NUM _("number")
<symrec*> <symrec*>
FUN _("function") FUN _("function")
VAR _("variable") VAR _("variable")
@@ -133,6 +154,7 @@ exp:
| "-" exp %prec NEG { $$ = -$2; } | "-" exp %prec NEG { $$ = -$2; }
| exp[l] "^" exp[r] { $$ = pow ($l, $r); } | exp[l] "^" exp[r] { $$ = pow ($l, $r); }
| "(" exp ")" { $$ = $2; } | "(" exp ")" { $$ = $2; }
| "(" error ")" { $$ = 666; }
; ;
// End of grammar. // End of grammar.
@@ -195,7 +217,7 @@ getsym (char const *name)
} }
// How many symbols are registered. // How many symbols are registered.
int static int
symbol_count (void) symbol_count (void)
{ {
int res = 0; int res = 0;
@@ -235,6 +257,8 @@ yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc)
case '(': return TOK_LPAREN; case '(': return TOK_LPAREN;
case ')': return TOK_RPAREN; case ')': return TOK_RPAREN;
case '!': return TOK_YYUNDEF;
case '\0': return TOK_YYEOF; case '\0': return TOK_YYEOF;
// Numbers. // Numbers.
@@ -244,9 +268,9 @@ yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc)
{ {
int nchars = 0; int nchars = 0;
sscanf (*line - 1, "%lf%n", &yylval->TOK_NUM, &nchars); sscanf (*line - 1, "%lf%n", &yylval->TOK_NUM, &nchars);
*line += nchars - 1; *line += nchars - 1;
yylloc->last_column += nchars - 1; yylloc->last_column += nchars - 1;
return TOK_NUM; return TOK_NUM;
} }
// Identifiers. // Identifiers.
@@ -276,8 +300,8 @@ yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc)
// Stray characters. // Stray characters.
default: default:
yyerror (yylloc, "error: invalid character"); yyerror (yylloc, "syntax error: invalid character: %c", c);
return yylex (line, yylval, yylloc); return TOK_YYerror;
} }
} }
@@ -286,40 +310,106 @@ yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc)
| Parser. | | Parser. |
`---------*/ `---------*/
static const char *
error_format_string (int argc)
{
switch (argc)
{
default: // Avoid compiler warnings.
case 0: return _("%@: syntax error");
case 1: return _("%@: syntax error: unexpected %u");
// TRANSLATORS: '%@' is a location in a file, '%u' is an
// "unexpected token", and '%0e', '%1e'... are expected tokens
// at this point.
//
// For instance on the expression "1 + * 2", you'd get
//
// 1.5: syntax error: expected - or ( or number or function or variable before *
case 2: return _("%@: syntax error: expected %0e before %u");
case 3: return _("%@: syntax error: expected %0e or %1e before %u");
case 4: return _("%@: syntax error: expected %0e or %1e or %2e before %u");
case 5: return _("%@: syntax error: expected %0e or %1e or %2e or %3e before %u");
case 6: return _("%@: syntax error: expected %0e or %1e or %2e or %3e or %4e before %u");
case 7: return _("%@: syntax error: expected %0e or %1e or %2e or %3e or %4e or %5e before %u");
case 8: return _("%@: syntax error: expected %0e or %1e or %2e or %3e or %4e or %5e etc., before %u");
}
}
int int
yyreport_syntax_error (const yypcontext_t *ctx) yyreport_syntax_error (const yypcontext_t *ctx)
{ {
int res = 0; enum { ARGS_MAX = 6 };
YY_LOCATION_PRINT (stderr, *yypcontext_location (ctx)); yysymbol_kind_t arg[ARGS_MAX];
fprintf (stderr, ": syntax error"); int argsize = yypcontext_expected_tokens (ctx, arg, ARGS_MAX);
// Report the tokens expected at this point. if (argsize < 0)
{ return argsize;
enum { TOKENMAX = 10 }; const int too_many_expected_tokens = argsize == 0 && arg[0] != YYSYMBOL_YYEMPTY;
yysymbol_kind_t expected[TOKENMAX]; if (too_many_expected_tokens)
int n = yypcontext_expected_tokens (ctx, expected, TOKENMAX); argsize = ARGS_MAX;
if (n < 0) const char *format = error_format_string (1 + argsize + too_many_expected_tokens);
// Forward errors to yyparse.
res = n; while (*format)
// %@: location.
if (format[0] == '%' && format[1] == '@')
{
YY_LOCATION_PRINT (stderr, *yypcontext_location (ctx));
format += 2;
}
// %u: unexpected token.
else if (format[0] == '%' && format[1] == 'u')
{
fputs (yysymbol_name (yypcontext_token (ctx)), stderr);
format += 2;
}
// %0e, %1e...: expected token.
else if (format[0] == '%'
&& isdigit ((unsigned char) format[1])
&& format[2] == 'e'
&& (format[1] - '0') < argsize)
{
int i = format[1] - '0';
fputs (yysymbol_name (arg[i]), stderr);
format += 3;
}
else else
for (int i = 0; i < n; ++i) {
fprintf (stderr, "%s %s", fputc (*format, stderr);
i == 0 ? ": expected" : " or", yysymbol_name (expected[i])); ++format;
} }
// Report the unexpected token. fputc ('\n', stderr);
{ return 0;
yysymbol_kind_t lookahead = yypcontext_token (ctx);
if (lookahead != YYSYMBOL_YYEMPTY)
fprintf (stderr, " before %s", yysymbol_name (lookahead));
}
fprintf (stderr, "\n");
return res;
} }
// Called by yyparse on error. // Called by yyparse on error.
void yyerror (YYLTYPE *loc, char const *msg) void yyerror (YYLTYPE *loc, char const *format, ...)
{ {
YY_LOCATION_PRINT (stderr, *loc); YY_LOCATION_PRINT (stderr, *loc);
fprintf (stderr, ": %s\n", msg); fputs (": ", stderr);
va_list args;
va_start (args, format);
vfprintf (stderr, format, args);
va_end (args);
putc ('\n', stderr);
}
// Return a newly allocated copy of at most N bytes of STRING. In
// other words, return a copy of the initial segment of length N of
// STRING.
static char *
xstrndup (const char *string, size_t n)
{
// len = strnlen (string, n), portably.
const char *end = memchr (string, '\0', n);
size_t len = end ? (size_t) (end - string) : n;
char *new = malloc (len + 1);
if (!new)
abort ();
new[len] = '\0';
return memcpy (new, string, len);
} }
@@ -328,7 +418,8 @@ void yyerror (YYLTYPE *loc, char const *msg)
`-----------*/ `-----------*/
// Parse (and execute) this line. // Parse (and execute) this line.
int process_line (YYLTYPE *lloc, const char *line) static int
process_line (YYLTYPE *lloc, const char *line)
{ {
yypstate *ps = yypstate_new (); yypstate *ps = yypstate_new ();
int status = 0; int status = 0;
@@ -343,7 +434,8 @@ int process_line (YYLTYPE *lloc, const char *line)
} }
// Get the list of possible tokens after INPUT was read. // Get the list of possible tokens after INPUT was read.
int // Returns a nonnegative.
static int
expected_tokens (const char *input, expected_tokens (const char *input,
int *tokens, int ntokens) int *tokens, int ntokens)
{ {
@@ -364,16 +456,18 @@ expected_tokens (const char *input,
// Then query for the accepted tokens at this point. // Then query for the accepted tokens at this point.
int res = yypstate_expected_tokens (ps, tokens, ntokens); int res = yypstate_expected_tokens (ps, tokens, ntokens);
if (res < 0)
abort ();
yypstate_delete (ps); yypstate_delete (ps);
return res; return res;
} }
/* Attempt to complete on the contents of TEXT. START and END bound the // Attempt to complete on the contents of TEXT. START and END bound
region of rl_line_buffer that contains the word to complete. TEXT is // the region of rl_line_buffer that contains the word to complete.
the word to complete. We can use the entire contents of rl_line_buffer // TEXT is the word to complete. We can use the entire contents of
in case we want to do some simple parsing. Return the array of matches, // rl_line_buffer in case we want to do some simple parsing. Return
or NULL if there aren't any. */ // the array of matches, or NULL if there aren't any.
char ** static char **
completion (const char *text, int start, int end) completion (const char *text, int start, int end)
{ {
YYDPRINTF ((stderr, "completion (\"%.*s[%.*s]%s\")\n", YYDPRINTF ((stderr, "completion (\"%.*s[%.*s]%s\")\n",
@@ -383,14 +477,17 @@ completion (const char *text, int start, int end)
// Get list of token numbers. // Get list of token numbers.
int tokens[YYNTOKENS]; int tokens[YYNTOKENS];
char *line = strndup (rl_line_buffer, start); char *line = xstrndup (rl_line_buffer, (size_t) start);
int ntokens = expected_tokens (line, tokens, YYNTOKENS); int ntokens = expected_tokens (line, tokens, YYNTOKENS);
free (line); free (line);
// Build MATCHES, the list of possible completions. // Build MATCHES, the list of possible completions.
const int len = strlen (text); const size_t len = strlen (text);
// Need initial prefix and final NULL. // Need initial prefix and final NULL.
char **matches = calloc (ntokens + symbol_count () + 2, sizeof *matches); char **matches
= calloc ((size_t) ntokens + (size_t) symbol_count () + 2, sizeof *matches);
if (!matches)
abort ();
int match = 1; int match = 1;
for (int i = 0; i < ntokens; ++i) for (int i = 0; i < ntokens; ++i)
switch (tokens[i]) switch (tokens[i])
@@ -420,12 +517,12 @@ completion (const char *text, int start, int end)
matches[0] = strdup (text); matches[0] = strdup (text);
else else
{ {
int lcplen = strlen (matches[1]); size_t lcplen = strlen (matches[1]);
for (int i = 2; i < match && lcplen; ++i) for (int i = 2; i < match && lcplen; ++i)
for (int j = 0; j < lcplen; ++j) for (size_t j = 0; j < lcplen; ++j)
if (matches[1][j] != matches[i][j]) if (matches[1][j] != matches[i][j])
lcplen = j; lcplen = j;
matches[0] = strndup (matches[1], lcplen); matches[0] = xstrndup (matches[1], lcplen);
} }
if (yydebug) if (yydebug)
@@ -446,7 +543,8 @@ completion (const char *text, int start, int end)
return matches; return matches;
} }
void init_readline (void) static void
init_readline (void)
{ {
// Allow conditional parsing of the ~/.inputrc file. // Allow conditional parsing of the ~/.inputrc file.
rl_readline_name = "bistromathic"; rl_readline_name = "bistromathic";
@@ -465,10 +563,23 @@ void init_readline (void)
| Main. | | Main. |
`-------*/ `-------*/
int main (int argc, char const* argv[]) int
main (int argc, char const* argv[])
{ {
#if defined ENABLE_NLS && ENABLE_NLS
// Set up internationalization.
setlocale (LC_ALL, "");
// Use Bison's standard translation catalogue for error messages
// (the generated messages).
bindtextdomain ("bison-runtime", BISON_LOCALEDIR);
// The translation catalogue of bistromathic is actually included in
// Bison's. In your own project, use the name of your project.
bindtextdomain ("bison", LOCALEDIR);
textdomain ("bison");
#endif
// Enable parse traces on option -p. // Enable parse traces on option -p.
if (argc == 2 && strcmp (argv[1], "-p") == 0) if (1 < argc && strcmp (argv[1], "-p") == 0)
yydebug = 1; yydebug = 1;
init_table (); init_table ();
init_readline (); init_readline ();
@@ -477,7 +588,11 @@ int main (int argc, char const* argv[])
{ {
char *line = readline ("> "); char *line = readline ("> ");
if (!line) if (!line)
return 0; {
// Finish the line started by the prompt.
putchar ('\n');
break;
}
if (*line) if (*line)
add_history (line); add_history (line);
process_line (&lloc, line); process_line (&lloc, line);
+4 -2
View File
@@ -1,6 +1,7 @@
%code top { %code top {
#include <ctype.h> /* isdigit. */ #include <ctype.h> /* isdigit. */
#include <stdio.h> /* For printf, etc. */ #include <stdio.h> /* printf. */
#include <stdlib.h> /* abort. */
#include <string.h> /* strcmp. */ #include <string.h> /* strcmp. */
int yylex (void); int yylex (void);
@@ -73,7 +74,8 @@ yylex (void)
if (c == '.' || isdigit (c)) if (c == '.' || isdigit (c))
{ {
ungetc (c, stdin); ungetc (c, stdin);
scanf ("%lf", &yylval.NUM); if (scanf ("%lf", &yylval.NUM) != 1)
abort ();
return NUM; return NUM;
} }
+1
View File
@@ -27,6 +27,7 @@ nodist_%C%_calc_SOURCES = %D%/calc.y
# Don't use gnulib's system headers. # Don't use gnulib's system headers.
%C%_calc_CPPFLAGS = -I$(top_srcdir)/%D% -I$(top_builddir)/%D% %C%_calc_CPPFLAGS = -I$(top_srcdir)/%D% -I$(top_builddir)/%D%
%C%_calc_CFLAGS = $(TEST_CFLAGS)
dist_calc_DATA = %D%/calc.y %D%/Makefile %D%/README.md dist_calc_DATA = %D%/calc.y %D%/Makefile %D%/README.md
CLEANFILES += %D%/calc.[ch] %D%/calc.output %D%/scan.c CLEANFILES += %D%/calc.[ch] %D%/calc.output %D%/scan.c
+2
View File
@@ -25,6 +25,8 @@ if FLEX_WORKS
nodist_%C%_lexcalc_SOURCES = %D%/parse.y %D%/parse.h %D%/scan.l nodist_%C%_lexcalc_SOURCES = %D%/parse.y %D%/parse.h %D%/scan.l
# Don't use gnulib's system headers. # Don't use gnulib's system headers.
%C%_lexcalc_CPPFLAGS = -I$(top_srcdir)/%D% -I$(top_builddir)/%D% %C%_lexcalc_CPPFLAGS = -I$(top_srcdir)/%D% -I$(top_builddir)/%D%
# Fighting warnings triggered by Flex is just too painful.
# %C%_lexcalc_CFLAGS = $(TEST_CFLAGS)
endif FLEX_WORKS endif FLEX_WORKS
%D%/parse.c: $(dependencies) %D%/parse.c: $(dependencies)
+2 -2
View File
@@ -4,7 +4,7 @@
%option nodefault noinput nounput noyywrap %option nodefault noinput nounput noyywrap
%{ %{
#include <errno.h> /* errno, ERANGE */ #include <errno.h> /* errno, ERANGE */
#include <limits.h> /* INT_MIN */ #include <limits.h> /* INT_MIN */
#include <stdlib.h> /* strtol */ #include <stdlib.h> /* strtol */
@@ -12,7 +12,7 @@
// Each time a rule is matched, advance the end cursor/position. // Each time a rule is matched, advance the end cursor/position.
#define YY_USER_ACTION \ #define YY_USER_ACTION \
yylloc->last_column += yyleng; yylloc->last_column += (int) yyleng;
// Move the first position onto the last. // Move the first position onto the last.
#define LOCATION_STEP() \ #define LOCATION_STEP() \
+1
View File
@@ -31,6 +31,7 @@ nodist_%C%_mfcalc_SOURCES = $(mfcalc_sources)
%D%/mfcalc.c: $(dependencies) %D%/mfcalc.c: $(dependencies)
# Don't use gnulib's system headers. # Don't use gnulib's system headers.
%C%_mfcalc_CPPFLAGS = -I$(top_srcdir)/%D% -I$(top_builddir)/%D% %C%_mfcalc_CPPFLAGS = -I$(top_srcdir)/%D% -I$(top_builddir)/%D%
%C%_mfcalc_CFLAGS = $(TEST_CFLAGS)
%C%_mfcalc_LDADD = -lm %C%_mfcalc_LDADD = -lm
dist_TESTS += %D%/mfcalc.test dist_TESTS += %D%/mfcalc.test
+4 -3
View File
@@ -1,7 +1,7 @@
%code top { %code top {
#include <ctype.h> /* isdigit. */ #include <ctype.h> /* isdigit. */
#include <stdbool.h> #include <stdio.h> /* printf. */
#include <stdio.h> /* For printf, etc. */ #include <stdlib.h> /* abort. */
#include <string.h> /* strcmp. */ #include <string.h> /* strcmp. */
} }
@@ -81,7 +81,8 @@ yylex (YYSTYPE *yylval)
if (c == '.' || isdigit (c)) if (c == '.' || isdigit (c))
{ {
ungetc (c, stdin); ungetc (c, stdin);
scanf ("%lf", &yylval->NUM); if (scanf ("%lf", &yylval->NUM) != 1)
abort ();
return NUM; return NUM;
} }
+1
View File
@@ -27,6 +27,7 @@ nodist_%C%_calc_SOURCES = %D%/calc.y
# Don't use gnulib's system headers. # Don't use gnulib's system headers.
%C%_calc_CPPFLAGS = -I$(top_srcdir)/%D% -I$(top_builddir)/%D% %C%_calc_CPPFLAGS = -I$(top_srcdir)/%D% -I$(top_builddir)/%D%
%C%_calc_CFLAGS = $(TEST_CFLAGS)
dist_pushcalc_DATA = %D%/calc.y %D%/Makefile %D%/README.md dist_pushcalc_DATA = %D%/calc.y %D%/Makefile %D%/README.md
CLEANFILES += %D%/calc.[ch] %D%/calc.output CLEANFILES += %D%/calc.[ch] %D%/calc.output
+1 -1
View File
@@ -12,7 +12,7 @@ all: $(BASE)
$(BISON) $(BISONFLAGS) --defines --xml --graph=$*.gv -o $*.c $< $(BISON) $(BISONFLAGS) --defines --xml --graph=$*.gv -o $*.c $<
%.c %.h: %.l %.c %.h: %.l
$(FLEX) $(FLEXFLAGS) -o$*.c --header-file=$*.h $< $(FLEX) $(FLEXFLAGS) -o$*.c --header=$*.h $<
scan.o: parse.h scan.o: parse.h
parse.o: scan.h parse.o: scan.h
+5 -1
View File
@@ -26,6 +26,8 @@ if FLEX_WORKS
BUILT_SOURCES += $(nodist_%C%_reccalc_SOURCES) BUILT_SOURCES += $(nodist_%C%_reccalc_SOURCES)
# Don't use gnulib's system headers. # Don't use gnulib's system headers.
%C%_reccalc_CPPFLAGS = -I$(top_srcdir)/%D% -I$(top_builddir)/%D% %C%_reccalc_CPPFLAGS = -I$(top_srcdir)/%D% -I$(top_builddir)/%D%
# Fighting warnings triggered by Flex is just too painful.
# %C%_reccalc_CFLAGS = $(TEST_CFLAGS)
endif FLEX_WORKS endif FLEX_WORKS
%D%/parse.c: $(dependencies) %D%/parse.c: $(dependencies)
@@ -69,7 +71,9 @@ DASH = -
$(AM_V_LEX)rm -f $@ $@.tmp $(AM_V_LEX)rm -f $@ $@.tmp
$(AM_V_at)$(MKDIR_P) %D% $(AM_V_at)$(MKDIR_P) %D%
$(AM_V_at)touch $@.tmp $(AM_V_at)touch $@.tmp
$(AM_V_at)$(LEX) $(AM_LFLAGS) $(LFLAGS) -o%D%/scan.c --header-file=%D%/scan.h $(srcdir)/%D%/scan.l ## --header introduced in 2.5.6, renamed as --header-file in 2.6.4.
## Backward compatibility ensured since --header is an unambiguous prefix.
$(AM_V_at)$(LEX) $(AM_LFLAGS) $(LFLAGS) -o%D%/scan.c --header=%D%/scan.h $(srcdir)/%D%/scan.l
$(AM_V_at)mv $@.tmp $@ $(AM_V_at)mv $@.tmp $@
+1 -1
View File
@@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
seq 0 >/dev/null || exit 77 (seq 0) >/dev/null 2>&1 || skip "gimme one seq"
cat >input <<EOF cat >input <<EOF
1+2*3 1+2*3
+2 -2
View File
@@ -32,9 +32,9 @@
do \ do \
capacity = capacity ? 2 * capacity : 128; \ capacity = capacity ? 2 * capacity : 128; \
while (capacity < size + yyleng + 1); \ while (capacity < size + yyleng + 1); \
str = realloc (str, capacity); \ str = realloc (str, (size_t) capacity); \
} \ } \
memcpy (str + size, yytext, yyleng); \ memcpy (str + size, yytext, (size_t) yyleng); \
size += yyleng; \ size += yyleng; \
assert (size < capacity); \ assert (size < capacity); \
} while (0) } while (0)
+1
View File
@@ -31,6 +31,7 @@ nodist_%C%_rpcalc_SOURCES = $(rpcalc_sources)
%D%/rpcalc.c: $(dependencies) %D%/rpcalc.c: $(dependencies)
# Don't use gnulib's system headers. # Don't use gnulib's system headers.
%C%_rpcalc_CPPFLAGS = -I$(top_builddir)/%D% %C%_rpcalc_CPPFLAGS = -I$(top_builddir)/%D%
%C%_rpcalc_CFLAGS = $(TEST_CFLAGS)
%C%_rpcalc_LDADD = -lm %C%_rpcalc_LDADD = -lm
dist_TESTS += %D%/rpcalc.test dist_TESTS += %D%/rpcalc.test
+1 -1
View File
@@ -9,7 +9,7 @@ afterwards.
The usual calculator, a very simple version. The usual calculator, a very simple version.
## calc/Calc.y ## calc/Calc.y
The calculator, but with location tracking and debug traces. The calculator, but with location tracking, debug traces, and a push parser.
<!--- <!---
+48 -19
View File
@@ -2,6 +2,7 @@
%define api.parser.class {Calc} %define api.parser.class {Calc}
%define api.parser.public %define api.parser.public
%define api.push-pull push
%define parse.error custom %define parse.error custom
%define parse.trace %define parse.trace
@@ -20,12 +21,19 @@
%code { %code {
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
CalcLexer l = new CalcLexer(System.in); CalcLexer scanner = new CalcLexer(System.in);
Calc p = new Calc(l); Calc parser = new Calc(scanner);
for (String arg : args) for (String arg : args)
if (arg.equals("-p")) if (arg.equals("-p"))
p.setDebugLevel(1); parser.setDebugLevel(1);
if (!p.parse()) int status;
do {
int token = scanner.getToken();
Object lval = scanner.getValue();
Calc.Location yyloc = scanner.getLocation();
status = parser.push_parse(token, lval, yyloc);
} while (status == Calc.YYPUSH_MORE);
if (status != Calc.YYACCEPT)
System.exit(1); System.exit(1);
} }
@@ -105,14 +113,17 @@ class CalcLexer implements Calc.Lexer {
Position start = new Position(1, 0); Position start = new Position(1, 0);
Position end = new Position(1, 0); Position end = new Position(1, 0);
public Position getStartPos() { /**
return new Position(start); * The location of the last token read.
} * Implemented with getStartPos and getEndPos in pull parsers.
*/
public Position getEndPos() { public Calc.Location getLocation() {
return new Position(end); return new Calc.Location(new Position(start), new Position(end));
} }
/**
* Build and emit a syntax error message.
*/
public void reportSyntaxError(Calc.Context ctx) { public void reportSyntaxError(Calc.Context ctx) {
System.err.print(ctx.getLocation() + ": syntax error"); System.err.print(ctx.getLocation() + ": syntax error");
{ {
@@ -131,26 +142,39 @@ class CalcLexer implements Calc.Lexer {
System.err.println(""); System.err.println("");
} }
public void yyerror(Calc.Location l, String s) { /**
if (l == null) * Emit an error referring to the given location in a user-defined way.
System.err.println(s); *
* @@param loc The location of the element to which the
* error message is related.
* @@param msg The string for the error message.
*/
public void yyerror(Calc.Location loc, String msg) {
if (loc == null)
System.err.println(msg);
else else
System.err.println(l + ": " + s); System.err.println(loc + ": " + msg);
} }
Integer yylval; Integer yylval;
public Object getLVal() { /**
* The value of the last token read. Called getLVal in pull parsers.
*/
public Object getValue() {
return yylval; return yylval;
} }
public int yylex() throws IOException { /**
* Fetch the next token. Called yylex in pull parsers.
*/
public int getToken() throws IOException {
start.set(reader.getPosition()); start.set(reader.getPosition());
int ttype = st.nextToken(); int ttype = st.nextToken();
end.set(reader.getPosition()); end.set(reader.getPosition());
switch (ttype) { switch (ttype) {
case StreamTokenizer.TT_EOF: case StreamTokenizer.TT_EOF:
return EOF; return YYEOF;
case StreamTokenizer.TT_EOL: case StreamTokenizer.TT_EOL:
end.line += 1; end.line += 1;
end.column = 0; end.column = 0;
@@ -160,7 +184,7 @@ class CalcLexer implements Calc.Lexer {
end.set(reader.getPreviousPosition()); end.set(reader.getPreviousPosition());
return NUM; return NUM;
case ' ': case '\t': case ' ': case '\t':
return yylex(); return getToken();
case '!': case '!':
return BANG; return BANG;
case '+': case '+':
@@ -185,7 +209,9 @@ class CalcLexer implements Calc.Lexer {
} }
} }
/**
* A class defining a point in the input.
*/
class Position { class Position {
public int line = 1; public int line = 1;
public int column = 1; public int column = 1;
@@ -227,6 +253,9 @@ class Position {
} }
} }
/**
* A Stream reader that keeps track of the current Position.
*/
class PositionReader extends BufferedReader { class PositionReader extends BufferedReader {
private Position position = new Position(); private Position position = new Position();
+1 -1
View File
@@ -93,7 +93,7 @@ class CalcLexer implements Calc.Lexer {
int ttype = st.nextToken(); int ttype = st.nextToken();
switch (ttype) { switch (ttype) {
case StreamTokenizer.TT_EOF: case StreamTokenizer.TT_EOF:
return EOF; return YYEOF;
case StreamTokenizer.TT_EOL: case StreamTokenizer.TT_EOL:
return (int) '\n'; return (int) '\n';
case StreamTokenizer.TT_WORD: case StreamTokenizer.TT_WORD:
+3
View File
@@ -35,6 +35,9 @@
dist_noinst_SCRIPTS = %D%/extexi %D%/test dist_noinst_SCRIPTS = %D%/extexi %D%/test
TEST_LOG_COMPILER = $(SHELL) $(top_srcdir)/%D%/test TEST_LOG_COMPILER = $(SHELL) $(top_srcdir)/%D%/test
TEST_CFLAGS = \
$(WARN_CFLAGS) $(WARN_CFLAGS_TEST) $(WERROR_CFLAGS)
AM_CXXFLAGS = \ AM_CXXFLAGS = \
$(WARN_CXXFLAGS) $(WARN_CXXFLAGS_TEST) $(WERROR_CXXFLAGS) $(WARN_CXXFLAGS) $(WARN_CXXFLAGS_TEST) $(WERROR_CXXFLAGS)
+60 -20
View File
@@ -25,7 +25,7 @@ medir=$(dirname "$1" | sed -e 's,.*examples/,,')
number=1 number=1
# Exit status of this script. # Exit status of this script.
exit=true status=0
# top_builddir. # top_builddir.
cwd=$(pwd) cwd=$(pwd)
@@ -34,6 +34,14 @@ cwd=$(pwd)
# See bistromathic.test. # See bistromathic.test.
strip_prompt=false strip_prompt=false
# If diff supports --strip-trailing-cr, use it, to avoid EOL issues
# when testing Java programs on Windows.
echo "checking for diff --strip-trailing-cr..."
if diff --strip-trailing-cr "$1" "$1"; then
diff_opts=--strip-trailing-cr
fi
echo "checking for diff --strip-trailing-cr... $diff_opts"
# The exercised program. # The exercised program.
abs_medir=$cwd/examples/$medir abs_medir=$cwd/examples/$medir
if test -x "$abs_medir/$me"; then if test -x "$abs_medir/$me"; then
@@ -68,26 +76,49 @@ trap cleanup 0 1 2 13 15
mkdir $$.dir mkdir $$.dir
cd $$.dir cd $$.dir
# run [-noerr] EXPECTED-EXIT-STATUS EXPECTED-OUTPUT [PARSER-OPTIONS]
# ------------------------------------------------------------------ # skip [MSG]
# ----------
# Skip this test.
skip ()
{
if test x"$1" != x; then
echo "SKIP: $1"
fi
# See Autoconf's doc on 'trap'.
(exit 77); exit 77
}
# run [-noerr, -n] EXPECTED-EXIT-STATUS EXPECTED-OUTPUT [PARSER-OPTIONS]
# ----------------------------------------------------------------------
# -noerr: ignore stderr, otherwise merge it into effective output. # -noerr: ignore stderr, otherwise merge it into effective output.
# -n: not final end-of-line in expected-output
run () run ()
{ {
noerr=false noerr=false
case $1 in echo=echo
(-noerr) noerr=true; shift;; while true; do
esac case $1 in
(-noerr) noerr=true; shift;;
(-n) echo=printf; shift;;
(*) break;;
esac
done
# Expected exit status. # Expected exit status.
sta_exp=$1 sta_exp=$1
shift shift
# Expected output. # Expected output.
if $strip_prompt; then $echo "$1" |
out_exp=$(echo "$1" | sed -e 's/^> err:/err:/;/^> /d') sed -e 's/Reducing stack by rule .* (line .*):/Reducing stack by rule XX (line XXX):/g' |
else if $strip_prompt; then
out_exp=$1 # An extra EOL added in bistromathic's main. Keep that empty line.
fi sed -e '/^> ./d;s/^> $//g'
else
cat
fi >exp
shift shift
# Effective exit status. # Effective exit status.
@@ -96,33 +127,42 @@ run ()
prog "$@" - <input >out_eff 2>err_eff || sta_eff=$? prog "$@" - <input >out_eff 2>err_eff || sta_eff=$?
# Combine effective output and error streams. # Combine effective output and error streams.
out_eff=$(cat out_eff && $noerr || sed -e 's/^/err: /g' err_eff) {
cat out_eff
if ! $noerr; then
sed -e 's/^/err: /g' \
-e 's/Reducing stack by rule .* (line .*):/Reducing stack by rule XX (line XXX):/g' \
err_eff
fi
} >eff
if test $sta_eff -eq $sta_exp; then if test $sta_eff -eq $sta_exp; then
if test "$out_eff" = "$out_exp"; then if diff $diff_opts eff exp >/dev/null 2>&1; then
echo "$me: PASS: $number" echo "$me: PASS: $number"
else else
echo "$me: FAIL: $number" echo "$me: FAIL: $number"
echo "$me: input:" echo "$me: input:"
sed -e 's/^/ /' input sed -e 's/^/ /' input
echo "$me: expected output:" echo "$me: expected output:"
echo "$out_exp" | sed -e 's/^/ /' sed -e 's/^/ /' exp
echo "$me: effective output:" echo "$me: effective output:"
echo "$out_eff" | sed -e 's/^/ /' sed -e 's/^/ /' eff
exit=false echo "$me: diff:"
diff $diff_opts -u exp eff | sed -e 's/^/ /'
status=1
fi fi
else else
echo "$me: FAIL: $number (expected status: $sta_exp, effective: $sta_eff)" echo "$me: FAIL: $number (expected status: $sta_exp, effective: $sta_eff)"
cat err_eff cat err_eff
exit=false status=1
fi fi
number=$(expr $number + 1) number=$(expr $number + 1)
} }
# We have cd'd one level deeper. # We have cd'd one level deeper.
case $1 in case $1 in
/*) . "$1";; /*) . "$1" || status=2;;
*) . "../$1";; *) . "../$1" || status=2;;
esac esac
$exit exit $status
+1 -1
Submodule gnulib updated: 64e1ff019f...ffbb0ced8b
+1
View File
@@ -1,3 +1,4 @@
/remove-potcdate.sin~
/*.gmo /*.gmo
/*.po /*.po
/LINGUAS /LINGUAS
+1
View File
@@ -1,3 +1,4 @@
/extern-inline.m4~
/*~ /*~
/00gnulib.m4 /00gnulib.m4
/__inline.m4 /__inline.m4
+16
View File
@@ -41,6 +41,22 @@ else
fi fi
]) ])
AC_CACHE_CHECK([whether flex supports --header=FILE],
[ac_cv_prog_lex_supports_header_opt],
[if _AC_DO_VAR([LEX --header=conftest.h conftest.l]); then
ac_cv_prog_lex_supports_header_opt=yes
else
ac_cv_prog_lex_supports_header_opt=no
fi
])
if test "$ac_cv_prog_lex_supports_header_opt" = yes; then
FLEX_SUPPORTS_HEADER_OPT=true
else
FLEX_SUPPORTS_HEADER_OPT=false
fi
cat >conftest.l <<_ACEOF[ cat >conftest.l <<_ACEOF[
%% %%
a { ECHO; } a { ECHO; }
+3
View File
@@ -1,3 +1,5 @@
examples/c/bistromathic/parse.y
examples/java/calc/Calc.y
src/complain.c src/complain.c
src/conflicts.c src/conflicts.c
src/files.c src/files.c
@@ -5,6 +7,7 @@ src/fixits.c
src/getargs.c src/getargs.c
src/gram.c src/gram.c
src/graphviz.c src/graphviz.c
src/i18n-strings.c
src/location.c src/location.c
src/main.c src/main.c
src/muscle-tab.c src/muscle-tab.c
+3 -3
View File
@@ -23,7 +23,7 @@
#include "system.h" #include "system.h"
#include <argmatch.h> #include <argmatch.h>
#include <ctype.h> #include <c-ctype.h>
#include <progname.h> #include <progname.h>
#include <stdarg.h> #include <stdarg.h>
#include <sys/stat.h> #include <sys/stat.h>
@@ -600,7 +600,7 @@ syntax_error (location loc,
CASE (2, _("expected %1$s before %0$s")); CASE (2, _("expected %1$s before %0$s"));
CASE (3, _("expected %1$s or %2$s before %0$s")); CASE (3, _("expected %1$s or %2$s before %0$s"));
CASE (4, _("expected %1$s or %2$s or %3$s before %0$s")); CASE (4, _("expected %1$s or %2$s or %3$s before %0$s"));
CASE (5, _("expected %1$s or %2$s or %4$s or %5$s before %0$s")); CASE (5, _("expected %1$s or %2$s or %3$s or %4$s before %0$s"));
#undef CASE #undef CASE
} }
location_print (loc, stderr); location_print (loc, stderr);
@@ -609,7 +609,7 @@ syntax_error (location loc,
while (*format) while (*format)
if (format[0] == '%' if (format[0] == '%'
&& isdigit (format[1]) && c_isdigit (format[1])
&& format[2] == '$' && format[2] == '$'
&& format[3] == 's' && format[3] == 's'
&& (format[1] - '0') < argc) && (format[1] - '0') < argc)
+3 -2
View File
@@ -124,10 +124,11 @@ fixits_run (void)
FILE *out = xfopen (input, "w"); FILE *out = xfopen (input, "w");
size_t line = 1; size_t line = 1;
size_t offset = 1; size_t offset = 1;
fixit const *f = NULL; void const *p = NULL;
gl_list_iterator_t iter = gl_list_iterator (fixits); gl_list_iterator_t iter = gl_list_iterator (fixits);
while (gl_list_iterator_next (&iter, (const void**) &f, NULL)) while (gl_list_iterator_next (&iter, &p, NULL))
{ {
fixit const *f = p;
/* Look for the correct line. */ /* Look for the correct line. */
while (line < f->location.start.line) while (line < f->location.start.line)
{ {
+3 -1
View File
@@ -257,7 +257,8 @@ static const argmatch_trace_doc argmatch_trace_docs[] =
{ "sets", "grammar sets: firsts, nullable etc." }, { "sets", "grammar sets: firsts, nullable etc." },
{ "muscles", "m4 definitions passed to the skeleton" }, { "muscles", "m4 definitions passed to the skeleton" },
{ "tools", "m4 invocation" }, { "tools", "m4 invocation" },
{ "m4", "m4 traces" }, { "m4-early", "m4 traces starting from the start" },
{ "m4", "m4 traces starting from the skeleton evaluation" },
{ "skeleton", "skeleton postprocessing" }, { "skeleton", "skeleton postprocessing" },
{ "time", "time consumption" }, { "time", "time consumption" },
{ "ielr", "IELR conversion" }, { "ielr", "IELR conversion" },
@@ -279,6 +280,7 @@ static const argmatch_trace_arg argmatch_trace_args[] =
{ "sets", trace_sets }, { "sets", trace_sets },
{ "muscles", trace_muscles }, { "muscles", trace_muscles },
{ "tools", trace_tools }, { "tools", trace_tools },
{ "m4-early", trace_m4_early },
{ "m4", trace_m4 }, { "m4", trace_m4 },
{ "skeleton", trace_skeleton }, { "skeleton", trace_skeleton },
{ "time", trace_time }, { "time", trace_time },
+6 -5
View File
@@ -100,11 +100,12 @@ enum trace
trace_grammar = 1 << 7, /**< Reading, reducing the grammar. */ trace_grammar = 1 << 7, /**< Reading, reducing the grammar. */
trace_time = 1 << 8, /**< Time consumption. */ trace_time = 1 << 8, /**< Time consumption. */
trace_skeleton = 1 << 9, /**< Skeleton postprocessing. */ trace_skeleton = 1 << 9, /**< Skeleton postprocessing. */
trace_m4 = 1 << 10, /**< M4 traces. */ trace_m4_early = 1 << 10, /**< M4 early traces. */
trace_muscles = 1 << 11, /**< M4 definitions of the muscles. */ trace_m4 = 1 << 11, /**< M4 traces. */
trace_ielr = 1 << 12, /**< IELR conversion. */ trace_muscles = 1 << 12, /**< M4 definitions of the muscles. */
trace_closure = 1 << 13, /**< Input/output of closure(). */ trace_ielr = 1 << 13, /**< IELR conversion. */
trace_locations = 1 << 14, /**< Full display of locations. */ trace_closure = 1 << 14, /**< Input/output of closure(). */
trace_locations = 1 << 15, /**< Full display of locations. */
trace_all = ~0 /**< All of the above. */ trace_all = ~0 /**< All of the above. */
}; };
/** What debug items bison displays during its run. */ /** What debug items bison displays during its run. */
+37
View File
@@ -0,0 +1,37 @@
/* This file is not compiled in, it is used only to expose more
strings to gettextize.
Why is this needed?
Bison emits strings to translate in the generated code, for builtin
tokens. So they appear only in generated parsers, which are not
shipped, so they are not in the src tree, so we cannot use them in
our POTFILE.
Except src/parse-gram.c, which is in the source tree. And even in
the git repo. But to avoid useless diffs in the repo, we do not
keep the #line directives in the src tree. Yet, for the user, we
ship a src/parse-gram.c _with_ the #lines. This is done in a
dist-hook which regenerates src/parse-gram.c when we run "make
dist".
Unfortunately, then, update-po traverses the whole tree and sees
that the location of the strings to translate in src/parse-gram.c
have changed, so the bison.pot is to be updated. And that is not
possible in the "make dist" which is run within "make distcheck"
(not the one preparing the dist for distcheck, the one run by
distcheck to check that a distributed tarball can build a tarball)
because then the src tree is read-only.
So let's not put src/parse-gram.c in the POTFILE, and expose these
strings to gettextize by hand.
*/
// Please syntax-check.
#include <config.h>
static const char *const msgid[] =
{
N_("end of file"),
N_("invalid token")
}
+1 -1
View File
@@ -92,7 +92,7 @@ goto_print (goto_number i, FILE *out)
const state_number dst = to_state[i]; const state_number dst = to_state[i];
symbol_number var = states[dst]->accessing_symbol; symbol_number var = states[dst]->accessing_symbol;
fprintf (out, fprintf (out,
"goto[%ld] = (%d, %s, %d)", i, src, symbols[var]->tag, dst); "goto[%zu] = (%d, %s, %d)", i, src, symbols[var]->tag, dst);
} }
void void
+3 -2
View File
@@ -117,6 +117,7 @@ BUILT_SOURCES += \
# definition of libbison, beware that they might expand as flags such as # definition of libbison, beware that they might expand as flags such as
# `-lm`. Keep them here. Or use a Libtool convenience library. # `-lm`. Keep them here. Or use a Libtool convenience library.
src_bison_LDADD = \ src_bison_LDADD = \
lib/libbison.a \
$(ISNAND_LIBM) \ $(ISNAND_LIBM) \
$(ISNANF_LIBM) \ $(ISNANF_LIBM) \
$(ISNANL_LIBM) \ $(ISNANL_LIBM) \
@@ -126,10 +127,10 @@ src_bison_LDADD = \
$(LIBTHREAD) \ $(LIBTHREAD) \
$(LIB_CLOCK_GETTIME) \ $(LIB_CLOCK_GETTIME) \
$(LIB_GETHRXTIME) \ $(LIB_GETHRXTIME) \
$(LIBTEXTSTYLE) \ $(LIBTEXTSTYLE)
lib/libbison.a
EXTRA_DIST += %D%/i18n-strings.c
## ------ ## ## ------ ##
+24 -34
View File
@@ -186,16 +186,6 @@ xescape_trigraphs (const char *src)
return buf; return buf;
} }
/* Whether some symbol requires internationalization. */
static bool
has_translations (void)
{
for (int i = 0; i < nsyms; i++)
if (symbols[i]->translatable)
return true;
return false;
}
/* The tag to show in the generated parsers. Use "end of file" rather /* The tag to show in the generated parsers. Use "end of file" rather
than "$end". But keep "$end" in the reports, it's shorter and more than "$end". But keep "$end" in the reports, it's shorter and more
consistent. Support i18n if the user already uses it. */ consistent. Support i18n if the user already uses it. */
@@ -219,11 +209,9 @@ symbol_tag (const symbol *sym)
static void static void
prepare_symbol_names (char const *muscle_name) prepare_symbol_names (char const *muscle_name)
{ {
const bool eof_is_user_defined // Whether to add a pair of quotes around the name.
= !endtoken->alias || STRNEQ (endtoken->alias->tag, "$end");
const bool quote = STREQ (muscle_name, "tname"); const bool quote = STREQ (muscle_name, "tname");
const bool with_translations = !quote && has_translations (); bool has_translations = false;
/* We assume that the table will be output starting at column 2. */ /* We assume that the table will be output starting at column 2. */
int col = 2; int col = 2;
@@ -233,11 +221,9 @@ prepare_symbol_names (char const *muscle_name)
for (int i = 0; i < nsyms; i++) for (int i = 0; i < nsyms; i++)
{ {
const char *tag = symbol_tag (symbols[i]); const char *tag = symbol_tag (symbols[i]);
bool translatable = bool translatable = !quote && symbols[i]->translatable;
with_translations if (translatable)
&& (symbols[i]->translatable has_translations = true;
|| (!eof_is_user_defined && symbols[i]->content == endtoken->content)
|| symbols[i]->content == undeftoken->content);
char *cp char *cp
= tag[0] == '"' && !quote = tag[0] == '"' && !quote
@@ -273,8 +259,7 @@ prepare_symbol_names (char const *muscle_name)
muscle_insert (muscle_name, obstack_finish0 (&format_obstack)); muscle_insert (muscle_name, obstack_finish0 (&format_obstack));
/* Announce whether translation support is needed. */ /* Announce whether translation support is needed. */
if (!quote) MUSCLE_INSERT_BOOL ("has_translations_flag", has_translations);
MUSCLE_INSERT_BOOL ("has_translations", with_translations);
} }
@@ -702,6 +687,7 @@ output_skeleton (void)
char *skeldir = xpath_join (datadir, "skeletons"); char *skeldir = xpath_join (datadir, "skeletons");
char *m4sugar = xpath_join (datadir, "m4sugar/m4sugar.m4"); char *m4sugar = xpath_join (datadir, "m4sugar/m4sugar.m4");
char *m4bison = xpath_join (skeldir, "bison.m4"); char *m4bison = xpath_join (skeldir, "bison.m4");
char *traceon = xpath_join (skeldir, "traceon.m4");
char *skel = (IS_PATH_WITH_DIR (skeleton) char *skel = (IS_PATH_WITH_DIR (skeleton)
? xstrdup (skeleton) ? xstrdup (skeleton)
: xpath_join (skeldir, skeleton)); : xpath_join (skeldir, skeleton));
@@ -713,21 +699,10 @@ output_skeleton (void)
/* Create an m4 subprocess connected to us via two pipes. */ /* Create an m4 subprocess connected to us via two pipes. */
if (trace_flag & trace_tools)
fprintf (stderr, "running: %s %s - %s %s\n",
m4, m4sugar, m4bison, skel);
/* Some future version of GNU M4 (most likely 1.6) may treat the -dV in a
position-dependent manner. Keep it as the first argument so that all
files are traced.
See the thread starting at
<http://lists.gnu.org/archive/html/bug-bison/2008-07/msg00000.html>
for details. */
int filter_fd[2]; int filter_fd[2];
pid_t pid; pid_t pid;
{ {
char const *argv[10]; char const *argv[11];
int i = 0; int i = 0;
argv[i++] = m4; argv[i++] = m4;
@@ -745,15 +720,29 @@ output_skeleton (void)
argv[i++] = "-I"; argv[i++] = "-I";
argv[i++] = datadir; argv[i++] = datadir;
if (trace_flag & trace_m4) /* Some future version of GNU M4 (most likely 1.6) may treat the
-dV in a position-dependent manner. See the thread starting at
<http://lists.gnu.org/archive/html/bug-bison/2008-07/msg00000.html>
for details. */
if (trace_flag & trace_m4_early)
argv[i++] = "-dV"; argv[i++] = "-dV";
argv[i++] = m4sugar; argv[i++] = m4sugar;
argv[i++] = "-"; argv[i++] = "-";
argv[i++] = m4bison; argv[i++] = m4bison;
if (trace_flag & trace_m4)
argv[i++] = traceon;
argv[i++] = skel; argv[i++] = skel;
argv[i++] = NULL; argv[i++] = NULL;
aver (i <= ARRAY_CARDINALITY (argv)); aver (i <= ARRAY_CARDINALITY (argv));
if (trace_flag & trace_tools)
{
fputs ("running:", stderr);
for (int j = 0; argv[j]; ++j)
fprintf (stderr, " %s", argv[j]);
fputc ('\n', stderr);
}
/* The ugly cast is because gnulib gets the const-ness wrong. */ /* The ugly cast is because gnulib gets the const-ness wrong. */
pid = create_pipe_bidi ("m4", m4, (char **)(void*)argv, false, true, pid = create_pipe_bidi ("m4", m4, (char **)(void*)argv, false, true,
true, filter_fd); true, filter_fd);
@@ -762,6 +751,7 @@ output_skeleton (void)
free (skeldir); free (skeldir);
free (m4sugar); free (m4sugar);
free (m4bison); free (m4bison);
free (traceon);
free (skel); free (skel);
if (trace_flag & trace_muscles) if (trace_flag & trace_muscles)
+54 -34
View File
@@ -1,4 +1,4 @@
/* A Bison parser, made by GNU Bison 3.5.4.236-8d75. */ /* A Bison parser, made by GNU Bison 3.6. */
/* Bison implementation for Yacc-like parsers in C /* Bison implementation for Yacc-like parsers in C
@@ -34,6 +34,10 @@
/* C LALR(1) parser skeleton written by Richard Stallman, by /* C LALR(1) parser skeleton written by Richard Stallman, by
simplifying the original so-called "semantic" parser. */ simplifying the original so-called "semantic" parser. */
/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
especially those whose name start with YY_ or yy_. They are
private implementation details that can be changed or removed. */
/* All symbols defined below should begin with yy or YY, to avoid /* All symbols defined below should begin with yy or YY, to avoid
infringing on user name space. This should be done even for local infringing on user name space. This should be done even for local
variables, as they might otherwise be expanded by user macros. variables, as they might otherwise be expanded by user macros.
@@ -41,14 +45,11 @@
define necessary library symbols; they are noted "INFRINGES ON define necessary library symbols; they are noted "INFRINGES ON
USER NAME SPACE" below. */ USER NAME SPACE" below. */
/* Undocumented macros, especially those whose name start with YY_,
are private implementation details. Do not rely on them. */
/* Identify Bison output. */ /* Identify Bison output. */
#define YYBISON 1 #define YYBISON 1
/* Bison version. */ /* Bison version. */
#define YYBISON_VERSION "3.5.4.236-8d75" #define YYBISON_VERSION "3.6"
/* Skeleton name. */ /* Skeleton name. */
#define YYSKELETON_NAME "yacc.c" #define YYSKELETON_NAME "yacc.c"
@@ -105,7 +106,7 @@ enum yysymbol_kind_t
{ {
YYSYMBOL_YYEMPTY = -2, YYSYMBOL_YYEMPTY = -2,
YYSYMBOL_YYEOF = 0, /* "end of file" */ YYSYMBOL_YYEOF = 0, /* "end of file" */
YYSYMBOL_YYERROR = 1, /* error */ YYSYMBOL_YYerror = 1, /* error */
YYSYMBOL_YYUNDEF = 2, /* "invalid token" */ YYSYMBOL_YYUNDEF = 2, /* "invalid token" */
YYSYMBOL_STRING = 3, /* "string" */ YYSYMBOL_STRING = 3, /* "string" */
YYSYMBOL_TSTRING = 4, /* "translatable string" */ YYSYMBOL_TSTRING = 4, /* "translatable string" */
@@ -407,6 +408,7 @@ typedef int yytype_uint16;
#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X)) #define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X))
/* Stored state numbers (used for stacks). */ /* Stored state numbers (used for stacks). */
typedef yytype_uint8 yy_state_t; typedef yytype_uint8 yy_state_t;
@@ -425,6 +427,11 @@ typedef int yy_state_fast_t;
# endif # endif
#endif #endif
#ifndef N_
# define N_(Msgid) Msgid
#endif
#ifndef YY_ATTRIBUTE_PURE #ifndef YY_ATTRIBUTE_PURE
# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) # if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) # define YY_ATTRIBUTE_PURE __attribute__ ((__pure__))
@@ -524,7 +531,7 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
# endif # endif
# endif # endif
# define YYCOPY_NEEDED 1 # define YYCOPY_NEEDED 1
#endif #endif /* 1 */
#if (! defined yyoverflow \ #if (! defined yyoverflow \
&& (! defined __cplusplus \ && (! defined __cplusplus \
@@ -643,7 +650,7 @@ yysymbol_name (yysymbol_kind_t yysymbol)
{ {
static const char *const yy_sname[] = static const char *const yy_sname[] =
{ {
N_("end of file"), "error", N_("invalid token"), N_("string"), N_("end of file"), N_("error"), N_("invalid token"), N_("string"),
N_("translatable string"), "%token", "%nterm", "%type", "%destructor", N_("translatable string"), "%token", "%nterm", "%type", "%destructor",
"%printer", "%left", "%right", "%nonassoc", "%precedence", "%prec", "%printer", "%left", "%right", "%nonassoc", "%precedence", "%prec",
"%dprec", "%merge", "%code", "%default-prec", "%define", "%defines", "%dprec", "%merge", "%code", "%default-prec", "%define", "%defines",
@@ -666,11 +673,11 @@ yysymbol_name (yysymbol_kind_t yysymbol)
"named_ref.opt", "variable", "value", "id", "id_colon", "symbol", "named_ref.opt", "variable", "value", "id", "id_colon", "symbol",
"string_as_id", "epilogue.opt", YY_NULLPTR "string_as_id", "epilogue.opt", YY_NULLPTR
}; };
/* YYTRANSLATABLE[SYMBOL-NUM] -- Whether YYTNAME[SYMBOL-NUM] is /* YYTRANSLATABLE[SYMBOL-NUM] -- Whether YY_SNAME[SYMBOL-NUM] is
internationalizable. */ internationalizable. */
static yytype_int8 yytranslatable[] = static yytype_int8 yytranslatable[] =
{ {
0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -684,7 +691,7 @@ yysymbol_name (yysymbol_kind_t yysymbol)
} }
#endif #endif
# ifdef YYPRINT #ifdef YYPRINT
/* YYTOKNUM[NUM] -- (External) token number corresponding to the /* YYTOKNUM[NUM] -- (External) token number corresponding to the
(internal) symbol number NUM (which must be that of a token). */ (internal) symbol number NUM (which must be that of a token). */
static const yytype_int16 yytoknum[] = static const yytype_int16 yytoknum[] =
@@ -697,7 +704,7 @@ static const yytype_int16 yytoknum[] =
305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
315 315
}; };
# endif #endif
#define YYPACT_NINF (-80) #define YYPACT_NINF (-80)
@@ -925,6 +932,9 @@ enum { YYENOMEM = -2 };
} \ } \
while (0) while (0)
/* Backward compatibility with an undocumented macro.
Use GRAM_error or GRAM_UNDEF. */
#define YYERRCODE GRAM_UNDEF
/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
If N is 0, then set CURRENT to the empty location which ends If N is 0, then set CURRENT to the empty location which ends
@@ -972,8 +982,8 @@ do { \
This macro was not mandated originally: define only if we know This macro was not mandated originally: define only if we know
we won't break user code: when these are the locations we know. */ we won't break user code: when these are the locations we know. */
#ifndef YY_LOCATION_PRINT # ifndef YY_LOCATION_PRINT
# if defined GRAM_LTYPE_IS_TRIVIAL && GRAM_LTYPE_IS_TRIVIAL # if defined GRAM_LTYPE_IS_TRIVIAL && GRAM_LTYPE_IS_TRIVIAL
/* Print *YYLOCP on YYO. Private, do not rely on its existence. */ /* Print *YYLOCP on YYO. Private, do not rely on its existence. */
@@ -1003,22 +1013,22 @@ yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp)
return res; return res;
} }
# define YY_LOCATION_PRINT(File, Loc) \ # define YY_LOCATION_PRINT(File, Loc) \
yy_location_print_ (File, &(Loc)) yy_location_print_ (File, &(Loc))
# else # else
# define YY_LOCATION_PRINT(File, Loc) ((void) 0) # define YY_LOCATION_PRINT(File, Loc) ((void) 0)
# endif # endif
#endif # endif /* !defined YY_LOCATION_PRINT */
# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ # define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \
do { \ do { \
if (yydebug) \ if (yydebug) \
{ \ { \
YYFPRINTF (stderr, "%s ", Title); \ YYFPRINTF (stderr, "%s ", Title); \
yy_symbol_print (stderr, \ yy_symbol_print (stderr, \
Type, Value, Location); \ Kind, Value, Location); \
YYFPRINTF (stderr, "\n"); \ YYFPRINTF (stderr, "\n"); \
} \ } \
} while (0) } while (0)
@@ -1295,8 +1305,8 @@ yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp,
YYFPRINTF (stderr, " $%d = ", yyi + 1); YYFPRINTF (stderr, " $%d = ", yyi + 1);
yy_symbol_print (stderr, yy_symbol_print (stderr,
YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]), YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]),
&yyvsp[(yyi + 1) - (yynrhs)] &yyvsp[(yyi + 1) - (yynrhs)],
, &(yylsp[(yyi + 1) - (yynrhs)]) ); &(yylsp[(yyi + 1) - (yynrhs)]));
YYFPRINTF (stderr, "\n"); YYFPRINTF (stderr, "\n");
} }
} }
@@ -1312,7 +1322,7 @@ do { \
int yydebug; int yydebug;
#else /* !GRAM_DEBUG */ #else /* !GRAM_DEBUG */
# define YYDPRINTF(Args) ((void) 0) # define YYDPRINTF(Args) ((void) 0)
# define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_SYMBOL_PRINT(Title, Kind, Value, Location)
# define YY_STACK_PRINT(Bottom, Top) # define YY_STACK_PRINT(Bottom, Top)
# define YY_REDUCE_PRINT(Rule) # define YY_REDUCE_PRINT(Rule)
#endif /* !GRAM_DEBUG */ #endif /* !GRAM_DEBUG */
@@ -1606,7 +1616,7 @@ yypcontext_expected_tokens (const yypcontext_t *yyctx,
for (yyx = 0; yyx < YYNTOKENS; ++yyx) for (yyx = 0; yyx < YYNTOKENS; ++yyx)
{ {
yysymbol_kind_t yysym = YY_CAST (yysymbol_kind_t, yyx); yysymbol_kind_t yysym = YY_CAST (yysymbol_kind_t, yyx);
if (yysym != YYSYMBOL_YYERROR && yysym != YYSYMBOL_YYUNDEF) if (yysym != YYSYMBOL_YYerror && yysym != YYSYMBOL_YYUNDEF)
switch (yy_lac (yyctx->yyesa, yyctx->yyes, yyctx->yyes_capacity, yyctx->yyssp, yysym)) switch (yy_lac (yyctx->yyesa, yyctx->yyes, yyctx->yyes_capacity, yyctx->yyssp, yysym))
{ {
case YYENOMEM: case YYENOMEM:
@@ -1622,6 +1632,8 @@ yypcontext_expected_tokens (const yypcontext_t *yyctx,
yyarg[yycount++] = yysym; yyarg[yycount++] = yysym;
} }
} }
if (yyarg && yycount == 0 && 0 < yyargn)
yyarg[0] = YYSYMBOL_YYEMPTY;
return yycount; return yycount;
} }
@@ -1901,7 +1913,7 @@ yysetstate:
YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyss_alloc, yyss);
YYSTACK_RELOCATE (yyvs_alloc, yyvs); YYSTACK_RELOCATE (yyvs_alloc, yyvs);
YYSTACK_RELOCATE (yyls_alloc, yyls); YYSTACK_RELOCATE (yyls_alloc, yyls);
# undef YYSTACK_RELOCATE # undef YYSTACK_RELOCATE
if (yyss1 != yyssa) if (yyss1 != yyssa)
YYSTACK_FREE (yyss1); YYSTACK_FREE (yyss1);
} }
@@ -1954,6 +1966,17 @@ yybackup:
yytoken = YYSYMBOL_YYEOF; yytoken = YYSYMBOL_YYEOF;
YYDPRINTF ((stderr, "Now at end of input.\n")); YYDPRINTF ((stderr, "Now at end of input.\n"));
} }
else if (yychar == GRAM_error)
{
/* The scanner already issued an error message, process directly
to error recovery. But do not keep the error token as
lookahead, it is too special and may lead us to an endless
loop in error recovery. */
yychar = GRAM_UNDEF;
yytoken = YYSYMBOL_YYerror;
yyerror_range[1] = yylloc;
goto yyerrlab1;
}
else else
{ {
yytoken = YYTRANSLATE (yychar); yytoken = YYTRANSLATE (yychar);
@@ -2619,7 +2642,6 @@ yyerrlab:
/* Make sure we have latest lookahead translation. See comments at /* Make sure we have latest lookahead translation. See comments at
user semantic actions for why this is necessary. */ user semantic actions for why this is necessary. */
yytoken = yychar == GRAM_EMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar); yytoken = yychar == GRAM_EMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar);
/* If not already recovering from an error, report this error. */ /* If not already recovering from an error, report this error. */
if (!yyerrstatus) if (!yyerrstatus)
{ {
@@ -2635,7 +2657,6 @@ yyerrlab:
} }
yyerror_range[1] = yylloc; yyerror_range[1] = yylloc;
if (yyerrstatus == 3) if (yyerrstatus == 3)
{ {
/* If just tried and failed to reuse lookahead token after an /* If just tried and failed to reuse lookahead token after an
@@ -2684,13 +2705,14 @@ yyerrorlab:
yyerrlab1: yyerrlab1:
yyerrstatus = 3; /* Each real token shifted decrements this. */ yyerrstatus = 3; /* Each real token shifted decrements this. */
/* Pop stack until we find a state that shifts the error token. */
for (;;) for (;;)
{ {
yyn = yypact[yystate]; yyn = yypact[yystate];
if (!yypact_value_is_default (yyn)) if (!yypact_value_is_default (yyn))
{ {
yyn += YYSYMBOL_YYERROR; yyn += YYSYMBOL_YYerror;
if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYERROR) if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror)
{ {
yyn = yytable[yyn]; yyn = yytable[yyn];
if (0 < yyn) if (0 < yyn)
@@ -2719,10 +2741,8 @@ yyerrlab1:
YY_IGNORE_MAYBE_UNINITIALIZED_END YY_IGNORE_MAYBE_UNINITIALIZED_END
yyerror_range[2] = yylloc; yyerror_range[2] = yylloc;
/* Using YYLLOC is tempting, but would change the location of ++yylsp;
the lookahead. YYLOC is available though. */ YYLLOC_DEFAULT (*yylsp, yyerror_range, 2);
YYLLOC_DEFAULT (yyloc, yyerror_range, 2);
*++yylsp = yyloc;
/* Shift the error token. */ /* Shift the error token. */
YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp); YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp);
+5 -4
View File
@@ -1,4 +1,4 @@
/* A Bison parser, made by GNU Bison 3.5.4.236-8d75. */ /* A Bison parser, made by GNU Bison 3.6. */
/* Bison interface for Yacc-like parsers in C /* Bison interface for Yacc-like parsers in C
@@ -31,8 +31,9 @@
This special exception was added by the Free Software Foundation in This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */ version 2.2 of Bison. */
/* Undocumented macros, especially those whose name start with YY_, /* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
are private implementation details. Do not rely on them. */ especially those whose name start with YY_ or yy_. They are
private implementation details that can be changed or removed. */
#ifndef YY_GRAM_SRC_PARSE_GRAM_H_INCLUDED #ifndef YY_GRAM_SRC_PARSE_GRAM_H_INCLUDED
# define YY_GRAM_SRC_PARSE_GRAM_H_INCLUDED # define YY_GRAM_SRC_PARSE_GRAM_H_INCLUDED
@@ -79,7 +80,7 @@ extern int gram_debug;
{ {
GRAM_EMPTY = -2, GRAM_EMPTY = -2,
GRAM_EOF = 0, /* "end of file" */ GRAM_EOF = 0, /* "end of file" */
GRAM_ERRCODE = 1, /* error */ GRAM_error = 1, /* error */
GRAM_UNDEF = 2, /* "invalid token" */ GRAM_UNDEF = 2, /* "invalid token" */
STRING = 3, /* "string" */ STRING = 3, /* "string" */
TSTRING = 4, /* "translatable string" */ TSTRING = 4, /* "translatable string" */
+53 -32
View File
@@ -83,6 +83,23 @@ static boundary scanner_cursor;
unput (Msg[i - 1]); \ unput (Msg[i - 1]); \
} while (0) } while (0)
#define STRING_GROW_ESCAPE(Char) \
do { \
long c = Char; \
if (0 < c && c <= UCHAR_MAX) \
obstack_1grow (&obstack_for_string, c); \
else \
{ \
complain (loc, complaint, \
_("invalid number after \\-escape: %s"), \
yytext + 1); \
/* Avoid additional errors about empty char literal. */ \
obstack_1grow (&obstack_for_string, '?'); \
} \
} while (0)
/* The current file name. Might change with #line. */ /* The current file name. Might change with #line. */
static uniqstr current_file = NULL; static uniqstr current_file = NULL;
@@ -290,6 +307,7 @@ eqopt ({sp}=)?
"%"{id} { "%"{id} {
complain (loc, complaint, _("invalid directive: %s"), quote (yytext)); complain (loc, complaint, _("invalid directive: %s"), quote (yytext));
return GRAM_error;
} }
":" return COLON; ":" return COLON;
@@ -311,6 +329,7 @@ eqopt ({sp}=)?
accept "1FOO" as "1 FOO". */ accept "1FOO" as "1 FOO". */
{int}{id} { {int}{id} {
complain (loc, complaint, _("invalid identifier: %s"), quote (yytext)); complain (loc, complaint, _("invalid identifier: %s"), quote (yytext));
return GRAM_error;
} }
/* Characters. */ /* Characters. */
@@ -361,10 +380,11 @@ eqopt ({sp}=)?
BEGIN SC_BRACKETED_ID; BEGIN SC_BRACKETED_ID;
} }
[^\[%A-Za-z0-9_<>{}\"\'*;|=/, \f\r\n\t\v]+|. { [^\[%A-Za-z0-9_<>{}""''*;|=/, \f\r\n\t\v]+|. {
complain (loc, complaint, "%s: %s", complain (loc, complaint, "%s: %s",
ngettext ("invalid character", "invalid characters", yyleng), ngettext ("invalid character", "invalid characters", yyleng),
quote_mem (yytext, yyleng)); quote_mem (yytext, yyleng));
return GRAM_error;
} }
<<EOF>> { <<EOF>> {
@@ -381,7 +401,11 @@ eqopt ({sp}=)?
<SC_ESCAPED_CHARACTER,SC_ESCAPED_STRING,SC_ESCAPED_TSTRING,SC_TAG> <SC_ESCAPED_CHARACTER,SC_ESCAPED_STRING,SC_ESCAPED_TSTRING,SC_TAG>
{ {
\0 complain (loc, complaint, _("invalid null character")); \0 {
complain (loc, complaint, _("invalid null character"));
STRING_FREE;
return GRAM_error;
}
} }
@@ -437,6 +461,7 @@ eqopt ({sp}=)?
complain (loc, complaint, complain (loc, complaint,
_("unexpected identifier in bracketed name: %s"), _("unexpected identifier in bracketed name: %s"),
quote (yytext)); quote (yytext));
return GRAM_error;
} }
else else
{ {
@@ -457,7 +482,10 @@ eqopt ({sp}=)?
} }
} }
else else
complain (loc, complaint, _("an identifier expected")); {
complain (loc, complaint, _("an identifier expected"));
return GRAM_error;
}
} }
[^\].A-Za-z0-9_/ \f\r\n\t\v]+|. { [^\].A-Za-z0-9_/ \f\r\n\t\v]+|. {
@@ -465,6 +493,7 @@ eqopt ({sp}=)?
ngettext ("invalid character in bracketed name", ngettext ("invalid character in bracketed name",
"invalid characters in bracketed name", yyleng), "invalid characters in bracketed name", yyleng),
quote_mem (yytext, yyleng)); quote_mem (yytext, yyleng));
return GRAM_error;
} }
<<EOF>> { <<EOF>> {
@@ -563,22 +592,27 @@ eqopt ({sp}=)?
{ {
"'" { "'" {
STRING_FINISH; STRING_FINISH;
BEGIN INITIAL;
loc->start = token_start; loc->start = token_start;
val->CHAR = last_string[0]; val->CHAR = last_string[0];
/* FIXME: Eventually, make these errors. */
if (last_string[0] == '\0') if (last_string[0] == '\0')
{ {
complain (loc, Wother, _("empty character literal")); complain (loc, complaint, _("empty character literal"));
/* '\0' seems dangerous even if we are about to complain. */ STRING_FREE;
val->CHAR = '\''; return GRAM_error;
} }
else if (last_string[1] != '\0') else if (last_string[1] != '\0')
complain (loc, Wother, {
_("extra characters in character literal")); complain (loc, complaint, _("extra characters in character literal"));
STRING_FREE; STRING_FREE;
BEGIN INITIAL; return GRAM_error;
return CHAR; }
else
{
STRING_FREE;
return CHAR;
}
} }
{eol} unexpected_newline (token_start, "'"); {eol} unexpected_newline (token_start, "'");
<<EOF>> unexpected_eof (token_start, "'"); <<EOF>> unexpected_eof (token_start, "'");
@@ -620,22 +654,12 @@ eqopt ({sp}=)?
{ {
\\[0-7]{1,3} { \\[0-7]{1,3} {
verify (UCHAR_MAX < ULONG_MAX); verify (UCHAR_MAX < ULONG_MAX);
long c = strtol (yytext + 1, NULL, 8); STRING_GROW_ESCAPE (strtol (yytext + 1, NULL, 8));
if (0 < c && c <= UCHAR_MAX)
obstack_1grow (&obstack_for_string, c);
else
complain (loc, complaint, _("invalid number after \\-escape: %s"),
yytext+1);
} }
\\x[0-9abcdefABCDEF]+ { \\x[0-9abcdefABCDEF]+ {
verify (UCHAR_MAX < ULONG_MAX); verify (UCHAR_MAX < ULONG_MAX);
long c = strtol (yytext + 2, NULL, 16); STRING_GROW_ESCAPE (strtol (yytext + 2, NULL, 16));
if (0 < c && c <= UCHAR_MAX)
obstack_1grow (&obstack_for_string, c);
else
complain (loc, complaint, _("invalid number after \\-escape: %s"),
yytext+1);
} }
\\a obstack_1grow (&obstack_for_string, '\a'); \\a obstack_1grow (&obstack_for_string, '\a');
@@ -650,13 +674,9 @@ eqopt ({sp}=)?
\\("\""|"'"|"?"|"\\") obstack_1grow (&obstack_for_string, yytext[1]); \\("\""|"'"|"?"|"\\") obstack_1grow (&obstack_for_string, yytext[1]);
\\(u|U[0-9abcdefABCDEF]{4})[0-9abcdefABCDEF]{4} { \\(u|U[0-9abcdefABCDEF]{4})[0-9abcdefABCDEF]{4} {
int c = convert_ucn_to_byte (yytext); STRING_GROW_ESCAPE (convert_ucn_to_byte (yytext));
if (c <= 0)
complain (loc, complaint, _("invalid number after \\-escape: %s"),
yytext+1);
else
obstack_1grow (&obstack_for_string, c);
} }
\\(.|{eol}) { \\(.|{eol}) {
char const *p = yytext + 1; char const *p = yytext + 1;
/* Quote only if escaping won't make the character visible. */ /* Quote only if escaping won't make the character visible. */
@@ -666,6 +686,7 @@ eqopt ({sp}=)?
p = quotearg_style_mem (escape_quoting_style, p, 1); p = quotearg_style_mem (escape_quoting_style, p, 1);
complain (loc, complaint, _("invalid character after \\-escape: %s"), complain (loc, complaint, _("invalid character after \\-escape: %s"),
p); p);
obstack_1grow (&obstack_for_string, '?');
} }
} }
+1 -1
View File
@@ -84,7 +84,7 @@ static void fail_for_invalid_at (char const *at);
"@output(" at_init (&argc, argv, &at_ptr, &at_output); "@output(" at_init (&argc, argv, &at_ptr, &at_output);
/* This pattern must not match more than the previous @ patterns. */ /* This pattern must not match more than the previous @ patterns. */
@[^@{}\'(\n]* fail_for_invalid_at (yytext); @[^@{}''(\n]* fail_for_invalid_at (yytext);
\n out_lineno++; ECHO; \n out_lineno++; ECHO;
[^@\n]+ ECHO; [^@\n]+ ECHO;
+4 -1
View File
@@ -67,7 +67,10 @@
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).
For each state, the tokens that are errors for this reason are For each state, the tokens that are errors for this reason are
recorded in an errs structure, which holds the token numbers. recorded in an errs structure. The generated parser does not
depend on this errs structure, it is used only in the reports
(*.output, etc.) to describe conflicted actions that have been
discarded.
There is at least one goto transition present in state zero. It There is at least one goto transition present in state zero. It
leads to a next-to-final state whose accessing_symbol is the leads to a next-to-final state whose accessing_symbol is the
+29 -2
View File
@@ -847,8 +847,8 @@ symbols_new (void)
accept->content->class = nterm_sym; accept->content->class = nterm_sym;
accept->content->number = nvars++; accept->content->number = nvars++;
/* Construct the YYERRCODE/"error" token */ /* Construct the YYerror/"error" token */
errtoken = symbol_get ("YYERRCODE", empty_loc); errtoken = symbol_get ("YYerror", empty_loc);
errtoken->content->class = token_sym; errtoken->content->class = token_sym;
errtoken->content->number = ntokens++; errtoken->content->number = ntokens++;
{ {
@@ -1095,6 +1095,21 @@ symbols_token_translations_init (void)
} }
/* Whether some symbol requires internationalization. */
static bool
has_translations (void)
{
for (const void *entry = hash_get_first (symbol_table);
entry;
entry = hash_get_next (symbol_table, entry))
{
const symbol *sym = (const symbol *) entry;
if (sym->translatable)
return true;
}
return false;
}
/*----------------------------------------------------------------. /*----------------------------------------------------------------.
| Assign symbol numbers, and write definition of token names into | | Assign symbol numbers, and write definition of token names into |
| FDEFINES. Set up vectors SYMBOL_TABLE, TAGS of symbols. | | FDEFINES. Set up vectors SYMBOL_TABLE, TAGS of symbols. |
@@ -1137,6 +1152,18 @@ symbols_pack (void)
complain (&startsymbol_loc, fatal, complain (&startsymbol_loc, fatal,
_("the start symbol %s is a token"), _("the start symbol %s is a token"),
startsymbol->tag); startsymbol->tag);
// If some user tokens are internationalized, the internal ones
// should be too.
if (has_translations ())
{
const bool eof_is_user_defined
= !endtoken->alias || STRNEQ (endtoken->alias->tag, "$end");
if (!eof_is_user_defined)
endtoken->alias->translatable = true;
undeftoken->alias->translatable = true;
errtoken->alias->translatable = true;
}
} }
/*---------------------------------. /*---------------------------------.
+41
View File
@@ -144,3 +144,44 @@ export LC_CTYPE
# Empty if no xsltproc was found # Empty if no xsltproc was found
: ${XSLTPROC='@XSLTPROC@'} : ${XSLTPROC='@XSLTPROC@'}
# Some tests expect a precise diff format. See AT_DIFF_U_CHECK.
# See https://lists.gnu.org/r/bug-bison/2020-05/msg00049.html.
cat >conftest.1 <<EOF
1
2
3
4
5
6
EOF
cat >conftest.2 <<EOF
1
22
3
4
55
6
EOF
cat >conftest.expected <<EOF
@@ -1,6 +1,6 @@
1
-2
+22
3
4
-5
+55
6
EOF
diff -u conftest.1 conftest.2 2>/dev/null | sed -n '/^@@/,$p' | sed 's/^ $//' >conftest.diff
if diff conftest.expected conftest.diff >/dev/null; then
DIFF_U_WORKS=true
else
DIFF_U_WORKS=false
fi
rm conftest.*
+18 -11
View File
@@ -109,11 +109,6 @@ AT_DATA_GRAMMAR([list.yy],
%define parse.assert %define parse.assert
%debug %debug
%code top
{
// Get access to stack_symbol_type for the tests.
# define private public
}
%code provides %code provides
{ {
]AT_YYLEX_DECLARE[ ]AT_YYLEX_DECLARE[
@@ -136,6 +131,14 @@ AT_DATA_GRAMMAR([list.yy],
%code requires { #include <vector> } %code requires { #include <vector> }
%code { int yylex (yy::parser::semantic_type* lvalp); } %code { int yylex (yy::parser::semantic_type* lvalp); }
// A hack which relies on internal hooks to check stack_symbol_type,
// which is private.
%code yy_bison_internal_hook {
public:
typedef stack_symbol_type yy_stack_symbol_type;
typedef stack_type yy_stack_type;
}
%% %%
exp: "int" { $$.push_back ($1); } exp: "int" { $$.push_back ($1); }
%% %%
@@ -157,6 +160,9 @@ int main()
// symbol_type: construction, accessor. // symbol_type: construction, accessor.
{ {
parser::symbol_type s = parser::make_INT (12); parser::symbol_type s = parser::make_INT (12);
assert_eq (s.kind (), parser::symbol_kind::S_INT);
assert_eq (parser::symbol_name (s.kind ()), std::string ("\"int\""));
assert_eq (s.name (), std::string ("\"int\""));
assert_eq (s.value.as<int> (), 12); assert_eq (s.value.as<int> (), 12);
} }
@@ -180,12 +186,13 @@ int main()
} }
// stack_symbol_type: construction, accessor. // stack_symbol_type: construction, accessor.
typedef parser::yy_stack_symbol_type stack_symbol_type;
{ {
#if 201103L <= YY_CPLUSPLUS #if 201103L <= YY_CPLUSPLUS
auto ss = parser::stack_symbol_type(1, parser::make_INT(123)); auto ss = stack_symbol_type (1, parser::make_INT(123));
#else #else
parser::symbol_type s = parser::make_INT (123); parser::symbol_type s = parser::make_INT (123);
parser::stack_symbol_type ss(1, s); stack_symbol_type ss(1, s);
#endif #endif
assert_eq (ss.value.as<int> (), 123); assert_eq (ss.value.as<int> (), 123);
} }
@@ -194,17 +201,17 @@ int main()
// Sufficiently many so that it will be resized. // Sufficiently many so that it will be resized.
// Probably 3 times (starting at 200). // Probably 3 times (starting at 200).
{ {
parser::stack_type st; parser::yy_stack_type st;
const int mucho = 1700; const int mucho = 1700;
const int int_reduction_state = 1; // Read list.output to find it. const int int_reduction_state = 1; // Read list.output to find it.
for (int i = 0; i < mucho; ++i) for (int i = 0; i < mucho; ++i)
{ {
#if 201103L <= YY_CPLUSPLUS #if 201103L <= YY_CPLUSPLUS
st.push(parser::stack_symbol_type{int_reduction_state, st.push(stack_symbol_type{int_reduction_state,
parser::make_INT (i)}); parser::make_INT (i)});
#else #else
parser::symbol_type s = parser::make_INT (i); parser::symbol_type s = parser::make_INT (i);
parser::stack_symbol_type ss (int_reduction_state, s); stack_symbol_type ss (int_reduction_state, s);
st.push (ss); st.push (ss);
#endif #endif
} }
+58 -9
View File
@@ -201,8 +201,8 @@ read_integer (]AT_YYLEX_FORMALS[)
/* Skip white spaces. */ /* Skip white spaces. */
do do
{ {
]AT_LOCATION_IF( ]AT_LOCATION_IF([
[ AT_LOC_FIRST_COLUMN = AT_LOC_LAST_COLUMN; AT_LOC_FIRST_COLUMN = AT_LOC_LAST_COLUMN;
AT_LOC_FIRST_LINE = AT_LOC_LAST_LINE; AT_LOC_FIRST_LINE = AT_LOC_LAST_LINE;
])[ ])[
} }
@@ -220,6 +220,15 @@ read_integer (]AT_YYLEX_FORMALS[)
if (c == EOF) if (c == EOF)
return ]AT_TOKEN_PREFIX[CALC_EOF; return ]AT_TOKEN_PREFIX[CALC_EOF;
/* An explicit error raised by the scanner. */
if (c == '#')
{]AT_LOCATION_IF([
fprintf (stderr, "%d.%d: ",
AT_LOC_FIRST_LINE, AT_LOC_FIRST_COLUMN);])[
fputs ("syntax error: invalid character: '#'\n", stderr);
return ]AT_TOKEN_PREFIX[]AT_API_PREFIX[error;
}
/* Return single chars. */ /* Return single chars. */
return c; return c;
} }
@@ -304,7 +313,7 @@ class CalcLexer(R) : Lexer
location.end.column += 1;]])[ location.end.column += 1;]])[
} }
// Handle EOF. // EOF.
if (input.empty) if (input.empty)
return TokenKind.CALC_EOF; return TokenKind.CALC_EOF;
@@ -325,6 +334,14 @@ class CalcLexer(R) : Lexer
else else
location.end.column += 1;]])[ location.end.column += 1;]])[
input.popFront; input.popFront;
// An explicit error raised by the scanner. */
if (c == '#')
{
stderr.writeln (]AT_LOCATION_IF([location, ": ", ])["syntax error: invalid character: '#'");
return TokenKind.YYerror;
}
return c; return c;
} }
} }
@@ -370,12 +387,12 @@ m4_define([AT_CALC_YYLEX(java)],
public int yylex () throws IOException {;]AT_LOCATION_IF([[ public int yylex () throws IOException {;]AT_LOCATION_IF([[
start.set (reader.getPosition ());]])[ start.set (reader.getPosition ());]])[
int ttype = st.nextToken ();]AT_LOCATION_IF([[ int tkind = st.nextToken ();]AT_LOCATION_IF([[
end.set (reader.getPosition ());]])[ end.set (reader.getPosition ());]])[
switch (ttype) switch (tkind)
{ {
case StreamTokenizer.TT_EOF: case StreamTokenizer.TT_EOF:
return EOF; return CALC_EOF;
case StreamTokenizer.TT_EOL:;]AT_LOCATION_IF([[ case StreamTokenizer.TT_EOL:;]AT_LOCATION_IF([[
end.line += 1; end.line += 1;
end.column = 0;]])[ end.column = 0;]])[
@@ -386,8 +403,11 @@ m4_define([AT_CALC_YYLEX(java)],
return NUM; return NUM;
case ' ': case '\t': case ' ': case '\t':
return yylex (); return yylex ();
case '#':
System.err.println(]AT_LOCATION_IF([[start + ": " + ]])["syntax error: invalid character: '#'");
return YYerror;
default: default:
return ttype; return tkind;
} }
} }
]AT_LEXPARAM_IF([], [[}]])[ ]AT_LEXPARAM_IF([], [[}]])[
@@ -763,8 +783,8 @@ AT_JAVA_IF(
[AT_PARSER_CHECK([calc input], 0, [AT_PARAM_IF([m4_n([$3])])], [stderr])]) [AT_PARSER_CHECK([calc input], 0, [AT_PARAM_IF([m4_n([$3])])], [stderr])])
AT_LANG_MATCH([c\|c++\|java], AT_LANG_MATCH([c\|c++\|java],
[AT_GLR_IF([], [AT_GLR_IF([],
[AT_CHECK([grep -v 'Return for a new token:' stderr | wc -l], [AT_CHECK([grep -c -v 'Return for a new token:' stderr],
[0], [ignore],
[m4_n([AT_DEBUG_IF([$4], [0])])])])]) [m4_n([AT_DEBUG_IF([$4], [0])])])])])
]) ])
@@ -1004,6 +1024,35 @@ _AT_CHECK_CALC_ERROR([$1], [0], [(* *) + (*) + (*)],
]AT_JAVA_IF([1.10-1.11], [1.10])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!']) ]AT_JAVA_IF([1.10-1.11], [1.10])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
]AT_JAVA_IF([1.16-1.17], [1.16])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])]]) ]AT_JAVA_IF([1.16-1.17], [1.16])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])]])
# YYerror.
# --------
# Check that returning YYerror from the scanner properly enters
# error-recovery without issuing a second error message.
_AT_CHECK_CALC_ERROR([$1], [0], [(#) + (#) = 2222],
[[final: 2222 0 0]],
[102],
[[1.2: syntax error: invalid character: '#'
1.8: syntax error: invalid character: '#']])
_AT_CHECK_CALC_ERROR([$1], [0], [(1 + #) = 1111],
[[final: 1111 0 0]],
[102],
[[1.6: syntax error: invalid character: '#']])
_AT_CHECK_CALC_ERROR([$1], [0], [(# + 1) = 1111],
[[final: 1111 0 0]],
[102],
[[1.2: syntax error: invalid character: '#']])
_AT_CHECK_CALC_ERROR([$1], [0], [(1 + # + 1) = 1111],
[[final: 1111 0 0]],
[102],
[[1.6: syntax error: invalid character: '#']])
AT_BISON_OPTION_POPDEFS AT_BISON_OPTION_POPDEFS
AT_CLEANUP AT_CLEANUP
+27 -13
View File
@@ -19,7 +19,7 @@ AT_BANNER([[Diagnostics.]])
# AT_TEST($1: TITLE, $2: GRAMMAR, $3: EXIT-STATUS, $4: OUTPUT-WITH-STYLE, # AT_TEST($1: TITLE, $2: GRAMMAR, $3: EXIT-STATUS, $4: OUTPUT-WITH-STYLE,
# $5: EXTRA_ENV # $5: EXTRA_ENV, $6: SKIP-IF)
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
# Run Bison on GRAMMAR with debugging style enabled, and expect # Run Bison on GRAMMAR with debugging style enabled, and expect
# OUTPUT-WITH-STYLE as diagnostics. # OUTPUT-WITH-STYLE as diagnostics.
@@ -33,6 +33,9 @@ AT_KEYWORDS([diagnostics])
locale=`locale -a | $EGREP '^en_US\.(UTF-8|utf8)$' | sed 1q` locale=`locale -a | $EGREP '^en_US\.(UTF-8|utf8)$' | sed 1q`
AT_SKIP_IF([test x == x"$locale"]) AT_SKIP_IF([test x == x"$locale"])
m4_ifval([$6],
[AT_SKIP_IF([$6])])
AT_BISON_OPTION_PUSHDEFS AT_BISON_OPTION_PUSHDEFS
AT_DATA_GRAMMAR([[input.y]], [$2]) AT_DATA_GRAMMAR([[input.y]], [$2])
@@ -220,15 +223,14 @@ exp: an\005error.
AT_TEST([[Tabulations and multibyte characters]], AT_TEST([[Tabulations and multibyte characters]],
[[%% [[%%
exp: a b c d e f g h exp: a b c d e f g
a: { } a: { }
b: { } b: { }
c: {------------} c: {------------}
d: {éééééééééééé} d: {éééééééééééé}
e: {∇⃗×𝐸⃗ = -∂𝐵⃗/∂t} e: { 42 }
f: { 42 } f: { "฿¥$€₦" }
g: { "฿¥$€₦" } g: { 🐃 }
h: { 🐃 }
]], ]],
[0], [0],
[[input.y:11.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>] [[input.y:11.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
@@ -248,25 +250,37 @@ input.y:14.4-17: <warning>warning:</warning> empty rule without %empty [<warning
| <warning>^~~~~~~~~~~~~~</warning> | <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%empty</fixit-insert> | <fixit-insert>%empty</fixit-insert>
input.y:15.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>] input.y:15.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
15 | e: <warning>{∇⃗×𝐸⃗ = -∂𝐵⃗/∂t}</warning> 15 | e: <warning>{ 42 }</warning>
| <warning>^~~~~~~~~~~~~~</warning> | <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%empty</fixit-insert> | <fixit-insert>%empty</fixit-insert>
input.y:16.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>] input.y:16.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
16 | f: <warning>{ 42 }</warning> 16 | f: <warning>{ "฿¥$€₦" }</warning>
| <warning>^~~~~~~~~~~~~~</warning> | <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%empty</fixit-insert> | <fixit-insert>%empty</fixit-insert>
input.y:17.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>] input.y:17.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
17 | g: <warning>{ "฿¥$€₦" }</warning> 17 | g: <warning>{ 🐃 }</warning>
| <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%empty</fixit-insert>
input.y:18.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
18 | h: <warning>{ 🐃 }</warning>
| <warning>^~~~~~~~~~~~~~</warning> | <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%empty</fixit-insert> | <fixit-insert>%empty</fixit-insert>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>] input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]]) ]])
# Likewise, but currently not portable to AIX and Cygwin.
# https://lists.gnu.org/r/bug-bison/2020-05/msg00050.html
# https://lists.gnu.org/r/bug-bison/2020-05/msg00003.html.
AT_TEST([[Tabulations and multibyte characters]],
[[%%
e: {∇⃗×𝐸⃗ = -∂𝐵⃗/∂t}
]],
[0],
[[input.y:10.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
10 | e: <warning>{∇⃗×𝐸⃗ = -∂𝐵⃗/∂t}</warning>
| <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%empty</fixit-insert>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]], [], [uname -a | $EGREP -i 'aix|cygwin'])
## --------------- ## ## --------------- ##
## Special files. ## ## Special files. ##
## --------------- ## ## --------------- ##
+2 -7
View File
@@ -35,14 +35,9 @@ dnl time comes, just use sed to drop the line numbers. For now, as LR(1)
dnl support is rapidly evolving, let's keep that information to be careful. dnl support is rapidly evolving, let's keep that information to be careful.
dnl However, we don't do diffs for canonical LR(1) because the diff is huge. dnl However, we don't do diffs for canonical LR(1) because the diff is huge.
m4_pushdef([AT_LALR1_DIFF_CHECK], m4_pushdef([AT_LALR1_DIFF_CHECK],
[dnl We need diff -u, which is not portable. [AT_CHECK([[sed 's/^%define lr.type .*$//' input.y > input-lalr.y]])
AT_CHECK([diff -u /dev/null /dev/null || exit 77], [0], [ignore])
AT_CHECK([[sed 's/^%define lr.type .*$//' input.y > input-lalr.y]])
AT_BISON_CHECK([[--report=all input-lalr.y]], [[0]], [ignore], [ignore]) AT_BISON_CHECK([[--report=all input-lalr.y]], [[0]], [ignore], [ignore])
AT_CHECK([[diff -u input-lalr.output input.output \ AT_DIFF_U_CHECK([[input-lalr.output input.output]], [$1])])
| sed -n '/^@@/,$p' | sed 's/^ $//']],
[[0]], [$1])])
AT_TEST_TABLES_AND_PARSE([$2[: LALR(1)]], [[LALR]], [[last-state]], AT_TEST_TABLES_AND_PARSE([$2[: LALR(1)]], [[LALR]], [[last-state]],
[[%define lr.type lalr [[%define lr.type lalr
+1 -1
View File
@@ -323,7 +323,7 @@ AT_PERL_CHECK([[-n -0777 -e '
|YYChar |YYChar
|YYNTOKENS # This is actual scoped in a C++ class. |YYNTOKENS # This is actual scoped in a C++ class.
|YYPUSH_MORE(?:_DEFINED)? |YYPUSH_MORE(?:_DEFINED)?
|S_(YY(ACCEPT|EMPTY|EOF|ERROR|UNDEF)) # These guys are scoped. |S_(YY(ACCEPT|EMPTY|EOF|error|UNDEF)) # These guys are scoped.
|YYUSE |YYUSE
|YY_ATTRIBUTE(?:_PURE|_UNUSED) |YY_ATTRIBUTE(?:_PURE|_UNUSED)
|YY(?:_REINTERPRET)?_CAST |YY(?:_REINTERPRET)?_CAST
+30 -24
View File
@@ -102,7 +102,6 @@ input.y:6.1-17: error: invalid directive: '%a-does-not-exist'
input.y:7.1: error: invalid character: '%' input.y:7.1: error: invalid character: '%'
input.y:7.2: error: invalid character: '-' input.y:7.2: error: invalid character: '-'
input.y:8.1-9.0: error: missing '%}' at end of file input.y:8.1-9.0: error: missing '%}' at end of file
input.y:8.1-9.0: error: unexpected %{...%}
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -343,9 +342,9 @@ exp:
%% %%
int main (void) int main (void)
{ {
assert (YYERRCODE == 123); assert (YYerror == 123);
assert (YYTRANSLATE (YYEOF) == YYSYMBOL_YYEOF); assert (YYTRANSLATE (YYEOF) == YYSYMBOL_YYEOF);
assert (YYTRANSLATE (YYERRCODE) == YYSYMBOL_YYERROR); assert (YYTRANSLATE (YYerror) == YYSYMBOL_YYerror);
assert (YYTRANSLATE (YYUNDEF) == YYSYMBOL_YYUNDEF); assert (YYTRANSLATE (YYUNDEF) == YYSYMBOL_YYUNDEF);
return 0; return 0;
} }
@@ -432,7 +431,7 @@ AT_BISON_CHECK([-Wno-other -S./dump-symbols.m4 input.y])
AT_CHECK([cat symbols.csv], [], AT_CHECK([cat symbols.csv], [],
[[number, class, tag, id, user_number, type, [[number, class, tag, id, user_number, type,
0, Token, "end of file", YYEOF, 0, , 0, Token, "end of file", YYEOF, 0, ,
1, Token, error, YYERRCODE, 256, , 1, Token, error, YYerror, 256, ,
2, Token, "invalid token", YYUNDEF, 257, , 2, Token, "invalid token", YYUNDEF, 257, ,
3, Token, 'a', , 97, , 3, Token, 'a', , 97, ,
4, Token, "A1", A1, 1, , 4, Token, "A1", A1, 1, ,
@@ -1353,8 +1352,20 @@ AT_BISON_CHECK([-fcaret input.y], [1], [],
]]) ]])
# Clang chokes on some of our comments, because it tries to "parse"
# some documentation directives in the comments:
#
# input.c:166:50: error: '\a' command does not have a valid word argument [-Werror,-Wdocumentation]
# FAKE = 258 /* "fake [] \a\b\f\n\r\t\v\"'?\\[\\ ??!??'??(??)??-??/??<??=??> \001\001" */
# ~~^
AT_DATA_GRAMMAR([input.y], AT_DATA_GRAMMAR([input.y],
[[%{ [[%code requires {
#if defined __clang__ && 10 <= __clang_major__
# pragma clang diagnostic ignored "-Wdocumentation"
#endif
}
%{
/* This is seen in GCC: a %{ and %} in middle of a comment. */ /* This is seen in GCC: a %{ and %} in middle of a comment. */
const char *foo = "So %{ and %} can be here too."; const char *foo = "So %{ and %} can be here too.";
@@ -1425,6 +1436,11 @@ char quote[] = "@:>@@:>@,";
/* Exercise quotes in strings. */ /* Exercise quotes in strings. */
%token FAKE "fake @<:@@:>@ \a\b\f\n\r\t\v\"\'\?\\\u005B\U0000005c ??!??'??(??)??-??/??<??=??> \x1\1" %token FAKE "fake @<:@@:>@ \a\b\f\n\r\t\v\"\'\?\\\u005B\U0000005c ??!??'??(??)??-??/??<??=??> \x1\1"
/* Beware of the generated comments that embed string aliases that
might close the comment. */
%token COMMENT_CLOSE "*/"
%token COMMENT "/* comment */"
%% %%
/* Exercise M4 quoting: '@:>@@:>@', @<:@, 1. */ /* Exercise M4 quoting: '@:>@@:>@', @<:@, 1. */
exp: '@<:@' '\1' two '$' '@' '{' oline output.or.oline.opt exp: '@<:@' '\1' two '$' '@' '{' oline output.or.oline.opt
@@ -2339,19 +2355,19 @@ start: '
start: ']]) start: ']])
AT_BISON_CHECK([-fcaret empty.y], [1], [], AT_BISON_CHECK([-fcaret empty.y], [1], [],
[[empty.y:2.8-9: warning: empty character literal [-Wother] [[empty.y:2.8-9: error: empty character literal
2 | start: ''; 2 | start: '';
| ^~ | ^~
empty.y:3.8-4.0: error: missing "'" at end of line empty.y:3.8-4.0: error: missing "'" at end of line
3 | start: ' 3 | start: '
| ^ | ^
empty.y:3.8-4.0: warning: empty character literal [-Wother] empty.y:3.8-4.0: error: empty character literal
3 | start: ' 3 | start: '
| ^ | ^
empty.y:4.8: error: missing "'" at end of file empty.y:4.8: error: missing "'" at end of file
4 | start: ' 4 | start: '
| ^ | ^
empty.y:4.8: warning: empty character literal [-Wother] empty.y:4.8: error: empty character literal
4 | start: ' 4 | start: '
| ^ | ^
]]) ]])
@@ -2363,11 +2379,11 @@ start: 'ab
start: 'ab]]) start: 'ab]])
AT_BISON_CHECK([two.y], [1], [], AT_BISON_CHECK([two.y], [1], [],
[[two.y:2.8-11: warning: extra characters in character literal [-Wother] [[two.y:2.8-11: error: extra characters in character literal
two.y:3.8-4.0: error: missing "'" at end of line two.y:3.8-4.0: error: missing "'" at end of line
two.y:3.8-4.0: warning: extra characters in character literal [-Wother] two.y:3.8-4.0: error: extra characters in character literal
two.y:4.8-10: error: missing "'" at end of file two.y:4.8-10: error: missing "'" at end of file
two.y:4.8-10: warning: extra characters in character literal [-Wother] two.y:4.8-10: error: extra characters in character literal
]]) ]])
AT_DATA_NO_FINAL_EOL([three.y], AT_DATA_NO_FINAL_EOL([three.y],
@@ -2377,11 +2393,11 @@ start: 'abc
start: 'abc]]) start: 'abc]])
AT_BISON_CHECK([three.y], [1], [], AT_BISON_CHECK([three.y], [1], [],
[[three.y:2.8-12: warning: extra characters in character literal [-Wother] [[three.y:2.8-12: error: extra characters in character literal
three.y:3.8-4.0: error: missing "'" at end of line three.y:3.8-4.0: error: missing "'" at end of line
three.y:3.8-4.0: warning: extra characters in character literal [-Wother] three.y:3.8-4.0: error: extra characters in character literal
three.y:4.8-11: error: missing "'" at end of file three.y:4.8-11: error: missing "'" at end of file
three.y:4.8-11: warning: extra characters in character literal [-Wother] three.y:4.8-11: error: extra characters in character literal
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -2408,25 +2424,15 @@ AT_PERL_REQUIRE([[-e 'print "start: \"\\\t\\\f\\\0\\\1\" ;";' >> input.y]])
AT_BISON_CHECK([input.y], [1], [], AT_BISON_CHECK([input.y], [1], [],
[[input.y:2.9-12: error: invalid number after \-escape: 777 [[input.y:2.9-12: error: invalid number after \-escape: 777
input.y:2.8-13: warning: empty character literal [-Wother]
input.y:2.16-17: error: invalid number after \-escape: 0 input.y:2.16-17: error: invalid number after \-escape: 0
input.y:2.15-18: warning: empty character literal [-Wother]
input.y:2.21-25: error: invalid number after \-escape: xfff input.y:2.21-25: error: invalid number after \-escape: xfff
input.y:2.20-26: warning: empty character literal [-Wother]
input.y:2.29-31: error: invalid number after \-escape: x0 input.y:2.29-31: error: invalid number after \-escape: x0
input.y:2.28-32: warning: empty character literal [-Wother]
input.y:3.9-14: error: invalid number after \-escape: uffff input.y:3.9-14: error: invalid number after \-escape: uffff
input.y:3.8-15: warning: empty character literal [-Wother]
input.y:3.18-23: error: invalid number after \-escape: u0000 input.y:3.18-23: error: invalid number after \-escape: u0000
input.y:3.17-24: warning: empty character literal [-Wother]
input.y:3.27-36: error: invalid number after \-escape: Uffffffff input.y:3.27-36: error: invalid number after \-escape: Uffffffff
input.y:3.26-37: warning: empty character literal [-Wother]
input.y:3.40-49: error: invalid number after \-escape: U00000000 input.y:3.40-49: error: invalid number after \-escape: U00000000
input.y:3.39-50: warning: empty character literal [-Wother]
input.y:4.9-10: error: invalid character after \-escape: ' ' input.y:4.9-10: error: invalid character after \-escape: ' '
input.y:4.8-11: warning: empty character literal [-Wother]
input.y:4.14-15: error: invalid character after \-escape: A input.y:4.14-15: error: invalid character after \-escape: A
input.y:4.13-16: warning: empty character literal [-Wother]
input.y:5.9-16: error: invalid character after \-escape: \t input.y:5.9-16: error: invalid character after \-escape: \t
input.y:5.17: error: invalid character after \-escape: \f input.y:5.17: error: invalid character after \-escape: \f
input.y:5.18: error: invalid character after \-escape: \0 input.y:5.18: error: invalid character after \-escape: \0
+37 -37
View File
@@ -18,9 +18,9 @@
AT_BANNER([[Java Calculator.]]) AT_BANNER([[Java Calculator.]])
# ------------------------- # ## ------------------------- ##
# Java invalid directives. # ## Java invalid directives. ##
# ------------------------- # ## ------------------------- ##
AT_SETUP([Java invalid directives]) AT_SETUP([Java invalid directives])
@@ -42,9 +42,9 @@ YYParser.y:4.13-30: error: %destructor does not make sense in Java
AT_CLEANUP AT_CLEANUP
# ------------------------- # ## ------------------------- ##
# Helping Autotest macros. # ## Helping Autotest macros. ##
# ------------------------- # ## ------------------------- ##
# AT_JAVA_POSITION_DEFINE_OLD # AT_JAVA_POSITION_DEFINE_OLD
@@ -91,9 +91,9 @@ m4_define([AT_JAVA_POSITION_DEFINE_OLD],
# -----------------# ## ----------------- ##
# Java Parameters. # ## Java Parameters. ##
# -----------------# ## ----------------- ##
AT_BANNER([Java Parameters.]) AT_BANNER([Java Parameters.])
@@ -146,7 +146,7 @@ m4_define([AT_CHECK_JAVA_MINIMAL_W_LEXER],
System.err.println (loc + ": " + s); System.err.println (loc + ": " + s);
} }
public int yylex ()$2 public int yylex()$2
{ {
$3 $3
} }
@@ -164,9 +164,9 @@ m4_define([AT_CHECK_JAVA_GREP],
])]) ])])
# ------------------------------------- # ## ------------------------------------- ##
# Java parser class and package names. # ## Java parser class and package names. ##
# ------------------------------------- # ## ------------------------------------- ##
AT_SETUP([Java parser class and package names]) AT_SETUP([Java parser class and package names])
@@ -191,9 +191,9 @@ AT_CHECK_JAVA_GREP([[package user_java_package;]])
AT_CLEANUP AT_CLEANUP
# ----------------------------- # ## ----------------------------- ##
# Java parser class modifiers. # ## Java parser class modifiers. ##
# ----------------------------- # ## ----------------------------- ##
AT_SETUP([Java parser class modifiers]) AT_SETUP([Java parser class modifiers])
@@ -255,9 +255,9 @@ AT_CHECK_JAVA_GREP([[/\*@Deprecated @SuppressWarnings("unchecked") @SuppressWarn
AT_CLEANUP AT_CLEANUP
# ---------------------------------------- # ## ---------------------------------------- ##
# Java parser class extends and implements # ## Java parser class extends and implements ##
# ---------------------------------------- # ## ---------------------------------------- ##
AT_SETUP([Java parser class extends and implements]) AT_SETUP([Java parser class extends and implements])
@@ -275,9 +275,9 @@ AT_CHECK_JAVA_GREP([[class YYParser extends Thread implements Cloneable]])
AT_CLEANUP AT_CLEANUP
# -------------------------------- # ## -------------------------------- ##
# Java %parse-param and %lex-param # ## Java %parse-param and %lex-param ##
# -------------------------------- # ## -------------------------------- ##
AT_SETUP([Java %parse-param and %lex-param]) AT_SETUP([Java %parse-param and %lex-param])
@@ -349,9 +349,9 @@ AT_CHECK_JAVA_GREP([[ *this.parse_param2 = parse_param2;]], [2])
AT_CLEANUP AT_CLEANUP
# ------------------------- # ## --------------------------- ##
# Java throw specifications # ## Java throw specifications. ##
# ------------------------- # ## --------------------------- ##
AT_SETUP([Java throws specifications]) AT_SETUP([Java throws specifications])
@@ -430,17 +430,17 @@ AT_JT_initial_action],
[AT_JT_yylex_action], [AT_JT_yylex_action],
[], [],
[AT_JT_parse_action])]) [AT_JT_parse_action])])
AT_CHECK_JAVA_GREP([[ *int yylex ()]AT_JT_yylex_throws *[;]]) AT_CHECK_JAVA_GREP([[ *int yylex()]AT_JT_yylex_throws *[;]])
AT_CHECK_JAVA_GREP([[ *private int yyaction ([^)]*)]AT_JT_yyaction_throws[ *]]) AT_CHECK_JAVA_GREP([[ *private int yyaction([^)]*)]AT_JT_yyaction_throws[ *]])
AT_CHECK_JAVA_GREP([[ *public boolean parse ()]AT_JT_parse_throws[ *]]) AT_CHECK_JAVA_GREP([[ *public boolean parse()]AT_JT_parse_throws[ *]])
])])]) ])])])
AT_CLEANUP AT_CLEANUP
# ------------------------------------- # ## --------------------------------------- ##
# Java constructor init and init_throws # ## Java constructor init and init_throws. ##
# ------------------------------------- # ## --------------------------------------- ##
AT_SETUP([Java constructor init and init_throws]) AT_SETUP([Java constructor init and init_throws])
@@ -465,9 +465,9 @@ m4_popdef([AT_Witness])
AT_CLEANUP AT_CLEANUP
# ------------------------------------------ # ## ------------------------------------------ ##
# Java value, position, and location types. # ## Java value, position, and location types. ##
# ------------------------------------------ # ## ------------------------------------------ ##
AT_SETUP([Java value, position, and location types]) AT_SETUP([Java value, position, and location types])
@@ -496,9 +496,9 @@ AT_CHECK([[$EGREP -v ' */?\*' YYParser.java | grep -w 'Location']], [1], [ignore
AT_CLEANUP AT_CLEANUP
# ----------------------------------------------- # ## ------------------------------------------------ ##
# Java syntax error handling without error token. # ## Java syntax error handling without error token. ##
# ----------------------------------------------- # ## ------------------------------------------------ ##
AT_SETUP([Java syntax error handling without error token]) AT_SETUP([Java syntax error handling without error token])
+6 -6
View File
@@ -180,28 +180,28 @@ AT_DATA([[input.y]],
# Verify that the proper procedure(s) are generated for each case. # Verify that the proper procedure(s) are generated for each case.
AT_BISON_CHECK([[-Dapi.push-pull=pull -o Main.java input.y]]) AT_BISON_CHECK([[-Dapi.push-pull=pull -o Main.java input.y]])
AT_CHECK_JAVA_GREP([[Main.java]], AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public boolean parse ().*]], [[.*public boolean parse().*]],
[1]) [1])
# If BISON_USE_PUSH_FOR_PULL is set, then we have one occurrence of # If BISON_USE_PUSH_FOR_PULL is set, then we have one occurrence of
# this function, otherwise it should not be there. # this function, otherwise it should not be there.
AT_CHECK_JAVA_GREP([[Main.java]], AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public int push_parse (int yylextoken, Object yylexval).*]], [[.*public int push_parse(int yylextoken, Object yylexval).*]],
[${BISON_USE_PUSH_FOR_PULL-0}]) [${BISON_USE_PUSH_FOR_PULL-0}])
AT_BISON_CHECK([[-Dapi.push-pull=both -o Main.java input.y]]) AT_BISON_CHECK([[-Dapi.push-pull=both -o Main.java input.y]])
AT_CHECK_JAVA_GREP([[Main.java]], AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public boolean parse ().*]], [[.*public boolean parse().*]],
[1]) [1])
AT_CHECK_JAVA_GREP([[Main.java]], AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public int push_parse (int yylextoken, Object yylexval).*]], [[.*public int push_parse(int yylextoken, Object yylexval).*]],
[1]) [1])
AT_BISON_CHECK([[-Dapi.push-pull=push -o Main.java input.y]]) AT_BISON_CHECK([[-Dapi.push-pull=push -o Main.java input.y]])
AT_CHECK_JAVA_GREP([[Main.java]], AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public boolean parse ().*]], [[.*public boolean parse().*]],
[0]) [0])
AT_CHECK_JAVA_GREP([[Main.java]], AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public int push_parse (int yylextoken, Object yylexval).*]], [[.*public int push_parse(int yylextoken, Object yylexval).*]],
[1]) [1])
AT_JAVA_COMPILE([[Main.java]]) AT_JAVA_COMPILE([[Main.java]])
+12 -2
View File
@@ -83,6 +83,16 @@ set x `LC_ALL=C ls -l '$1'` &&
## ------------- ## ## ------------- ##
# AT_DIFF_U_CHECK(DIFF-ARGS, EXPECTED-DIFF)
# -----------------------------------------
# If diff -u works as we expect, use it, with headers stripped.
m4_define([AT_DIFF_U_CHECK],
[if $DIFF_U_WORKS; then
AT_CHECK([diff -u $1 | sed -n '/^@@/,$p' | sed 's/^ $//'], [0], [$2])
fi
])
# AT_PERL_CHECK(PERL-ARGS, ...) # AT_PERL_CHECK(PERL-ARGS, ...)
# ----------------------------- # -----------------------------
# If Perl is available, run this test. # If Perl is available, run this test.
@@ -490,7 +500,7 @@ m4_define([AT_DATA_SOURCE_PROLOGUE],
# The prologue that should be included in any grammar whose parser is # The prologue that should be included in any grammar whose parser is
# meant to be compiled. # meant to be compiled.
m4_define([AT_DATA_GRAMMAR_PROLOGUE], m4_define([AT_DATA_GRAMMAR_PROLOGUE],
[[%code top { [[%code top { /* -*- ]AT_LANG[ -*- */
]AT_DATA_SOURCE_PROLOGUE[]dnl ]AT_DATA_SOURCE_PROLOGUE[]dnl
[} [}
]]) ]])
@@ -1601,7 +1611,7 @@ $9
# (C90 and C++98) guarantee: 32767. In that case, GCC's -pedantic # (C90 and C++98) guarantee: 32767. In that case, GCC's -pedantic
# will issue an error. # will issue an error.
# #
# There is no "" around `wc` since some indent the result. # There is no "" around `wc` since some wc indent the result.
m4_bmatch([$4], [%define lr.type canonical-lr], m4_bmatch([$4], [%define lr.type canonical-lr],
[if test 32767 -lt `wc -l < input.c`; then [if test 32767 -lt `wc -l < input.c`; then
CFLAGS=`echo " $CFLAGS " | sed -e 's/ -pedantic / /'` CFLAGS=`echo " $CFLAGS " | sed -e 's/ -pedantic / /'`
+1
View File
@@ -56,6 +56,7 @@ TESTSUITE_AT = \
%D%/java.at \ %D%/java.at \
%D%/javapush.at \ %D%/javapush.at \
%D%/local.at \ %D%/local.at \
%D%/m4.at \
%D%/named-refs.at \ %D%/named-refs.at \
%D%/output.at \ %D%/output.at \
%D%/package.m4 \ %D%/package.m4 \
+72
View File
@@ -0,0 +1,72 @@
# Basic m4 macros. -*- Autotest -*-
# Copyright (C) 2020 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# 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/>.
AT_BANNER([[M4 Macros.]])
AT_SETUP([Generating Comments])
AT_DATA([input.y],
[%%
exp:
])
AT_DATA([input.m4],
[[m4@&t@_include(b4_skeletonsdir/[c.m4])
b4_output_begin([output.txt])
b4_gsub([[abcd]],
[a], [b])
b4_gsub([[abcd]],
[a], [b],
[b], [c],
[c], [d])
_b4_comment([["/* () */"]])
_b4_comment([["/* ( */"]])
_b4_comment([["/* ) */"]])
_b4_comment([["/* [] */"]])
b4_comment([["/* () */"]])
b4_comment([["/* ( */"]])
b4_comment([["/* ) */"]])
b4_comment([["/* [] */"]])
b4_output_end([output.txt])
]])
AT_BISON_CHECK([-S ./input.m4 input.y])
AT_CHECK([cat output.txt], [],
[[
[bbcd]
[dddd]
"/\* () *\/"
"/\* ( *\/"
"/\* ) *\/"
"/\* [] *\/"
/* "/\* () *\/" */
/* "/\* ( *\/" */
/* "/\* ) *\/" */
/* "/\* [] *\/" */
]])
AT_CLEANUP
+17 -6
View File
@@ -372,8 +372,19 @@ m4_pushdef([AT_TEST],
AT_BISON_OPTION_PUSHDEFS([$1]) AT_BISON_OPTION_PUSHDEFS([$1])
# Clang chokes on some of our comments, because it tries to "parse"
# some documentation directives in the comments:
#
# input.c:131:48: error: '\a' command does not have a valid word argument [-Werror,-Wdocumentation]
# SPECIAL = 261 /* "\\'?\"\a\b\f\n\r\t\v\001\201\001\201??!" */
# ~~^
AT_DATA_GRAMMAR([input.y], AT_DATA_GRAMMAR([input.y],
[%{ [%{
#if defined __clang__ && 10 <= __clang_major__
# pragma clang diagnostic ignored "-Wdocumentation"
#endif
]AT_YYERROR_DECLARE[ ]AT_YYERROR_DECLARE[
]AT_YYLEX_DECLARE[ ]AT_YYLEX_DECLARE[
%} %}
@@ -398,14 +409,14 @@ exp: ]AT_ERROR_VERBOSE_IF(["\\\'\?\"\a\b\f\n\r\t\v\001\201\x001\x000081??!"], ["
# C-string literal. Also notice that unnecessary escaping, such as "\?", from # C-string literal. Also notice that unnecessary escaping, such as "\?", from
# the user specification is eliminated. # the user specification is eliminated.
AT_BISON_CHECK([-fcaret -o input.c input.y], [[0]], [[]], AT_BISON_CHECK([-fcaret -o input.c input.y], [[0]], [[]],
[[input.y:22.8-14: warning: symbol SPECIAL redeclared [-Wother] [[input.y:26.8-14: warning: symbol SPECIAL redeclared [-Wother]
22 | %token SPECIAL "\\\'\?\"\a\b\f\n\r\t\v\001\201\x001\x000081??!" 26 | %token SPECIAL "\\\'\?\"\a\b\f\n\r\t\v\001\201\x001\x000081??!"
| ^~~~~~~ | ^~~~~~~
input.y:21.8-14: note: previous declaration input.y:25.8-14: note: previous declaration
21 | %token SPECIAL "\\\'\?\"\a\b\f\n\r\t\v\001\201\x001\x000081??!" 25 | %token SPECIAL "\\\'\?\"\a\b\f\n\r\t\v\001\201\x001\x000081??!"
| ^~~~~~~ | ^~~~~~~
input.y:22.16-63: warning: symbol "\\'?\"\a\b\f\n\r\t\v\001\201\001\201??!" used more than once as a literal string [-Wother] input.y:26.16-63: warning: symbol "\\'?\"\a\b\f\n\r\t\v\001\201\001\201??!" used more than once as a literal string [-Wother]
22 | %token SPECIAL "\\\'\?\"\a\b\f\n\r\t\v\001\201\x001\x000081??!" 26 | %token SPECIAL "\\\'\?\"\a\b\f\n\r\t\v\001\201\x001\x000081??!"
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
]]) ]])
+2
View File
@@ -16,6 +16,8 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# Basic M4 macros.
m4_include([m4.at])
# Resistance to user bugs. # Resistance to user bugs.
m4_include([input.at]) m4_include([input.at])