mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-08-13 04:35:14 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4d18c7fc6 | ||
|
|
3e6e51cf5c | ||
|
|
d309bd9f9f | ||
|
|
203f7230ec | ||
|
|
156e548341 | ||
|
|
526ef45f30 | ||
|
|
d7f7fcd9c7 | ||
|
|
0fd542c3e0 | ||
|
|
413908e5a4 | ||
|
|
84ef175287 | ||
|
|
5234c8390f | ||
|
|
21f7690570 | ||
|
|
edb39c29a2 | ||
|
|
1247d94ba6 | ||
|
|
ed9a821caa | ||
|
|
330552ea49 | ||
|
|
7c609859ee | ||
|
|
ed10c308fa | ||
|
|
b91566edd1 | ||
|
|
29520abb3b | ||
|
|
2491de1eef | ||
|
|
ec207d1bb2 | ||
|
|
688b3404a2 | ||
|
|
cd6ef1e7d7 | ||
|
|
2b518d621f | ||
|
|
1ae4f1d329 | ||
|
|
160df55c56 | ||
|
|
e0b0a67b86 | ||
|
|
0e5cbd38b2 | ||
|
|
feb0bb0a59 | ||
|
|
d796e11f8f | ||
|
|
0895858d8e | ||
|
|
4efb2f7bd2 | ||
|
|
eeafc706e8 | ||
|
|
cf6d8d0631 | ||
|
|
8f44164443 | ||
|
|
1001f48416 | ||
|
|
3be228f64c | ||
|
|
670c7e7a75 | ||
|
|
c4b1a2b68f | ||
|
|
b65bd16e45 | ||
|
|
0f120354b6 | ||
|
|
69e3b405d9 | ||
|
|
3dd8f2305a | ||
|
|
9e75066819 | ||
|
|
efb65daa36 | ||
|
|
e077bf1ebc | ||
|
|
c35e829a76 | ||
|
|
d4f854e5b2 | ||
|
|
35c0fe6789 | ||
|
|
22f62414f9 | ||
|
|
9206b15c4e | ||
|
|
5edac5e15a | ||
|
|
1c3189734c | ||
|
|
c662b23735 | ||
|
|
627fecb19e | ||
|
|
2a069f22c6 | ||
|
|
3f4ffea6f2 | ||
|
|
251e1b137f | ||
|
|
efbcadeca7 | ||
|
|
e4d33cf579 | ||
|
|
5855da4722 | ||
|
|
5d5e1df1dc | ||
|
|
cef13e11f5 | ||
|
|
b7fbfd050e | ||
|
|
e088b4f90f | ||
|
|
c857ed4f72 | ||
|
|
1998606a90 | ||
|
|
b0bb4cde2e | ||
|
|
d2acc4b401 | ||
|
|
a53c6026cd | ||
|
|
ae5edcc23b | ||
|
|
296e2f90ab | ||
|
|
1ccb4be02b | ||
|
|
421662ec88 | ||
|
|
39be113b1f | ||
|
|
2101b0e210 | ||
|
|
b1327c56f7 | ||
|
|
ae03b16785 | ||
|
|
7e16bd2cae | ||
|
|
508ac09939 | ||
|
|
0535d2a608 | ||
|
|
94f7606db6 | ||
|
|
de5be4a693 | ||
|
|
03a6b439f6 | ||
|
|
742910838e | ||
|
|
52ce2a008b | ||
|
|
bb311cfbed | ||
|
|
518dc6ca26 | ||
|
|
6a1a681fd2 | ||
|
|
dd878d1851 | ||
|
|
6ed813c122 | ||
|
|
1ec93ca2a2 | ||
|
|
12f4091de4 | ||
|
|
8ece778cb8 | ||
|
|
f32ba07f94 | ||
|
|
50cd3f16de | ||
|
|
37da3c4b42 | ||
|
|
79bae4d6bb | ||
|
|
23f7554188 | ||
|
|
3ff248ebfe | ||
|
|
4e1a5aae96 | ||
|
|
8e70880af1 | ||
|
|
3fea8fade8 | ||
|
|
e7aff57122 | ||
|
|
339d11badf | ||
|
|
99260caef9 | ||
|
|
c19af5cbb4 | ||
|
|
b54181ff9b | ||
|
|
86c45be582 | ||
|
|
b5e0351c3e | ||
|
|
150b2318ed | ||
|
|
35c4a8e65e | ||
|
|
fc39ccab6b | ||
|
|
9a33fb9317 | ||
|
|
866bc6a49f | ||
|
|
e8619330e8 | ||
|
|
193dc86965 | ||
|
|
51fa2ab0a2 | ||
|
|
2d8c3edbf8 | ||
|
|
4590071287 | ||
|
|
ac3b6c18a5 | ||
|
|
f3ef847539 | ||
|
|
16f2353723 | ||
|
|
da5317cc9d | ||
|
|
e0cb91a922 | ||
|
|
482b370540 | ||
|
|
66283fb625 | ||
|
|
93c849ef0d | ||
|
|
6279945003 | ||
|
|
dcb6c972a2 | ||
|
|
af0441cfd2 | ||
|
|
bbb63b1ca9 | ||
|
|
ac54d19eba | ||
|
|
5807dd9279 | ||
|
|
94bfdf3b4b | ||
|
|
f80890c4bb | ||
|
|
1ebc2ac55c | ||
|
|
94952779b6 | ||
|
|
ed7d5c2b5b | ||
|
|
1ce02e13c3 | ||
|
|
8ef0b12eb7 | ||
|
|
e6d83116ae | ||
|
|
4d9fa28ba8 | ||
|
|
a100a3c4c1 | ||
|
|
b18ceb50f1 | ||
|
|
ff4d67ede8 | ||
|
|
465babb635 | ||
|
|
22c3839168 | ||
|
|
4619b32dc0 | ||
|
|
ad921890c1 | ||
|
|
6a28e6d412 | ||
|
|
f4495da337 | ||
|
|
dbaed0bbf2 | ||
|
|
78c7fb6460 | ||
|
|
14ce500508 | ||
|
|
acba58ac59 | ||
|
|
da29809969 | ||
|
|
87e4895189 | ||
|
|
9c21da3363 | ||
|
|
febf6115a0 | ||
|
|
11b5bac7bf | ||
|
|
b61bf2f0e8 | ||
|
|
19f45df02b | ||
|
|
2ab4058de0 | ||
|
|
f2277c3fec | ||
|
|
fb49a10e2c | ||
|
|
f049a57eec |
+1
-1
@@ -1 +1 @@
|
||||
3.6
|
||||
3.6.4
|
||||
|
||||
+68
-46
@@ -29,12 +29,13 @@ jobs:
|
||||
clone: true
|
||||
dist: bionic
|
||||
script:
|
||||
- sudo apt-get install -qq autoconf automake autopoint flex gettext graphviz help2man m4 texinfo
|
||||
- sudo apt-get install -qq autoconf automake autopoint flex gettext gperf graphviz help2man m4 texinfo
|
||||
- autoconf --version
|
||||
- automake --version
|
||||
- autopoint --version
|
||||
- dot -V
|
||||
- gettext --version
|
||||
- gperf --version
|
||||
- help2man --version
|
||||
- makeinfo --version
|
||||
- m4 --version
|
||||
@@ -69,53 +70,53 @@ jobs:
|
||||
|
||||
# Start with three completely different environments, to get errors asap.
|
||||
|
||||
- name: "GCC 9 -O3"
|
||||
- name: "GCC 10 -O3"
|
||||
stage: check
|
||||
os: linux
|
||||
dist: bionic
|
||||
addons: &gcc9
|
||||
addons: &gcc10
|
||||
apt:
|
||||
sources:
|
||||
# See https://github.com/travis-ci/apt-source-safelist/issues/410.
|
||||
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||
packages: g++-9
|
||||
packages: g++-10
|
||||
env:
|
||||
- CC=gcc-9
|
||||
- CXX=g++-9
|
||||
- CC=gcc-10
|
||||
- CXX=g++-10
|
||||
- CONFIGUREFLAGS='CPPFLAGS=-DNDEBUG CFLAGS=-O3 CXXFLAGS=-O3'
|
||||
|
||||
# ASAN is time consuming, and we timeout the 50min granted by
|
||||
# Travis if we run all the tests in one go. Run in two parts.
|
||||
- name: "Clang 9 libc++ and ASAN part 1"
|
||||
- name: "Clang 10 libc++ and ASAN part 1"
|
||||
stage: check
|
||||
os: linux
|
||||
dist: bionic
|
||||
addons: &clang9
|
||||
addons: &clang10
|
||||
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'
|
||||
- sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main'
|
||||
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
|
||||
packages:
|
||||
- clang-9
|
||||
- libc++-9-dev
|
||||
- libc++abi-9-dev
|
||||
- clang-10
|
||||
- libc++-10-dev
|
||||
- libc++abi-10-dev
|
||||
env:
|
||||
# Do not use ASAN with ubuntu's libc++: https://bugs.llvm.org/show_bug.cgi?id=17379
|
||||
- CC='clang-9 -fsanitize=address'
|
||||
- CXX='clang++-9 -fsanitize=address -stdlib=libc++'
|
||||
- CC='clang-10 -fsanitize=address'
|
||||
- CXX='clang++-10 -fsanitize=address -stdlib=libc++'
|
||||
- PART=1
|
||||
|
||||
- name: "Clang 9 libc++ and ASAN part 2"
|
||||
- name: "Clang 10 libc++ and ASAN part 2"
|
||||
stage: check
|
||||
os: linux
|
||||
dist: bionic
|
||||
addons: *clang9
|
||||
addons: *clang10
|
||||
env:
|
||||
# Do not use ASAN with ubuntu's libc++: https://bugs.llvm.org/show_bug.cgi?id=17379
|
||||
- CC='clang-9 -fsanitize=address'
|
||||
- CXX='clang++-9 -fsanitize=address -stdlib=libc++'
|
||||
- CC='clang-10 -fsanitize=address'
|
||||
- CXX='clang++-10 -fsanitize=address -stdlib=libc++'
|
||||
- PART=2
|
||||
|
||||
- name: "ICC"
|
||||
@@ -135,62 +136,64 @@ jobs:
|
||||
packages:
|
||||
- intel-oneapi-icc
|
||||
|
||||
## ------- ##
|
||||
## First. ##
|
||||
## ------- ##
|
||||
|
||||
# Start with three completely different environments, to get
|
||||
# errors asap.
|
||||
|
||||
- name: "ARM64: GCC 9 -O3 part 1"
|
||||
- name: "ARM64: GCC 10 -O2 part 1"
|
||||
stage: check
|
||||
os: linux
|
||||
arch: arm64
|
||||
dist: bionic
|
||||
addons: *gcc9
|
||||
addons: *gcc10
|
||||
env:
|
||||
- CC=gcc-9
|
||||
- CXX=g++-9
|
||||
- CONFIGUREFLAGS='CPPFLAGS=-DNDEBUG CFLAGS=-O3 CXXFLAGS=-O3'
|
||||
- CC=gcc-10
|
||||
- CXX=g++-10
|
||||
- CONFIGUREFLAGS='CPPFLAGS=-DNDEBUG CFLAGS=-O2 CXXFLAGS=-O2'
|
||||
- PART=1
|
||||
|
||||
- name: "PPC64le: GCC 9 part 1"
|
||||
- name: "PPC64le: GCC 10 -O2 part 1"
|
||||
stage: check
|
||||
os: linux
|
||||
arch: ppc64le
|
||||
dist: bionic
|
||||
addons: *gcc9
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
# See https://github.com/travis-ci/apt-source-safelist/issues/410.
|
||||
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||
packages: g++-10
|
||||
env:
|
||||
- CC=gcc-9
|
||||
- CXX=g++-9
|
||||
- CONFIGUREFLAGS='CFLAGS=-O3 CXXFLAGS=-O3'
|
||||
- CC=gcc-10
|
||||
- CXX=g++-10
|
||||
- CONFIGUREFLAGS='CFLAGS=-O2 CXXFLAGS=-O2'
|
||||
- PART=1
|
||||
|
||||
- name: "s390x: GCC 9 part 1"
|
||||
- name: "s390x: GCC 10 -O2 part 1"
|
||||
stage: check
|
||||
os: linux
|
||||
arch: s390x
|
||||
dist: bionic
|
||||
addons: *gcc9
|
||||
addons: *gcc10
|
||||
env:
|
||||
- CC=gcc-9
|
||||
- CXX=g++-9
|
||||
- CONFIGUREFLAGS='CFLAGS=-O3 CXXFLAGS=-O3'
|
||||
- CC=gcc-10
|
||||
- CXX=g++-10
|
||||
- CONFIGUREFLAGS='CFLAGS=-O2 CXXFLAGS=-O2'
|
||||
- PART=1
|
||||
|
||||
## ----- ##
|
||||
## GCC. ##
|
||||
## ----- ##
|
||||
|
||||
- name: "GCC 8 with sanitizers part 1"
|
||||
- name: "GCC 9 with sanitizers part 1"
|
||||
stage: check
|
||||
os: linux
|
||||
dist: bionic
|
||||
addons:
|
||||
apt:
|
||||
packages: g++-8
|
||||
sources:
|
||||
# See https://github.com/travis-ci/apt-source-safelist/issues/410.
|
||||
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||
packages: g++-9
|
||||
env:
|
||||
- CC='gcc-8 -fsanitize=undefined,address -fno-omit-frame-pointer'
|
||||
- CXX='g++-8 -fsanitize=undefined,address -fno-omit-frame-pointer'
|
||||
- CC='gcc-9 -fsanitize=undefined,address -fno-omit-frame-pointer'
|
||||
- CXX='g++-9 -fsanitize=undefined,address -fno-omit-frame-pointer'
|
||||
- CONFIGUREFLAGS='CFLAGS=-O1 CXXFLAGS=-O1'
|
||||
- PART=1
|
||||
|
||||
@@ -292,7 +295,27 @@ jobs:
|
||||
## 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
|
||||
os: linux
|
||||
dist: bionic
|
||||
@@ -305,7 +328,6 @@ jobs:
|
||||
env:
|
||||
- CC=clang-8
|
||||
- CXX='clang++-8 -stdlib=libc++'
|
||||
- CONFIGUREFLAGS='CPPFLAGS=-DNDEBUG CFLAGS=-O3 CXXFLAGS=-O3'
|
||||
|
||||
- name: "Clang 7"
|
||||
stage: check
|
||||
|
||||
+12
@@ -127,3 +127,15 @@ gen-ChangeLog:
|
||||
--since=$(gen_start_date) > $$cl.tmp && \
|
||||
mv -f $$cl.tmp $$cl; \
|
||||
fi
|
||||
|
||||
# Useful to debug.
|
||||
.c.i:
|
||||
$(CC) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -o $@ -E $<
|
||||
|
||||
.PHONY: codespell
|
||||
codespell:
|
||||
$(AM_V_GEN) cd $(srcdir) \
|
||||
&& codespell \
|
||||
--regex "[\\w\\-'’\`]+\+*" \
|
||||
--ignore-words-list "ba,circularly,cloneable,copyable,define'd,dout,froms,iff,ifset,od,ois" \
|
||||
$$(git ls-files data doc lib src tests)
|
||||
|
||||
@@ -1,9 +1,177 @@
|
||||
GNU Bison NEWS
|
||||
|
||||
* Noteworthy changes in release 3.6.90 (2020-07-04) [beta]
|
||||
|
||||
** 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.
|
||||
|
||||
In conformance with the recommendations of the Graphviz team, in the next
|
||||
version Bison the option `--graph` will generate a *.gv file by default,
|
||||
instead of *.dot. A transition started in Bison 3.4.
|
||||
|
||||
** New features
|
||||
|
||||
*** Counterexample Generation
|
||||
|
||||
Contributed by Vincent Imbimbo.
|
||||
|
||||
When given `--report=counterexamples` or `-Wcounterexamples`, bison will
|
||||
now output counterexamples for conflicts in the grammar. These are
|
||||
strings in the grammar which can be parsed in two ways due to the
|
||||
conflict. For example:
|
||||
|
||||
Example exp '+' exp • '/' exp
|
||||
First derivation exp ::=[ exp ::=[ exp '+' exp • ] '/' exp ]
|
||||
Second derivation exp ::=[ exp '+' exp ::=[ exp • '/' exp ] ]
|
||||
|
||||
This is a shift/reduce conflict caused by none of the operators having
|
||||
precedence, so the example can be parsed in the two ways shown. When
|
||||
bison cannot find an example that can be derived in two ways, it instead
|
||||
generates two examples that are the same up until the dot:
|
||||
|
||||
First example expr • ID $end
|
||||
First derivation $accept ::=[ s ::=[ a ::=[ expr • ] ID ] $end ]
|
||||
Second example expr • ID ',' ID $end
|
||||
Second derivation $accept ::=[ s ::=[ a ::=[ expr ::=[ expr • ID ',' ] ] ID ] $end ]
|
||||
|
||||
In these cases, the parser usually doesn't have enough lookahead to
|
||||
differentiate the two given examples.
|
||||
|
||||
*** File prefix mapping
|
||||
|
||||
Contributed by Joshua Watt.
|
||||
|
||||
Bison learned a new argument, `--file-prefix-map OLD=NEW`. Any file path
|
||||
in the output (specifically `#line` directives and `#ifdef` header guards)
|
||||
that begins with the prefix OLD will have it replaced with the prefix NEW,
|
||||
similar to the `-ffile-prefix-map` in GCC. This option can be used to
|
||||
make bison output reproducible.
|
||||
|
||||
** Changes
|
||||
|
||||
*** Relocatable installation
|
||||
|
||||
When installed to be relocatable (via `configure --enable-relocatable`),
|
||||
bison will now also look for a relocated m4.
|
||||
|
||||
*** C++ file names
|
||||
|
||||
The `filename_type` %define variable was renamed `api.filename.type`.
|
||||
Instead of
|
||||
|
||||
%define filename_type "symbol"
|
||||
|
||||
write
|
||||
|
||||
%define api.filename.type {symbol}
|
||||
|
||||
(Or let `bison --update` do it for you).
|
||||
|
||||
It now defaults to `const std::string` instead of `std::string`.
|
||||
|
||||
*** Deprecated %define variable names
|
||||
|
||||
The following variables have been renamed for consistency. Backward
|
||||
compatibility is ensured, but upgrading is recommended.
|
||||
|
||||
filename_type -> api.filename.type
|
||||
package -> api.package
|
||||
|
||||
*** Push parsers no longer clear their state when parsing is finished
|
||||
|
||||
Previously push-parsers cleared their state when parsing was finished (on
|
||||
success and on failure). This made it impossible to check if there were
|
||||
parse errors, since `yynerrs` was also reset. This can be especially
|
||||
troublesome when used in autocompletion, since a parser with error
|
||||
recovery would suggest (irrelevant) expected tokens even if there were
|
||||
failure.
|
||||
|
||||
Now the parser state can be examined when parsing is finished. The parser
|
||||
state is reset when starting a new parse.
|
||||
|
||||
** Bug fixes
|
||||
|
||||
*** Include the generated header (yacc.c)
|
||||
|
||||
Historically, when --defines was used, bison generated a header and pasted
|
||||
an exact copy of it into the generated parser implementation file. Since
|
||||
Bison 3.4 it is possible to specify that the header should be `#include`d,
|
||||
and how. For instance
|
||||
|
||||
%define api.header.include {"parse.h"}
|
||||
|
||||
or
|
||||
|
||||
%define api.header.include {<parser/parse.h>}
|
||||
|
||||
Now api.header.include defaults to `"header-basename"`, as was intended in
|
||||
Bison 3.4, where `header-basename` is the basename of the generated
|
||||
header. This is disabled when the generated header is `y.tab.h`, to
|
||||
comply with Automake's ylwrap.
|
||||
|
||||
*** String aliases are faithfully propagated
|
||||
|
||||
Bison used to interpret user strings (i.e., decoding backslash escapes)
|
||||
when reading them, and to escape them (i.e., issue non-printable
|
||||
characters as backslash escapes, taking the locale into account) when
|
||||
outputting them. As a consequence non-ASCII strings (say in UTF-8) ended
|
||||
up "ciphered" as sequences of backslash escapes. This happened not only
|
||||
in the generated sources (where the compiler will reinterpret them), but
|
||||
also in all the generated reports (text, xml, html, dot, etc.). Reports
|
||||
were therefore not readable when string aliases were not pure ASCII.
|
||||
Worse yet: the output depended on the user's locale.
|
||||
|
||||
Now Bison faithfully treats the string aliases exactly the way the user
|
||||
spelled them. This fixes all the aforementioned problems. However, now,
|
||||
string aliases semantically equivalent but syntactically different (e.g.,
|
||||
"A", "\x41", "\101") are considered to be different.
|
||||
|
||||
*** Crash when generating IELR
|
||||
|
||||
An old, well hidden, bug in the generation of IELR parsers was fixed.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.6.4 (2020-06-15) [stable]
|
||||
|
||||
** Bug fixes
|
||||
|
||||
In glr.cc some internal macros leaked in the user's code, and could damage
|
||||
access to the token kinds.
|
||||
|
||||
|
||||
* 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.
|
||||
@@ -12,6 +180,7 @@ GNU Bison NEWS
|
||||
|
||||
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
|
||||
@@ -234,6 +403,7 @@ GNU Bison NEWS
|
||||
autocompletion on the existing variables, rather than of the word
|
||||
"variable".
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.5.4 (2020-04-05) [stable]
|
||||
|
||||
** WARNING: Future backward-incompatibilities!
|
||||
@@ -254,6 +424,7 @@ GNU Bison NEWS
|
||||
|
||||
Fix api.token.raw support in Java.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.5.3 (2020-03-08) [stable]
|
||||
|
||||
** Bug fixes
|
||||
@@ -264,6 +435,7 @@ GNU Bison NEWS
|
||||
|
||||
Several unlikely crashes found by fuzzing have been fixed.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.5.2 (2020-02-13) [stable]
|
||||
|
||||
** Bug fixes
|
||||
@@ -273,6 +445,7 @@ GNU Bison NEWS
|
||||
The lalr1.cc skeleton properly rejects unsupported values for parse.lac
|
||||
(as yacc.c does).
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.5.1 (2020-01-19) [stable]
|
||||
|
||||
** Bug fixes
|
||||
@@ -281,6 +454,7 @@ GNU Bison NEWS
|
||||
|
||||
Fix compiler warnings.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.5 (2019-12-11) [stable]
|
||||
|
||||
** Backward incompatible changes
|
||||
@@ -488,6 +662,7 @@ GNU Bison NEWS
|
||||
|
||||
In Java, %define api.prefix was ignored. It now behaves as expected.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.4.2 (2019-09-12) [stable]
|
||||
|
||||
** Bug fixes
|
||||
@@ -505,12 +680,14 @@ GNU Bison NEWS
|
||||
When lone carriage-return characters appeared in the input file,
|
||||
diagnostics could hang forever.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.4.1 (2019-05-22) [stable]
|
||||
|
||||
** Bug fixes
|
||||
|
||||
Portability fixes.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.4 (2019-05-19) [stable]
|
||||
|
||||
** Deprecated features
|
||||
@@ -651,6 +828,7 @@ GNU Bison NEWS
|
||||
system, in December 1987. See the NEWS of Bison 3.3 for the previous
|
||||
oldest bug.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.3.2 (2019-02-03) [stable]
|
||||
|
||||
** Bug fixes
|
||||
@@ -658,6 +836,7 @@ GNU Bison NEWS
|
||||
Bison 3.3 failed to generate parsers for grammars with unused nonterminal
|
||||
symbols.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.3.1 (2019-01-27) [stable]
|
||||
|
||||
** Changes
|
||||
@@ -665,6 +844,7 @@ GNU Bison NEWS
|
||||
The option -y/--yacc used to imply -Werror=yacc, which turns uses of Bison
|
||||
extensions into errors. It now makes them simple warnings (-Wyacc).
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.3 (2019-01-26) [stable]
|
||||
|
||||
A new mailing list was created, Bison Announce. It is low traffic, and is
|
||||
@@ -807,11 +987,11 @@ GNU Bison NEWS
|
||||
|
||||
...
|
||||
|
||||
Looking at the output from -v, one can see that the shift-reduce conflict
|
||||
Looking at the output from -v, one can see that the shift/reduce conflict
|
||||
here is due to the fact that the parser does not know whether to reduce
|
||||
arguments to argument_list until it sees the token _after_ the following
|
||||
','. By marking the rule with %expect 1 (because there is a conflict in
|
||||
one state), we document the source of the 1 overall shift-reduce conflict.
|
||||
one state), we document the source of the 1 overall shift/reduce conflict.
|
||||
|
||||
In GLR parsers, we can use %expect-rr in a rule for reduce/reduce
|
||||
conflicts. In this case, we mark each of the conflicting rules. For
|
||||
@@ -926,7 +1106,7 @@ GNU Bison NEWS
|
||||
|
||||
** Bug fixes
|
||||
|
||||
*** Incorrect number of reduce-reduce conflicts
|
||||
*** Incorrect number of reduce/reduce conflicts
|
||||
|
||||
On a grammar such as
|
||||
|
||||
@@ -980,6 +1160,7 @@ GNU Bison NEWS
|
||||
literal such as ‘"number"’. The post-fix quantifiers are ‘?’ (zero or
|
||||
one), ‘*’ (zero or more) and ‘+’ (one or more).
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.2.4 (2018-12-24) [stable]
|
||||
|
||||
** Bug fixes
|
||||
@@ -988,6 +1169,7 @@ GNU Bison NEWS
|
||||
|
||||
Always provide a copy constructor for symbol_type, even in modern C++.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.2.3 (2018-12-18) [stable]
|
||||
|
||||
** Bug fixes
|
||||
@@ -995,12 +1177,14 @@ GNU Bison NEWS
|
||||
Properly support token constructors in C++ with types that include commas
|
||||
(e.g., std::pair<int, int>). A regression introduced in Bison 3.2.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.2.2 (2018-11-21) [stable]
|
||||
|
||||
** Bug fixes
|
||||
|
||||
C++ portability issues.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.2.1 (2018-11-09) [stable]
|
||||
|
||||
** Bug fixes
|
||||
@@ -1008,6 +1192,7 @@ GNU Bison NEWS
|
||||
Several portability issues have been fixed in the build system, in the
|
||||
test suite, and in the generated parsers in C++.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.2 (2018-10-29) [stable]
|
||||
|
||||
** Backward incompatible changes
|
||||
@@ -1174,6 +1359,7 @@ GNU Bison NEWS
|
||||
|
||||
Portability/warning issues with Flex.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.1 (2018-08-27) [stable]
|
||||
|
||||
** Backward incompatible changes
|
||||
@@ -1314,6 +1500,7 @@ GNU Bison NEWS
|
||||
Useless code was removed from C++ parsers, and some of the generated
|
||||
constructors are more 'natural'.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.0.5 (2018-05-27) [stable]
|
||||
|
||||
** Bug fixes
|
||||
@@ -1344,6 +1531,7 @@ GNU Bison NEWS
|
||||
|
||||
On some platforms, some Java and/or C++ tests were failing.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.0.4 (2015-01-23) [stable]
|
||||
|
||||
** Bug fixes
|
||||
@@ -1356,6 +1544,7 @@ GNU Bison NEWS
|
||||
|
||||
Several portability issues in tests were fixed.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.0.3 (2015-01-15) [stable]
|
||||
|
||||
** Bug fixes
|
||||
@@ -1412,6 +1601,7 @@ GNU Bison NEWS
|
||||
- calc++
|
||||
a calculator in C++ using variant support and token constructors.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.0.2 (2013-12-05) [stable]
|
||||
|
||||
** Bug fixes
|
||||
@@ -1436,6 +1626,7 @@ GNU Bison NEWS
|
||||
When C++ variant support is enabled, an error triggered via YYERROR, but
|
||||
not caught via error recovery, resulted in a double deletion.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.0.1 (2013-11-12) [stable]
|
||||
|
||||
** Bug fixes
|
||||
@@ -1467,6 +1658,7 @@ GNU Bison NEWS
|
||||
|
||||
Bugs and portability issues.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.0 (2013-07-25) [stable]
|
||||
|
||||
** WARNING: Future backward-incompatibilities!
|
||||
@@ -1837,7 +2029,7 @@ GNU Bison NEWS
|
||||
%error-verbose directive is deprecated in favor of "%define parse.error
|
||||
verbose".
|
||||
|
||||
** Renamed %define variables
|
||||
** Deprecated %define variable names
|
||||
|
||||
The following variables have been renamed for consistency. Backward
|
||||
compatibility is ensured, but upgrading is recommended.
|
||||
@@ -2063,6 +2255,7 @@ GNU Bison NEWS
|
||||
There are operator- and operator-= for 'location'. Negative line/column
|
||||
increments can no longer underflow the resulting value.
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.7.1 (2013-04-15) [stable]
|
||||
|
||||
** Bug fixes
|
||||
@@ -2073,6 +2266,7 @@ GNU Bison NEWS
|
||||
|
||||
*** Fix some compiler warnings (lalr1.cc)
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.7 (2012-12-12) [stable]
|
||||
|
||||
** Bug fixes
|
||||
@@ -2197,6 +2391,7 @@ GNU Bison NEWS
|
||||
|
||||
The translation of midrule actions is now described.
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.6.5 (2012-11-07) [stable]
|
||||
|
||||
We consider compiler warnings about Bison generated parsers to be bugs.
|
||||
@@ -2216,10 +2411,12 @@ GNU Bison NEWS
|
||||
When possible, yylloc is correctly initialized before calling yylex. It
|
||||
is no longer necessary to initialize it in the %initial-action.
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.6.4 (2012-10-23) [stable]
|
||||
|
||||
Bison 2.6.3's --version was incorrect. This release fixes this issue.
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.6.3 (2012-10-22) [stable]
|
||||
|
||||
** Bug fixes
|
||||
@@ -2264,6 +2461,7 @@ GNU Bison NEWS
|
||||
"function declared 'noreturn' should not return") have also been
|
||||
addressed.
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.6.2 (2012-08-03) [stable]
|
||||
|
||||
** Bug fixes
|
||||
@@ -2280,6 +2478,7 @@ GNU Bison NEWS
|
||||
|
||||
The generated files no longer end (nor start) with empty lines.
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.6.1 (2012-07-30) [stable]
|
||||
|
||||
Bison no longer executes user-specified M4 code when processing a grammar.
|
||||
@@ -2318,6 +2517,7 @@ GNU Bison NEWS
|
||||
will display two values for each typed and untyped symbol (provided
|
||||
that YYSTYPE has both "ival" and "fval" fields).
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.6 (2012-07-19) [stable]
|
||||
|
||||
** Future changes
|
||||
@@ -2451,6 +2651,7 @@ GNU Bison NEWS
|
||||
|
||||
#endif /* !BAR_FOO_H */ #endif /* !BAR_FOO_H */
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.5.1 (2012-06-05) [stable]
|
||||
|
||||
** Future changes:
|
||||
@@ -2548,6 +2749,7 @@ GNU Bison NEWS
|
||||
Running "make install-pdf" (or -dvi, -html, -info, and -ps) no longer
|
||||
halts in the middle of its course.
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.5 (2011-05-14)
|
||||
|
||||
** Grammar symbol names can now contain non-initial dashes:
|
||||
@@ -2903,6 +3105,7 @@ GNU Bison NEWS
|
||||
|
||||
This bug has been fixed.
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.4.3 (2010-08-05)
|
||||
|
||||
** Bison now obeys -Werror and --warnings=error for warnings about
|
||||
@@ -2923,6 +3126,7 @@ GNU Bison NEWS
|
||||
|
||||
** Minor documentation fixes.
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.4.2 (2010-03-20)
|
||||
|
||||
** Some portability problems that resulted in failures and livelocks
|
||||
@@ -3017,6 +3221,7 @@ GNU Bison NEWS
|
||||
message translations were not installed although supported by the
|
||||
host system.
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.4.1 (2008-12-11)
|
||||
|
||||
** In the GLR defines file, unexpanded M4 macros in the yylval and yylloc
|
||||
@@ -3042,6 +3247,7 @@ GNU Bison NEWS
|
||||
|
||||
** A few minor improvements to the Bison manual.
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.4 (2008-11-02)
|
||||
|
||||
** %language is an experimental feature.
|
||||
@@ -3057,6 +3263,7 @@ GNU Bison NEWS
|
||||
** Several bugs in the C++ skeleton and the experimental Java skeleton have been
|
||||
fixed.
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.3b (2008-05-27)
|
||||
|
||||
** The quotes around NAME that used to be required in the following directive
|
||||
@@ -3243,6 +3450,7 @@ GNU Bison NEWS
|
||||
** The nonfunctional --no-parser, -n, and %no-parser options have been
|
||||
completely removed from Bison.
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.3a (2006-09-13)
|
||||
|
||||
** Instead of %union, you can define and use your own union type
|
||||
@@ -3357,6 +3565,7 @@ GNU Bison NEWS
|
||||
The old spelling still works, but is not documented and may be removed
|
||||
in a future release.
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.3 (2006-06-05)
|
||||
|
||||
** GLR grammars should now use "YYRECOVERING ()" instead of "YYRECOVERING",
|
||||
@@ -3365,6 +3574,7 @@ GNU Bison NEWS
|
||||
** It is now documented that any definition of YYSTYPE or YYLTYPE should
|
||||
be to a type name that does not contain parentheses or brackets.
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.2 (2006-05-19)
|
||||
|
||||
** The distribution terms for all Bison-generated parsers now permit
|
||||
@@ -3447,6 +3657,7 @@ GNU Bison NEWS
|
||||
|
||||
** DJGPP support added.
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.1 (2005-09-16)
|
||||
|
||||
** The C++ lalr1.cc skeleton supports %lex-param.
|
||||
@@ -3473,6 +3684,7 @@ GNU Bison NEWS
|
||||
print 'syntax error, unexpected number' instead of 'syntax error,
|
||||
unexpected "number"'.
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.0 (2004-12-25)
|
||||
|
||||
** Possibly-incompatible changes
|
||||
@@ -3536,6 +3748,7 @@ GNU Bison NEWS
|
||||
|
||||
- Semicolons are now allowed before "|" in grammar rules, as POSIX requires.
|
||||
|
||||
|
||||
* Noteworthy changes in release 1.875 (2003-01-01)
|
||||
|
||||
** The documentation license has been upgraded to version 1.2
|
||||
@@ -3656,6 +3869,7 @@ GNU Bison NEWS
|
||||
ago, but nobody noticed until we recently asked someone to try
|
||||
building Bison with a K&R C compiler.
|
||||
|
||||
|
||||
* Noteworthy changes in release 1.75 (2002-10-14)
|
||||
|
||||
** Bison should now work on 64-bit hosts.
|
||||
@@ -3687,6 +3901,7 @@ GNU Bison NEWS
|
||||
was incorrectly rejected: $1 is defined in the second midrule
|
||||
action, and is equal to the $$ of the first midrule action.
|
||||
|
||||
|
||||
* Noteworthy changes in release 1.50 (2002-10-04)
|
||||
|
||||
** GLR parsing
|
||||
@@ -3831,6 +4046,7 @@ GNU Bison NEWS
|
||||
|
||||
** GNU M4 is now required when using Bison.
|
||||
|
||||
|
||||
* Noteworthy changes in release 1.35 (2002-03-25)
|
||||
|
||||
** C Skeleton
|
||||
@@ -3846,6 +4062,7 @@ GNU Bison NEWS
|
||||
This kludge also addresses some C++ problems when the stack was
|
||||
extended.
|
||||
|
||||
|
||||
* Noteworthy changes in release 1.34 (2002-03-12)
|
||||
|
||||
** File name clashes are detected
|
||||
@@ -3866,6 +4083,7 @@ GNU Bison NEWS
|
||||
|
||||
** Fix test suite portability problems.
|
||||
|
||||
|
||||
* Noteworthy changes in release 1.33 (2002-02-07)
|
||||
|
||||
** Fix C++ issues
|
||||
@@ -3875,6 +4093,7 @@ GNU Bison NEWS
|
||||
** Catch invalid @n
|
||||
As is done with $n.
|
||||
|
||||
|
||||
* Noteworthy changes in release 1.32 (2002-01-23)
|
||||
|
||||
** Fix Yacc output file names
|
||||
@@ -3883,6 +4102,7 @@ GNU Bison NEWS
|
||||
|
||||
** Italian, Dutch translations
|
||||
|
||||
|
||||
* Noteworthy changes in release 1.31 (2002-01-14)
|
||||
|
||||
** Many Bug Fixes
|
||||
@@ -3970,6 +4190,7 @@ GNU Bison NEWS
|
||||
** --output
|
||||
New, aliasing "--output-file".
|
||||
|
||||
|
||||
* Noteworthy changes in release 1.30 (2001-10-26)
|
||||
|
||||
** "--defines" and "--graph" have now an optional argument which is the
|
||||
@@ -3981,6 +4202,7 @@ GNU Bison NEWS
|
||||
|
||||
** Portability fixes.
|
||||
|
||||
|
||||
* Noteworthy changes in release 1.29 (2001-09-07)
|
||||
|
||||
** The output file does not define const, as this caused problems when used
|
||||
@@ -4016,6 +4238,7 @@ GNU Bison NEWS
|
||||
** @$
|
||||
Automatic location tracking.
|
||||
|
||||
|
||||
* Noteworthy changes in release 1.28 (1999-07-06)
|
||||
|
||||
** Should compile better now with K&R compilers.
|
||||
@@ -4026,11 +4249,13 @@ GNU Bison NEWS
|
||||
|
||||
** There is now a FAQ.
|
||||
|
||||
|
||||
* Noteworthy changes in release 1.27
|
||||
|
||||
** The make rule which prevented bison.simple from being created on
|
||||
some systems has been fixed.
|
||||
|
||||
|
||||
* Noteworthy changes in release 1.26
|
||||
|
||||
** Bison now uses Automake.
|
||||
@@ -4048,6 +4273,7 @@ GNU Bison NEWS
|
||||
** Generated parsers should now work even on operating systems which do
|
||||
not provide alloca().
|
||||
|
||||
|
||||
* Noteworthy changes in release 1.25 (1995-10-16)
|
||||
|
||||
** Errors in the input grammar are not fatal; Bison keeps reading
|
||||
@@ -4073,6 +4299,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
|
||||
a switch statement body.
|
||||
|
||||
|
||||
* Noteworthy changes in release 1.23
|
||||
|
||||
The user can define YYPARSE_PARAM as the name of an argument to be
|
||||
@@ -4082,72 +4309,69 @@ by casting it to the proper pointer type.
|
||||
|
||||
Line numbers in output file corrected.
|
||||
|
||||
|
||||
* Noteworthy changes in release 1.22
|
||||
|
||||
--help option added.
|
||||
|
||||
|
||||
* Noteworthy changes in release 1.20
|
||||
|
||||
Output file does not redefine const for C++.
|
||||
|
||||
-----
|
||||
|
||||
Copyright (C) 1995-2015, 2018-2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Parser Generator.
|
||||
|
||||
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/>.
|
||||
|
||||
LocalWords: yacc YYBACKUP glr GCC lalr ArrayIndexOutOfBoundsException nullptr
|
||||
LocalWords: cplusplus liby rpl fprintf mfcalc Wyacc stmt cond expr mk sym lr
|
||||
LocalWords: IELR ielr Lookahead YYERROR nonassoc LALR's api lookaheads yychar
|
||||
LocalWords: destructor lookahead YYRHSLOC YYLLOC Rhs ifndef YYFAIL cpp sr rr
|
||||
LocalWords: preprocessor initializer Wno Wnone Werror FreeBSD prec livelocks
|
||||
LocalWords: Solaris AIX UX RHEL Tru LHS gcc's Wundef YYENABLE NLS YYLTYPE VCG
|
||||
LocalWords: yyerror cpp's Wunused yylval yylloc prepend yyparse yylex yypush
|
||||
LocalWords: Graphviz xml nonterminals midrule destructor's YYSTYPE typedef ly
|
||||
LocalWords: CHR chr printf stdout namespace preprocessing enum pre include's
|
||||
LocalWords: YYRECOVERING nonfree destructors YYABORT YYACCEPT params enums de
|
||||
LocalWords: struct yystype DJGPP lex param Haible NUM alloca YYSTACK NUL goto
|
||||
LocalWords: YYMAXDEPTH Unescaped UCNs YYLTYPE's yyltype typedefs inline Yaccs
|
||||
LocalWords: Heriyanto Reenable dprec Hilfinger Eggert MYEOF Folle Menezes EOF
|
||||
LocalWords: Lackovic define's itemset Groff Gettext malloc NEWS'ed YYDEBUG YY
|
||||
LocalWords: namespaces strerror const autoconfiguration Dconst Autoconf's FDL
|
||||
LocalWords: Automake TMPDIR LESSEQ ylwrap endif yydebug YYTOKEN YYLSP ival hh
|
||||
LocalWords: extern YYTOKENTYPE TOKENTYPE yytokentype tokentype STYPE lval pdf
|
||||
LocalWords: lang yyoutput dvi html ps POSIX lvalp llocp Wother nterm arg init
|
||||
LocalWords: TOK calc yyo fval Wconflicts parsers yystackp yyval yynerrs
|
||||
LocalWords: Théophile Ranquet Santet fno fnone stype associativity Tolmer
|
||||
LocalWords: Wprecedence Rassoul Wempty Paolo Bonzini parser's Michiel loc
|
||||
LocalWords: redeclaration sval fcaret reentrant XSLT xsl Wmaybe yyvsp Tedi
|
||||
LocalWords: pragmas noreturn untyped Rozenman unexpanded Wojciech Polak
|
||||
LocalWords: Alexandre MERCHANTABILITY yytype emplace ptr automove lvalues
|
||||
LocalWords: nonterminal yy args Pragma dereference yyformat rhs docdir bw
|
||||
LocalWords: Redeclarations rpcalc Autoconf YFLAGS Makefiles PROG DECL num
|
||||
LocalWords: Heimbigner AST src ast Makefile srcdir MinGW xxlex XXSTYPE
|
||||
LocalWords: XXLTYPE strictfp IDEs ffixit fdiagnostics parseable fixits
|
||||
LocalWords: Wdeprecated yytext Variadic variadic yyrhs yyphrs RCS README
|
||||
LocalWords: noexcept constexpr ispell american deprecations backend Teoh
|
||||
LocalWords: YYPRINT Mangold Bonzini's Wdangling exVal baz checkable gcc
|
||||
LocalWords: fsanitize Vogelsgesang lis redeclared stdint automata yytname
|
||||
LocalWords: yysymbol yytnamerr yyreport ctx ARGMAX yysyntax stderr LPAREN
|
||||
LocalWords: symrec yypcontext TOKENMAX yyexpected YYEMPTY yypstate YYEOF
|
||||
LocalWords: autocompletion bistromathic submessages Cayuela lexcalc hoc
|
||||
LocalWords: yytoken YYUNDEF YYerror
|
||||
LocalWords: yacc YYBACKUP glr GCC lalr ArrayIndexOutOfBoundsException nullptr
|
||||
LocalWords: cplusplus liby rpl fprintf mfcalc Wyacc stmt cond expr mk sym lr
|
||||
LocalWords: IELR ielr Lookahead YYERROR nonassoc LALR's api lookaheads yychar
|
||||
LocalWords: destructor lookahead YYRHSLOC YYLLOC Rhs ifndef YYFAIL cpp sr rr
|
||||
LocalWords: preprocessor initializer Wno Wnone Werror FreeBSD prec livelocks
|
||||
LocalWords: Solaris AIX UX RHEL Tru LHS gcc's Wundef YYENABLE NLS YYLTYPE VCG
|
||||
LocalWords: yyerror cpp's Wunused yylval yylloc prepend yyparse yylex yypush
|
||||
LocalWords: Graphviz xml nonterminals midrule destructor's YYSTYPE typedef ly
|
||||
LocalWords: CHR chr printf stdout namespace preprocessing enum pre include's
|
||||
LocalWords: YYRECOVERING nonfree destructors YYABORT YYACCEPT params enums de
|
||||
LocalWords: struct yystype DJGPP lex param Haible NUM alloca YYSTACK NUL goto
|
||||
LocalWords: YYMAXDEPTH Unescaped UCNs YYLTYPE's yyltype typedefs inline Yaccs
|
||||
LocalWords: Heriyanto Reenable dprec Hilfinger Eggert MYEOF Folle Menezes EOF
|
||||
LocalWords: Lackovic define's itemset Groff Gettext malloc NEWS'ed YYDEBUG YY
|
||||
LocalWords: namespaces strerror const autoconfiguration Dconst Autoconf's FDL
|
||||
LocalWords: Automake TMPDIR LESSEQ ylwrap endif yydebug YYTOKEN YYLSP ival hh
|
||||
LocalWords: extern YYTOKENTYPE TOKENTYPE yytokentype tokentype STYPE lval pdf
|
||||
LocalWords: lang yyoutput dvi html ps POSIX lvalp llocp Wother nterm arg init
|
||||
LocalWords: TOK calc yyo fval Wconflicts parsers yystackp yyval yynerrs
|
||||
LocalWords: Théophile Ranquet Santet fno fnone stype associativity Tolmer
|
||||
LocalWords: Wprecedence Rassoul Wempty Paolo Bonzini parser's Michiel loc
|
||||
LocalWords: redeclaration sval fcaret reentrant XSLT xsl Wmaybe yyvsp Tedi
|
||||
LocalWords: pragmas noreturn untyped Rozenman unexpanded Wojciech Polak
|
||||
LocalWords: Alexandre MERCHANTABILITY yytype emplace ptr automove lvalues
|
||||
LocalWords: nonterminal yy args Pragma dereference yyformat rhs docdir bw
|
||||
LocalWords: Redeclarations rpcalc Autoconf YFLAGS Makefiles PROG DECL num
|
||||
LocalWords: Heimbigner AST src ast Makefile srcdir MinGW xxlex XXSTYPE
|
||||
LocalWords: XXLTYPE strictfp IDEs ffixit fdiagnostics parseable fixits
|
||||
LocalWords: Wdeprecated yytext Variadic variadic yyrhs yyphrs RCS README
|
||||
LocalWords: noexcept constexpr ispell american deprecations backend Teoh
|
||||
LocalWords: YYPRINT Mangold Bonzini's Wdangling exVal baz checkable gcc
|
||||
LocalWords: fsanitize Vogelsgesang lis redeclared stdint automata yytname
|
||||
LocalWords: yysymbol yytnamerr yyreport ctx ARGMAX yysyntax stderr LPAREN
|
||||
LocalWords: symrec yypcontext TOKENMAX yyexpected YYEMPTY yypstate YYEOF
|
||||
LocalWords: autocompletion bistromathic submessages Cayuela lexcalc hoc
|
||||
LocalWords: yytoken YYUNDEF YYerror basename Automake's UTF ifdef ffile
|
||||
LocalWords: gotos readline Imbimbo Wcounterexamples
|
||||
|
||||
Local Variables:
|
||||
ispell-dictionary: "american"
|
||||
mode: outline
|
||||
fill-column: 76
|
||||
End:
|
||||
|
||||
Copyright (C) 1995-2015, 2018-2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Parser Generator.
|
||||
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.3 or
|
||||
any later version published by the Free Software Foundation; with no
|
||||
Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
|
||||
Texts. A copy of the license is included in the "GNU Free
|
||||
Documentation License" file as part of this distribution.
|
||||
|
||||
@@ -17,17 +17,18 @@ GNU Bison's home page is https://gnu.org/software/bison/.
|
||||
|
||||
# Installation
|
||||
## Build from git
|
||||
Here are basic installation instructions for a repository checkout:
|
||||
The [README-hacking.md file](README-hacking.md) is about building, modifying
|
||||
and checking Bison. See its "Working from the Repository" section to build
|
||||
Bison from the git repo. Roughly, run:
|
||||
|
||||
$ git submodule update --init
|
||||
$ ./bootstrap
|
||||
|
||||
then proceed with the usual `configure && make` steps.
|
||||
|
||||
The file README-hacking.md is about building, modifying and checking Bison.
|
||||
|
||||
## Build from tarball
|
||||
See the file INSTALL for generic compilation and installation instructions.
|
||||
See the [INSTALL file](INSTALL] for generic compilation and installation
|
||||
instructions.
|
||||
|
||||
Bison requires GNU m4 1.4.6 or later. See
|
||||
https://ftp.gnu.org/gnu/m4/m4-1.4.6.tar.gz.
|
||||
@@ -100,6 +101,16 @@ that the range specifies every single year in that closed interval.
|
||||
|
||||
<!--
|
||||
|
||||
LocalWords: parsers ngettext Texinfo pdf html YYYY ZZZZ ispell american md
|
||||
LocalWords: MERCHANTABILITY GLR LALR IELR submodule init README src bw
|
||||
LocalWords: Relocatability symlinks symlink
|
||||
|
||||
Local Variables:
|
||||
mode: markdown
|
||||
fill-column: 76
|
||||
ispell-dictionary: "american"
|
||||
End:
|
||||
|
||||
Copyright (C) 1992, 1998-1999, 2003-2005, 2008-2015, 2018-2020 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
@@ -112,14 +123,4 @@ Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
|
||||
Texts. A copy of the license is included in the "GNU Free
|
||||
Documentation License" file as part of this distribution.
|
||||
|
||||
Local Variables:
|
||||
mode: markdown
|
||||
fill-column: 76
|
||||
ispell-dictionary: "american"
|
||||
End:
|
||||
|
||||
LocalWords: parsers ngettext Texinfo pdf html YYYY ZZZZ ispell american md
|
||||
LocalWords: MERCHANTABILITY GLR LALR IELR submodule init README src bw
|
||||
LocalWords: Relocatability symlinks symlink
|
||||
|
||||
-->
|
||||
|
||||
+230
-153
@@ -5,151 +5,6 @@ Everything related to the development of Bison is on Savannah:
|
||||
http://savannah.gnu.org/projects/bison/.
|
||||
|
||||
|
||||
Administrivia
|
||||
=============
|
||||
|
||||
## If you incorporate a change from somebody on the net:
|
||||
First, if it is a large change, you must make sure they have signed the
|
||||
appropriate paperwork. Second, be sure to add their name and email address
|
||||
to THANKS.
|
||||
|
||||
## If a change fixes a test, mention the test in the commit message.
|
||||
|
||||
## Bug reports
|
||||
If somebody reports a new bug, mention his name in the commit message and in
|
||||
the test case you write. Put him into THANKS.
|
||||
|
||||
The correct response to most actual bugs is to write a new test case which
|
||||
demonstrates the bug. Then fix the bug, re-run the test suite, and check
|
||||
everything in.
|
||||
|
||||
|
||||
|
||||
Hacking
|
||||
=======
|
||||
|
||||
## Visible Changes
|
||||
Which include serious bug fixes, must be mentioned in NEWS.
|
||||
|
||||
## Translations
|
||||
Only user visible strings are to be translated: error messages, bits of the
|
||||
.output file etc. This excludes impossible error messages (comparable to
|
||||
assert/abort), and all the --trace output which is meant for the maintainers
|
||||
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
|
||||
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.
|
||||
However, make files, ChangeLog, and some regular expressions require tabs.
|
||||
Also, test cases might need to contain tabs to check that Bison properly
|
||||
processes tabs in its input.
|
||||
|
||||
Prefer "res" as the name of the local variable that will be "return"ed by
|
||||
the function.
|
||||
|
||||
### Bison
|
||||
Follow the GNU Coding Standards.
|
||||
|
||||
Don't reinvent the wheel: we use gnulib, which features many components.
|
||||
Actually, Bison has legacy code that we should replace with gnulib modules
|
||||
(e.g., many ad hoc implementations of lists).
|
||||
|
||||
### Skeletons
|
||||
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++
|
||||
Follow the GNU Coding Standards.
|
||||
|
||||
The `glr.c` skeleton was implemented with `camlCase`. We are migrating it
|
||||
to `snake_case`. Because we are standardizing the code, it is currently
|
||||
inconsistent.
|
||||
|
||||
Use `YYFOO` and `yyfoo` for entities that are exposed to the user. They are
|
||||
part of our contract with the users wrt backward compatibility.
|
||||
|
||||
Use `YY_FOO` and `yy_foo` for private matters. Users should not use them,
|
||||
we are free to change them without fear of backward compatibility issues.
|
||||
|
||||
Use `*_t` for types, especially for `yy*_t` in which case we shouldn't worry
|
||||
about the C standard introducing such a name.
|
||||
|
||||
#### C++
|
||||
Follow the C++ Core Guidelines
|
||||
(http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines). The Google
|
||||
ones may be interesting too
|
||||
(https://google.github.io/styleguide/cppguide.html).
|
||||
|
||||
Our enumerators, such as the kinds (symbol and token kinds), should be lower
|
||||
case, but it was too late to follow that track for token kinds, and symbol
|
||||
kind enumerators are made to be consistent with them.
|
||||
|
||||
Use `*_type` for type aliases. Use `foo_get()` and `foo_set(v)` for
|
||||
accessors, or simply `foo()` and `foo(v)`.
|
||||
|
||||
Use the `yy` prefix for private stuff, but there's no need for it in the
|
||||
public API. The `yy` prefix is already taken care of via the namespace.
|
||||
|
||||
#### Java
|
||||
We follow https://www.oracle.com/technetwork/java/codeconventions-150003.pdf
|
||||
and https://google.github.io/styleguide/javaguide.html. Unfortunately at
|
||||
some point some GNU Coding Style was installed in Java, but it's an error.
|
||||
So we should for instance stop putting spaces in function calls. Because we
|
||||
are standardizing the code, it is currently inconsistent.
|
||||
|
||||
Use a 2-space indentation (Google) rather than 4 (Oracle).
|
||||
|
||||
Don't use the "yy" prefix for public members: "getExpectedTokens", not
|
||||
"yyexpectedTokens" or "yygetExpectedTokens".
|
||||
|
||||
## Commit Messages
|
||||
Imitate the style we use. Use `git log` to get sources of inspiration.
|
||||
|
||||
If the changes have a small impact on Bison's generated parser, embed these
|
||||
changes in the commit itself. If the impact is large, first push all the
|
||||
changes except those about src/parse-gram.[ch], and then another commit
|
||||
named "regen" which is only about them.
|
||||
|
||||
## Debugging
|
||||
Bison supports tracing of its various steps, via the `--trace` option.
|
||||
Since it is not meant for the end user, it is not displayed by `bison
|
||||
--help`, nor is it documented in the manual. Instead, run `bison
|
||||
--trace=help`.
|
||||
|
||||
|
||||
|
||||
Working from the Repository
|
||||
===========================
|
||||
|
||||
@@ -168,6 +23,7 @@ tools we depend upon, including:
|
||||
- Automake <http://www.gnu.org/software/automake/>
|
||||
- Flex <http://www.gnu.org/software/flex/>
|
||||
- Gettext <http://www.gnu.org/software/gettext/>
|
||||
- Gperf <http://www.gnu.org/software/gperf/>
|
||||
- Graphviz <http://www.graphviz.org>
|
||||
- Gzip <http://www.gnu.org/software/gzip/>
|
||||
- Help2man <http://www.gnu.org/software/help2man/>
|
||||
@@ -184,7 +40,7 @@ above packages depends on your system. The following shell command should
|
||||
work for Debian-based systems such as Ubuntu:
|
||||
|
||||
sudo apt-get install \
|
||||
autoconf automake autopoint flex graphviz help2man texinfo valgrind
|
||||
autoconf automake autopoint flex gperf graphviz help2man texinfo valgrind
|
||||
|
||||
Bison is written using Bison grammars, so there are bootstrapping issues.
|
||||
The bootstrap script attempts to discover when the C code generated from the
|
||||
@@ -322,6 +178,199 @@ version, compile bison, then force it to recreate the files:
|
||||
$ make -C _build
|
||||
|
||||
|
||||
Administrivia
|
||||
=============
|
||||
|
||||
## If you incorporate a change from somebody on the net:
|
||||
First, if it is a large change, you must make sure they have signed the
|
||||
appropriate paperwork. Second, be sure to add their name and email address
|
||||
to THANKS.
|
||||
|
||||
## If a change fixes a test, mention the test in the commit message.
|
||||
|
||||
## Bug reports
|
||||
If somebody reports a new bug, mention his name in the commit message and in
|
||||
the test case you write. Put him into THANKS.
|
||||
|
||||
The correct response to most actual bugs is to write a new test case which
|
||||
demonstrates the bug. Then fix the bug, re-run the test suite, and check
|
||||
everything in.
|
||||
|
||||
|
||||
|
||||
Hacking
|
||||
=======
|
||||
|
||||
## Visible Changes
|
||||
Which include serious bug fixes, must be mentioned in NEWS.
|
||||
|
||||
## Translations
|
||||
Only user visible strings are to be translated: error messages, bits of the
|
||||
.output file etc. This excludes impossible error messages (comparable to
|
||||
assert/abort), and all the --trace output which is meant for the maintainers
|
||||
only.
|
||||
|
||||
## Vocabulary
|
||||
- "nonterminal", not "variable" or "non-terminal" or "non terminal".
|
||||
Abbreviated as "nterm".
|
||||
- "shift/reduce" and "reduce/reduce", not "shift-reduce" or "shift reduce",
|
||||
etc.
|
||||
|
||||
## 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...
|
||||
|
||||
## Implementation Notes
|
||||
There are several places with interesting details about the implementation:
|
||||
- [Understanding C parsers generated by GNU
|
||||
Bison](https://www.cs.uic.edu/~spopuri/cparser.html) by Satya Kiran Popuri,
|
||||
is a wonderful piece of work that explains the implementation of Bison,
|
||||
- [src/gram.h](src/gram.h) documents the way the grammar is represented
|
||||
- [src/tables.h](src/tables.h) documents the generated tables
|
||||
- [data/README.md](data/README.md) contains details about the m4 implementation
|
||||
|
||||
## Coding Style
|
||||
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.
|
||||
However, make files, ChangeLog, and some regular expressions require tabs.
|
||||
Also, test cases might need to contain tabs to check that Bison properly
|
||||
processes tabs in its input.
|
||||
|
||||
Prefer `res` as the name of the local variable that will be "return"ed by
|
||||
the function.
|
||||
|
||||
In writing arithmetic comparisons, use "<" and "<=" rather than ">" and ">="
|
||||
(http://www.gelato.unsw.edu.au/archives/git/0505/4507.html).
|
||||
|
||||
### Bison
|
||||
Follow the GNU Coding Standards.
|
||||
|
||||
Don't reinvent the wheel: we use gnulib, which features many components.
|
||||
Actually, Bison has legacy code that we should replace with gnulib modules
|
||||
(e.g., many ad hoc implementations of lists).
|
||||
|
||||
#### Includes
|
||||
The `#include` directives follow an order:
|
||||
- first section for *.c files is `<config.h>`. Don't include it in header
|
||||
files
|
||||
- then, for *.c files, the corresponding *.h file
|
||||
- then possibly the `"system.h"` header
|
||||
- then the system headers.
|
||||
Consider headers from `lib/` like system headers (i.e., `#include
|
||||
<verify.h>`, not `#include "verify.h"`).
|
||||
- then headers from src/ with double quotes (`#include "getargs.h"`).
|
||||
|
||||
Keep headers sorted alphabetically in each section.
|
||||
|
||||
See also the [Header
|
||||
files](https://www.gnu.org/software/gnulib/manual/html_node/Header-files.html)
|
||||
and the [Implementation
|
||||
files](https://www.gnu.org/software/gnulib/manual/html_node/Implementation-files.html#Implementation-files)
|
||||
nodes of the gnulib documentation.
|
||||
|
||||
Some source files are in the build tree (e.g., `src/scan-gram.c` made from
|
||||
`src/scan-gram.l`). For them to find the headers from `src/`, we actually
|
||||
use `#include "src/getargs.h"` instead of `#include "getargs.h"`---that
|
||||
saves us from additional `-I` flags.
|
||||
|
||||
### Skeletons
|
||||
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 consistency on `! defined` vs. `!defined`. The day gnulib
|
||||
decides, we'll follow them.
|
||||
|
||||
#### C/C++
|
||||
Follow the GNU Coding Standards.
|
||||
|
||||
The `glr.c` skeleton was implemented with `camlCase`. We are migrating it
|
||||
to `snake_case`. Because we are gradually standardizing the code, it is
|
||||
currently inconsistent.
|
||||
|
||||
Use `YYFOO` and `yyfoo` for entities that are exposed to the user. They are
|
||||
part of our contract with the users wrt backward compatibility.
|
||||
|
||||
Use `YY_FOO` and `yy_foo` for private matters. Users should not use them,
|
||||
we are free to change them without fear of backward compatibility issues.
|
||||
|
||||
Use `*_t` for types, especially for `yy*_t` in which case we shouldn't worry
|
||||
about the C standard introducing such a name.
|
||||
|
||||
#### C++
|
||||
Follow the [C++ Core
|
||||
Guidelines](http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines).
|
||||
The [Google ones](https://google.github.io/styleguide/cppguide.html) may be
|
||||
interesting too.
|
||||
|
||||
Our enumerators, such as the kinds (symbol and token kinds), should be lower
|
||||
case, but it was too late to follow that track for token kinds, and symbol
|
||||
kind enumerators are made to be consistent with them.
|
||||
|
||||
Use `*_type` for type aliases. Use `foo_get()` and `foo_set(v)` for
|
||||
accessors, or simply `foo()` and `foo(v)`.
|
||||
|
||||
Use the `yy` prefix for private stuff, but there's no need for it in the
|
||||
public API. The `yy` prefix is already taken care of via the namespace.
|
||||
|
||||
#### Java
|
||||
We follow the [Java Code
|
||||
Conventions](https://www.oracle.com/technetwork/java/codeconventions-150003.pdf)
|
||||
and [Google Java Style
|
||||
Guide](https://google.github.io/styleguide/javaguide.html). Unfortunately
|
||||
at some point some GNU Coding Style was installed in Java, but it's an
|
||||
error. So we should for instance stop putting spaces in function calls.
|
||||
Because we are standardizing the code, it is currently inconsistent.
|
||||
|
||||
Use a 2-space indentation (Google) rather than 4 (Oracle).
|
||||
|
||||
Don't use the "yy" prefix for public members: "getExpectedTokens", not
|
||||
"yyexpectedTokens" or "yygetExpectedTokens".
|
||||
|
||||
## Commit Messages
|
||||
Imitate the style we use. Use `git log` to get sources of inspiration.
|
||||
|
||||
If the changes have a small impact on Bison's generated parser, embed these
|
||||
changes in the commit itself. If the impact is large, first push all the
|
||||
changes except those about src/parse-gram.[ch], and then another commit
|
||||
named "regen" which is only about them.
|
||||
|
||||
## Debugging
|
||||
Bison supports tracing of its various steps, via the `--trace` option.
|
||||
Since it is not meant for the end user, it is not displayed by `bison
|
||||
--help`, nor is it documented in the manual. Instead, run `bison
|
||||
--trace=help`.
|
||||
|
||||
## Documentation
|
||||
Use `@option` for options and options with their argument if they have no
|
||||
space (e.g., `@option{-Dfoo=bar}`). However, use `@samp` elsewhere (e.g.,
|
||||
`@samp{-I foo}`).
|
||||
|
||||
|
||||
Test Suite
|
||||
==========
|
||||
|
||||
@@ -331,9 +380,9 @@ examples, and the main test suite.
|
||||
|
||||
### The Examples
|
||||
In examples/, there is a number of ready-to-use examples (see
|
||||
examples/README.md). These examples have small test suites run by `make
|
||||
check`. The test results are in local `*.log` files (e.g.,
|
||||
`$build/examples/c/calc/calc.log`).
|
||||
[examples/README.md](examples/README.md)). These examples have small test
|
||||
suites run by `make check`. The test results are in local `*.log` files
|
||||
(e.g., `$build/examples/c/calc/calc.log`).
|
||||
|
||||
### The Main Test Suite
|
||||
The main test suite, in tests/, is written on top of GNU Autotest, which is
|
||||
@@ -409,6 +458,31 @@ Use the `javaexec.sh` script. For instance to run the parser of test case
|
||||
|
||||
$ sh ./_build/javaexec.sh -cp ./_build/tests/testsuite.dir/504 Calc
|
||||
|
||||
## Using Sanitizers
|
||||
Address sanitizer (ASAN) and undefined-behavior sanitizer (UBSAN) are very
|
||||
useful. Here's one way to set ASAN up with GCC 10 on Mac Ports
|
||||
|
||||
1. Configure with
|
||||
|
||||
$ ./configure -C --enable-gcc-warnings \
|
||||
CPPFLAGS='-isystem /opt/local/include' \
|
||||
CC='gcc-mp-10 -fsanitize=address' \
|
||||
CFLAGS='-ggdb' \
|
||||
CXX='g++-mp-10.0 -fsanitize=address' \
|
||||
CXXFLAGS='-ggdb' \
|
||||
LDFLAGS='-L/opt/local/lib'
|
||||
|
||||
2. Compile
|
||||
|
||||
3. Generate debug symbols:
|
||||
|
||||
$ dsymutil src/bison
|
||||
|
||||
4. Run the tests with leak detection enabled
|
||||
(`ASAN_OPTIONS=detect_leaks=1`). E.g. for counterexamples:
|
||||
|
||||
$ make check-local TESTSUITEFLAGS='-j5 -k cex' ASAN_OPTIONS=detect_leaks=1
|
||||
|
||||
## make maintainer-check-valgrind
|
||||
This target uses valgrind both to check bison, and the generated parsers.
|
||||
|
||||
@@ -488,7 +562,8 @@ re-run the tests, run:
|
||||
Release Procedure
|
||||
=================
|
||||
|
||||
See README-release.
|
||||
See the [README-release file](README-release), created when the package is
|
||||
bootstrapped.
|
||||
|
||||
<!--
|
||||
|
||||
@@ -524,8 +599,10 @@ LocalWords: symlinks vti html lt POSIX Cc'ed Graphviz Texinfo autoconf jN
|
||||
LocalWords: automake autopoint graphviz texinfo PROG Wother parsers YYFOO
|
||||
LocalWords: TESTSUITEFLAGS deprec struct gnulib's getopt config ggdb yyfoo
|
||||
LocalWords: bitset fsanitize symlink CFLAGS MERCHANTABILITY ispell wrt YY
|
||||
LocalWords: american Administrivia camlCase yy accessors namespace src
|
||||
LocalWords: getExpectedTokens yyexpectedTokens yygetExpectedTokens
|
||||
LocalWords: regen dogfooding Autotest testsuite
|
||||
LocalWords: american Administrivia camlCase yy accessors namespace src hoc
|
||||
LocalWords: getExpectedTokens yyexpectedTokens yygetExpectedTokens parens
|
||||
LocalWords: regen dogfooding Autotest testsuite getargs CPP BAZ endif cppi
|
||||
LocalWords: cpp javaexec cp Calc ASAN UBSAN CPPFLAGS isystem CXX cex Gperf
|
||||
LocalWords: CXXFLAGS LDFLAGS dsymutil gperf
|
||||
|
||||
-->
|
||||
|
||||
@@ -1,14 +1,42 @@
|
||||
* Bison 3.7
|
||||
** Cex
|
||||
*** Improve gnulib
|
||||
Don't do this (counterexample.c):
|
||||
|
||||
// This is the fastest way to get the tail node from the gl_list API.
|
||||
gl_list_node_t
|
||||
list_get_end (gl_list_t list)
|
||||
{
|
||||
gl_list_node_t sentinel = gl_list_add_last (list, NULL);
|
||||
gl_list_node_t res = gl_list_previous_node (list, sentinel);
|
||||
gl_list_remove_node (list, sentinel);
|
||||
return res;
|
||||
}
|
||||
|
||||
*** Ambiguous rewriting
|
||||
If the user is stupid enough to have equal rules, then the derivations are
|
||||
harder to read:
|
||||
|
||||
Reduce/reduce conflict on tokens $end, "+", "⊕":
|
||||
2 exp: exp "+" exp .
|
||||
3 exp: exp "+" exp .
|
||||
Example exp "+" exp •
|
||||
First derivation exp ::=[ exp "+" exp • ]
|
||||
Example exp "+" exp •
|
||||
Second derivation exp ::=[ exp "+" exp • ]
|
||||
|
||||
Do we care about this? In color, we use twice the same color here, but we
|
||||
could try to use the same color for the same rule.
|
||||
|
||||
*** XML reports
|
||||
Show the counterexamples. This is going to be really hard and/or painful.
|
||||
Unless we play it dumb (little structure).
|
||||
|
||||
** 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
|
||||
- Caret diagnostics
|
||||
|
||||
** Questions
|
||||
*** Java
|
||||
@@ -39,23 +67,6 @@ enough.
|
||||
*** calc.at
|
||||
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.
|
||||
@@ -66,7 +77,7 @@ generates tons of white space in the page, and may contribute to bad page
|
||||
breaks.
|
||||
|
||||
** consistency
|
||||
token vs terminal, variable vs non terminal.
|
||||
token vs terminal.
|
||||
|
||||
** api.token.raw
|
||||
The YYUNDEFTOK could be assigned a semantic value so that yyerror could be
|
||||
@@ -128,7 +139,29 @@ Rici:
|
||||
> 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
|
||||
** Rewrite glr.cc
|
||||
Get rid of scaffolding in glr.c.
|
||||
|
||||
** Unit rules / Injection rules (Akim Demaille)
|
||||
Maybe we could expand unit rules (or "injections", see
|
||||
https://homepages.cwi.nl/~daybuild/daily-books/syntax/2-sdf/sdf.html), i.e.,
|
||||
@@ -395,16 +428,6 @@ undocumented ''features''. Maybe an empty action ought to be
|
||||
presented too. Shall we try to make a single grammar with all these
|
||||
features, or should we have several very small grammars?
|
||||
|
||||
** --report=conflict-path
|
||||
Provide better assistance for understanding the conflicts by providing
|
||||
a sample text exhibiting the (LALR) ambiguity. See the paper from
|
||||
DeRemer and Penello: they already provide the algorithm.
|
||||
|
||||
** Statically check for potential ambiguities in GLR grammars
|
||||
See <http://www.lsv.fr/~schmitz/pub/expamb.pdf> for an approach.
|
||||
An Experimental Ambiguity Detection Tool ∗ Sylvain Schmitz
|
||||
LORIA, INRIA Nancy - Grand Est, Nancy, France
|
||||
|
||||
* Extensions
|
||||
** More languages?
|
||||
Well, only if there is really some demand for it.
|
||||
@@ -495,13 +518,6 @@ XML output for GNU Bison and gcc
|
||||
XML output for GNU Bison
|
||||
http://yaxx.sourceforge.net/
|
||||
|
||||
** Counterexample generation
|
||||
https://lists.gnu.org/archive/html/bug-bison/2016-06/msg00000.html
|
||||
http://www.cs.cornell.edu/andru/papers/cupex/
|
||||
|
||||
Andrew Myers and Vincent Imbimbo are working on this item, see
|
||||
https://github.com/akimd/bison/issues/12
|
||||
|
||||
* Coding system independence
|
||||
Paul notes:
|
||||
|
||||
@@ -578,15 +594,9 @@ Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Compiler Compiler.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.3 or
|
||||
any later version published by the Free Software Foundation; with no
|
||||
Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
|
||||
Texts. A copy of the license is included in the "GNU Free
|
||||
Documentation License" file as part of this distribution.
|
||||
|
||||
+4
-2
@@ -17,7 +17,7 @@
|
||||
|
||||
# gnulib modules used by this package.
|
||||
gnulib_modules='
|
||||
argmatch array-list assert assure
|
||||
argmatch array-list assert assure attribute
|
||||
bitsetv
|
||||
calloc-posix close closeout config-h c-strcase
|
||||
configmake
|
||||
@@ -30,6 +30,7 @@ gnulib_modules='
|
||||
javaexec-script
|
||||
ldexpl
|
||||
libtextstyle-optional
|
||||
linked-list
|
||||
malloc-gnu
|
||||
mbfile mbswidth
|
||||
non-recursive-gnulib-prefix-hack
|
||||
@@ -37,6 +38,7 @@ gnulib_modules='
|
||||
obstack-printf
|
||||
perror progname
|
||||
quote quotearg
|
||||
rbtreehash-list
|
||||
readline
|
||||
readme-release
|
||||
realloc-posix
|
||||
@@ -44,7 +46,7 @@ gnulib_modules='
|
||||
rename
|
||||
spawn-pipe stdbool stpcpy strdup-posix strerror strverscmp
|
||||
timevar
|
||||
unistd unistd-safer unlink unlocked-io
|
||||
unicodeio unistd unistd-safer unlink unlocked-io
|
||||
update-copyright unsetenv verify
|
||||
warnings
|
||||
winsz-ioctl
|
||||
|
||||
@@ -73,6 +73,11 @@ def diff_to_re(match):
|
||||
is_diff = True
|
||||
to.append(l)
|
||||
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)
|
||||
to = "\n".join(to)
|
||||
subst[frm] = to
|
||||
@@ -112,4 +117,6 @@ def process(logfile):
|
||||
|
||||
for logfile in args.logs:
|
||||
trace("FILE:", logfile)
|
||||
if os.path.isdir(logfile):
|
||||
logfile = os.path.join(logfile, 'testsuite.log')
|
||||
process(logfile)
|
||||
|
||||
+4
-2
@@ -132,10 +132,12 @@ if test "$enable_gcc_warnings" = yes; then
|
||||
-fparse-all-comments -Wdocumentation
|
||||
-Wformat -Wimplicit-fallthrough -Wnull-dereference
|
||||
-Wno-sign-compare -Wno-tautological-constant-out-of-range-compare
|
||||
-Wpointer-arith -Wshadow
|
||||
-Wpointer-arith -Wshadow -Wstrict-aliasing
|
||||
-Wwrite-strings
|
||||
-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
|
||||
-Wweak-vtables'
|
||||
# Warnings for the test suite only.
|
||||
|
||||
+23
-15
@@ -1,6 +1,6 @@
|
||||
This directory contains data needed by Bison.
|
||||
|
||||
# Directory content
|
||||
# Directory Content
|
||||
## Skeletons
|
||||
Bison skeletons: the general shapes of the different parser kinds, that are
|
||||
specialized for specific grammars by the bison program.
|
||||
@@ -48,7 +48,7 @@ various formats.
|
||||
- xml2xhtml.xsl
|
||||
Conversion into XHTML.
|
||||
|
||||
# Implementation note about the skeletons
|
||||
# Implementation Notes About the Skeletons
|
||||
|
||||
"Skeleton" in Bison parlance means "backend": a skeleton is fed by the bison
|
||||
executable with LR tables, facts about the symbols, etc. and they generate
|
||||
@@ -84,29 +84,35 @@ field), where field can `has_id`, `id`, etc.: see
|
||||
The macro `b4_symbol(NUM, FIELD)` gives access to the following FIELDS:
|
||||
|
||||
- `has_id`: 0 or 1
|
||||
Whether the symbol has an id.
|
||||
Whether the symbol has an `id`.
|
||||
|
||||
- `id`: string
|
||||
If has_id, the id (prefixed by api.token.prefix if defined), otherwise
|
||||
defined as empty. Guaranteed to be usable as a C identifier. This is
|
||||
used to define the token kind (i.e., the enum used by the return value of
|
||||
yylex).
|
||||
If `has_id`, the name of the token kind (prefixed by api.token.prefix if
|
||||
defined), otherwise empty. Guaranteed to be usable as a C identifier.
|
||||
This is used to define the token kind (i.e., the enum used by the return
|
||||
value of yylex). Should be named `token_kind`.
|
||||
|
||||
- `tag`: string
|
||||
A human representation of the symbol. Can be 'foo', 'foo.id', '"foo"' etc.
|
||||
A human readable representation of the symbol. Can be `'foo'`,
|
||||
`'foo.id'`, `'"foo"'` etc.
|
||||
|
||||
- `user_number`: integer
|
||||
The code associated to the `id`.
|
||||
- `code`: integer
|
||||
The token code associated to the token kind `id`.
|
||||
The external number as used by yylex. Can be ASCII code when a character,
|
||||
some number chosen by bison, or some user number in the case of
|
||||
%token FOO <NUM>. Corresponds to yychar in yacc.c.
|
||||
some number chosen by bison, or some user number in the case of `%token
|
||||
FOO <NUM>`. Corresponds to `yychar` in `yacc.c`.
|
||||
|
||||
- `is_token`: 0 or 1
|
||||
Whether this is a terminal symbol.
|
||||
|
||||
- `kind_base`: string
|
||||
The base of the symbol kind, i.e., the enumerator of this symbol (token or
|
||||
nonterminal) which is mapping to its `number`.
|
||||
|
||||
- `kind`: string
|
||||
The symbol kind, i.e., the enumerator of this symbol (token or nonterminal)
|
||||
which is mapping to its `number`.
|
||||
Same as `kind_base`, but possibly with a prefix in some languages. E.g.,
|
||||
EOF's `kind_base` and `kind` are `YYSYMBOL_YYEOF` in C, but are
|
||||
`S_YYEMPTY` and `symbol_kind::S_YYEMPTY` in C++.
|
||||
|
||||
- `number`: integer
|
||||
The code associated to the `kind`.
|
||||
@@ -173,7 +179,7 @@ The data corresponding to the symbol `#POS`, where the current rule has
|
||||
Expansion of `$<TYPE>POS`, where the current rule has `RULE-LENGTH` symbols
|
||||
on RHS.
|
||||
|
||||
-----
|
||||
<!--
|
||||
|
||||
Local Variables:
|
||||
mode: markdown
|
||||
@@ -197,3 +203,5 @@ 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/>.
|
||||
|
||||
-->
|
||||
|
||||
@@ -30,5 +30,28 @@
|
||||
/* "Sections" in traces (--trace). */
|
||||
.trace0 { color: green; }
|
||||
|
||||
/* Syntax error messages. */
|
||||
.expected { color: green; }
|
||||
.unexpected { color: red; }
|
||||
|
||||
|
||||
/* Counterexamples. */
|
||||
|
||||
/* Cex: point in rule. */
|
||||
.cex-dot { color: red; }
|
||||
|
||||
/* Cex: coloring various rules. */
|
||||
.cex-0 { color: yellow; }
|
||||
.cex-1 { color: green; }
|
||||
.cex-2 { color: blue; }
|
||||
.cex-3 { color: purple; }
|
||||
.cex-4 { color: violet; }
|
||||
.cex-5 { color: orange; }
|
||||
.cex-6 { color: brown; }
|
||||
.cex-7 { color: mauve; }
|
||||
|
||||
/* Cex: derivation rewriting steps. */
|
||||
.cex-step { font-style: italic; }
|
||||
|
||||
/* Cex: leaves of a derivation. */
|
||||
.cex-leaf { font-weight: 600; }
|
||||
|
||||
@@ -34,6 +34,7 @@ dist_skeletons_DATA = \
|
||||
data/skeletons/lalr1.java \
|
||||
data/skeletons/location.cc \
|
||||
data/skeletons/stack.hh \
|
||||
data/skeletons/traceon.m4 \
|
||||
data/skeletons/variant.hh \
|
||||
data/skeletons/yacc.c
|
||||
|
||||
|
||||
+41
-10
@@ -19,6 +19,29 @@
|
||||
# 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])])
|
||||
|
||||
# m4_shift2 and m4_shift3 are provided by m4sugar.
|
||||
m4_define([m4_shift4], [m4_shift(m4_shift(m4_shift(m4_shift($@))))])
|
||||
|
||||
|
||||
## ---------------- ##
|
||||
## Identification. ##
|
||||
## ---------------- ##
|
||||
@@ -162,7 +185,7 @@ m4_define([b4_error],
|
||||
[b4_cat([[@complain][(]$1[@,]$2[@,]$3[@,]$4[]]dnl
|
||||
[m4_if([$#], [4], [],
|
||||
[m4_foreach([b4_arg],
|
||||
m4_dquote(m4_shift(m4_shift(m4_shift(m4_shift($@))))),
|
||||
m4_dquote(m4_shift4($@)),
|
||||
[[@,]b4_arg])])[@)]])])
|
||||
|
||||
# b4_warn(FORMAT, [ARG1], [ARG2], ...)
|
||||
@@ -415,14 +438,14 @@ m4_define([b4_symbol_token_kind],
|
||||
_b4_symbol([$1], [id])])
|
||||
|
||||
|
||||
# b4_symbol_kind(NUM)
|
||||
# -------------------
|
||||
# b4_symbol_kind_base(NUM)
|
||||
# ------------------------
|
||||
# Build the name of the kind of this symbol. It must always exist,
|
||||
# otherwise some symbols might not be represented in the enum, which
|
||||
# might be compiled into too small a type to contain all the symbol
|
||||
# numbers.
|
||||
m4_define([b4_symbol_prefix], [b4_percent_define_get([api.symbol.prefix])])
|
||||
m4_define([b4_symbol_kind],
|
||||
m4_define([b4_symbol_kind_base],
|
||||
[b4_percent_define_get([api.symbol.prefix])dnl
|
||||
m4_case([$1],
|
||||
[-2], [[YYEMPTY]],
|
||||
@@ -435,6 +458,13 @@ m4_case([$1],
|
||||
[m4_bpatsubst([$1-][]_b4_symbol([$1], [tag]), [[^a-zA-Z_0-9]+], [_])])])])])
|
||||
|
||||
|
||||
# b4_symbol_kind(NUM)
|
||||
# -------------------
|
||||
# Same as b4_symbol_kind, but possibly with a prefix in some
|
||||
# languages. E.g., EOF's kind_base and kind are YYSYMBOL_YYEOF in C,
|
||||
# but are S_YYEMPTY and symbol_kind::S_YYEMPTY in C++.
|
||||
m4_copy([b4_symbol_kind_base], [b4_symbol_kind])
|
||||
|
||||
# b4_symbol(NUM, FIELD)
|
||||
# ---------------------
|
||||
# Fetch FIELD of symbol #NUM (or "orig NUM"). Fail if undefined.
|
||||
@@ -442,8 +472,9 @@ m4_case([$1],
|
||||
# If FIELD = id, prepend the token prefix.
|
||||
m4_define([b4_symbol],
|
||||
[m4_case([$2],
|
||||
[id], [b4_symbol_token_kind([$1])],
|
||||
[kind], [b4_symbol_kind([$1])],
|
||||
[id], [b4_symbol_token_kind([$1])],
|
||||
[kind_base], [b4_symbol_kind_base([$1])],
|
||||
[kind], [b4_symbol_kind([$1])],
|
||||
[_b4_symbol($@)])])
|
||||
|
||||
|
||||
@@ -516,7 +547,7 @@ m4_popdef([b4_actions_])dnl
|
||||
# easier to use with m4_map, but then, use []dnl to suppress the last
|
||||
# one.
|
||||
m4_define([_b4_symbol_case],
|
||||
[case b4_symbol([$1], [number]): b4_symbol_tag_comment([$1])])
|
||||
[case b4_symbol([$1], [kind]): b4_symbol_tag_comment([$1])])
|
||||
])
|
||||
|
||||
|
||||
@@ -564,8 +595,8 @@ m4_define([b4_any_token_visible_if],
|
||||
m4_define([b4_token_format],
|
||||
[b4_token_visible_if([$2],
|
||||
[m4_format([[$1]],
|
||||
m4_expand(b4_symbol([$2], [id])),
|
||||
m4_expand(b4_symbol([$2], b4_api_token_raw_if([[number]], [[user_number]]))))])])
|
||||
b4_symbol([$2], [id]),
|
||||
b4_symbol([$2], b4_api_token_raw_if([[number]], [[code]])))])])
|
||||
|
||||
|
||||
# b4_last_enum_token
|
||||
@@ -727,7 +758,7 @@ m4_define([b4_check_user_names],
|
||||
[m4_pushdef([b4_occurrence], b4_occurrence)dnl
|
||||
m4_pushdef([b4_user_name], m4_car(b4_occurrence))dnl
|
||||
m4_pushdef([b4_start], m4_car(m4_shift(b4_occurrence)))dnl
|
||||
m4_pushdef([b4_end], m4_shift(m4_shift(b4_occurrence)))dnl
|
||||
m4_pushdef([b4_end], m4_shift2(b4_occurrence))dnl
|
||||
m4_ifndef($3[(]m4_quote(b4_user_name)[)],
|
||||
[b4_complain_at([b4_start], [b4_end],
|
||||
[[%s '%s' is not used]],
|
||||
|
||||
@@ -105,7 +105,7 @@ b4_percent_define_default([[api.parser.class]], [[parser]])
|
||||
#
|
||||
# b4_percent_define_default([[api.location.type]], [[location]])
|
||||
|
||||
b4_percent_define_default([[filename_type]], [[std::string]])
|
||||
b4_percent_define_default([[api.filename.type]], [[const std::string]])
|
||||
# Make it a warning for those who used betas of Bison 3.0.
|
||||
b4_percent_define_default([[api.namespace]], m4_defn([b4_prefix]))
|
||||
|
||||
@@ -193,7 +193,7 @@ m4_define([b4_declare_symbol_enum],
|
||||
[[enum symbol_kind_type
|
||||
{
|
||||
YYNTOKENS = ]b4_tokens_number[, ///< Number of tokens.
|
||||
]b4_symbol_kind([-2])[ = -2,
|
||||
]b4_symbol(-2, kind_base)[ = -2,
|
||||
]b4_symbol_foreach([ b4_symbol_enum])dnl
|
||||
[ };]])
|
||||
|
||||
@@ -507,7 +507,7 @@ m4_define([b4_public_types_define],
|
||||
bool
|
||||
]b4_parser_class[::basic_symbol<Base>::empty () const YY_NOEXCEPT
|
||||
{
|
||||
return this->kind () == symbol_kind::]b4_symbol_prefix[YYEMPTY;
|
||||
return this->kind () == ]b4_symbol(-2, kind)[;
|
||||
}
|
||||
|
||||
template <typename Base>
|
||||
@@ -523,7 +523,7 @@ m4_define([b4_public_types_define],
|
||||
|
||||
// by_kind.
|
||||
]b4_inline([$1])b4_parser_class[::by_kind::by_kind ()
|
||||
: kind_ (symbol_kind::]b4_symbol_prefix[YYEMPTY)
|
||||
: kind_ (]b4_symbol(-2, kind)[)
|
||||
{}
|
||||
|
||||
#if 201103L <= YY_CPLUSPLUS
|
||||
@@ -545,7 +545,7 @@ m4_define([b4_public_types_define],
|
||||
]b4_inline([$1])[void
|
||||
]b4_parser_class[::by_kind::clear ()
|
||||
{
|
||||
kind_ = symbol_kind::]b4_symbol_prefix[YYEMPTY;
|
||||
kind_ = ]b4_symbol(-2, kind)[;
|
||||
}
|
||||
|
||||
]b4_inline([$1])[void
|
||||
@@ -594,11 +594,11 @@ m4_define([b4_yytranslate_define],
|
||||
{
|
||||
]b4_translate[
|
||||
};
|
||||
const int user_token_number_max_ = ]b4_user_token_number_max[;
|
||||
const int code_max_ = ]b4_code_max[;
|
||||
|
||||
if (t <= 0)
|
||||
return symbol_kind::]b4_symbol_prefix[YYEOF;
|
||||
else if (t <= user_token_number_max_)
|
||||
else if (t <= code_max_)
|
||||
return YY_CAST (symbol_kind_type, translate_table[t]);
|
||||
else
|
||||
return symbol_kind::]b4_symbol_prefix[YYUNDEF;]])[
|
||||
|
||||
@@ -17,15 +17,21 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
# _b4_comment(TEXT, OPEN, CONTINUE, END)
|
||||
# --------------------------------------
|
||||
# Put TEXT in comment. Avoid trailing spaces: don't indent empty lines.
|
||||
# Avoid adding indentation to the first line, as the indentation comes
|
||||
# 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.
|
||||
m4_define([_b4_comment],
|
||||
[$2[]m4_bpatsubst(m4_expand([[$1]]), [
|
||||
[$2[]b4_gsub(m4_expand([$1]),
|
||||
[[*]/], [*\\/],
|
||||
[/[*]], [/\\*],
|
||||
[
|
||||
\(.\)], [
|
||||
$3\1])$4])
|
||||
|
||||
|
||||
+17
-9
@@ -355,15 +355,23 @@ m4_define([b4_attribute_define],
|
||||
#endif
|
||||
|
||||
]m4_bmatch([$1], [\bnoreturn\b], [[/* The _Noreturn keyword of C11. */
|
||||
]dnl This is an exact copy of lib/_Noreturn.h.
|
||||
]dnl This is close to lib/_Noreturn.h, except that we do enable
|
||||
dnl the use of [[noreturn]], because _Noreturn is used in places
|
||||
dnl where [[noreturn]] works in C++. We need this in particular
|
||||
dnl because of glr.cc which compiles code from glr.c in C++.
|
||||
dnl And the C++ compiler chokes on _Noreturn. Also, we do not
|
||||
dnl use C' _Noreturn in C++, to avoid -Wc11-extensions warnings.
|
||||
[#ifndef _Noreturn
|
||||
# if (defined __cplusplus \
|
||||
&& ((201103 <= __cplusplus && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \
|
||||
|| (defined _MSC_VER && 1900 <= _MSC_VER)))
|
||||
# define _Noreturn [[noreturn]]
|
||||
# elif ((!defined __cplusplus || defined __clang__) \
|
||||
# elif (!defined __cplusplus \
|
||||
&& (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \
|
||||
|| 4 < __GNUC__ + (7 <= __GNUC_MINOR__)))
|
||||
|| 4 < __GNUC__ + (7 <= __GNUC_MINOR__) \
|
||||
|| (defined __apple_build_version__ \
|
||||
? 6000000 <= __apple_build_version__ \
|
||||
: 3 < __clang_major__ + (5 <= __clang_minor__))))
|
||||
/* _Noreturn works as-is. */
|
||||
# elif 2 < __GNUC__ + (8 <= __GNUC_MINOR__) || 0x5110 <= __SUNPRO_C
|
||||
# define _Noreturn __attribute__ ((__noreturn__))
|
||||
@@ -515,7 +523,7 @@ m4_define([b4_token_enum],
|
||||
[m4_format([ %-30s %s],
|
||||
m4_format([[%s = %s%s%s]],
|
||||
b4_symbol([$1], [id]),
|
||||
b4_symbol([$1], b4_api_token_raw_if([[number]], [[user_number]])),
|
||||
b4_symbol([$1], b4_api_token_raw_if([[number]], [[code]])),
|
||||
m4_if([$1], b4_last_enum_token, [], [[,]])),
|
||||
[b4_symbol_tag_comment([$1])])])])
|
||||
|
||||
@@ -564,7 +572,7 @@ m4_define([b4_symbol_translate],
|
||||
m4_define([b4_symbol_enum],
|
||||
[m4_format([ %-40s %s],
|
||||
m4_format([[%s = %s%s%s]],
|
||||
b4_symbol([$1], [kind]),
|
||||
b4_symbol([$1], [kind_base]),
|
||||
[$1],
|
||||
m4_if([$1], b4_last_symbol, [], [[,]])),
|
||||
[b4_symbol_tag_comment([$1])])])
|
||||
@@ -579,7 +587,7 @@ m4_define([b4_declare_symbol_enum],
|
||||
[[/* Symbol kind. */
|
||||
enum yysymbol_kind_t
|
||||
{
|
||||
]b4_symbol_kind([-2])[ = -2,
|
||||
]b4_symbol([-2], kind_base)[ = -2,
|
||||
]b4_symbol_foreach([b4_symbol_enum])dnl
|
||||
[};
|
||||
typedef enum yysymbol_kind_t yysymbol_kind_t;
|
||||
@@ -658,10 +666,10 @@ m4_define([b4_sync_start], [[#]line $1 $2])
|
||||
## User actions. ##
|
||||
## -------------- ##
|
||||
|
||||
# b4_case(LABEL, STATEMENTS)
|
||||
# --------------------------
|
||||
# b4_case(LABEL, STATEMENTS, [COMMENTS])
|
||||
# --------------------------------------
|
||||
m4_define([b4_case],
|
||||
[ case $1:
|
||||
[ case $1:m4_ifval([$3], [ b4_comment([$3])])
|
||||
$2
|
||||
b4_syncline([@oline@], [@ofile@])dnl
|
||||
break;])
|
||||
|
||||
+12
-5
@@ -152,6 +152,8 @@ private static immutable b4_int_type_for([$2])[[]] yy$1_ =
|
||||
## Token kinds. ##
|
||||
## ------------- ##
|
||||
|
||||
m4_define([b4_symbol(-2, id)], [[YYEMPTY]])
|
||||
|
||||
# b4_token_enum(TOKEN-NAME, TOKEN-NUMBER)
|
||||
# ---------------------------------------
|
||||
# Output the definition of this token as an enum.
|
||||
@@ -178,6 +180,11 @@ b4_symbol_foreach([b4_token_enum])dnl
|
||||
|
||||
b4_percent_define_default([[api.symbol.prefix]], [[S_]])
|
||||
|
||||
# b4_symbol_kind(NUM)
|
||||
# -------------------
|
||||
m4_define([b4_symbol_kind],
|
||||
[SymbolKind.b4_symbol_kind_base($@)])
|
||||
|
||||
|
||||
# b4_symbol_enum(SYMBOL-NUM)
|
||||
# --------------------------
|
||||
@@ -185,7 +192,7 @@ b4_percent_define_default([[api.symbol.prefix]], [[S_]])
|
||||
m4_define([b4_symbol_enum],
|
||||
[m4_format([ %-30s %s],
|
||||
m4_format([[%s = %s,]],
|
||||
b4_symbol([$1], [kind]),
|
||||
b4_symbol([$1], [kind_base]),
|
||||
[$1]),
|
||||
[b4_symbol_tag_comment([$1])])])
|
||||
|
||||
@@ -199,16 +206,16 @@ m4_define([b4_declare_symbol_enum],
|
||||
[[ /* Symbol kinds. */
|
||||
public enum SymbolKind
|
||||
{
|
||||
]b4_symbol_kind([-2])[ = -2, /* No symbol. */
|
||||
]b4_symbol(-2, kind_base)[ = -2, /* No symbol. */
|
||||
]b4_symbol_foreach([b4_symbol_enum])dnl
|
||||
[ };
|
||||
]])])
|
||||
|
||||
|
||||
|
||||
# b4-case(ID, CODE)
|
||||
# -----------------
|
||||
m4_define([b4_case], [ case $1:
|
||||
# b4-case(ID, CODE, [COMMENTS])
|
||||
# -----------------------------
|
||||
m4_define([b4_case], [ case $1:m4_ifval([$3], [ b4_comment([$3])])
|
||||
$2
|
||||
break;])
|
||||
|
||||
|
||||
@@ -189,9 +189,9 @@ b4_glr_cc_if([],
|
||||
[b4_output_begin([b4_spec_header_file])
|
||||
b4_copyright([Skeleton interface for Bison GLR parsers in C],
|
||||
[2002-2015, 2018-2020])[
|
||||
]b4_cpp_guard_open([b4_spec_header_file])[
|
||||
]b4_cpp_guard_open([b4_spec_mapped_header_file])[
|
||||
]b4_shared_declarations[
|
||||
]b4_cpp_guard_close([b4_spec_header_file])[
|
||||
]b4_cpp_guard_close([b4_spec_mapped_header_file])[
|
||||
]b4_output_end[
|
||||
]])])
|
||||
|
||||
@@ -230,7 +230,9 @@ b4_copyright([Skeleton implementation for Bison GLR parsers in C],
|
||||
|
||||
]b4_defines_if([[#include "@basename(]b4_spec_header_file[@)"]],
|
||||
[b4_shared_declarations])[
|
||||
]b4_declare_symbol_enum[
|
||||
|
||||
]b4_glr_cc_if([b4_glr_cc_setup],
|
||||
[b4_declare_symbol_enum])[
|
||||
|
||||
/* Default (constant) value used for initialization for null
|
||||
right-hand sides. Unlike the standard yacc.c template, here we set
|
||||
@@ -332,7 +334,7 @@ static YYLTYPE yyloc_default][]b4_yyloc_default;])[
|
||||
#define YYMAXLEFT ]b4_max_left_semantic_context[
|
||||
|
||||
/* YYMAXUTOK -- Last valid token number (for yychar). */
|
||||
#define YYMAXUTOK ]b4_user_token_number_max[
|
||||
#define YYMAXUTOK ]b4_code_max[
|
||||
|
||||
/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
|
||||
as returned by yylex, with out-of-bounds checking. */
|
||||
@@ -2731,7 +2733,8 @@ m4_if(b4_prefix, [yy], [],
|
||||
#define yynerrs ]b4_prefix[nerrs]b4_locations_if([[
|
||||
#define yylloc ]b4_prefix[lloc]])])[
|
||||
|
||||
]m4_ifdef([b4_pre_epilogue], [b4_pre_epilogue])[]dnl This is a hack for glr.cc. To remove when we have a better glr.cc.
|
||||
b4_percent_code_get([[epilogue]])[]dnl
|
||||
]b4_glr_cc_if([b4_glr_cc_pre_epilogue
|
||||
b4_glr_cc_cleanup])[
|
||||
]b4_percent_code_get([[epilogue]])[]dnl
|
||||
b4_epilogue[]dnl
|
||||
b4_output_end
|
||||
|
||||
+57
-44
@@ -66,12 +66,6 @@ m4_defn([b4_parse_param]))],
|
||||
[[b4_namespace_ref::b4_parser_class[& yyparser], [[yyparser]]]])
|
||||
])
|
||||
|
||||
# b4_declare_symbol_enum
|
||||
# ----------------------
|
||||
m4_append([b4_declare_symbol_enum],
|
||||
[[typedef symbol_kind_type yysymbol_kind_t;
|
||||
]])
|
||||
|
||||
|
||||
# b4_yy_symbol_print_define
|
||||
# -------------------------
|
||||
@@ -105,15 +99,9 @@ yyerror (]b4_locations_if([[const ]b4_namespace_ref::b4_parser_class[::location_
|
||||
]])[]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param),
|
||||
])[const char* msg);]])[
|
||||
|
||||
]b4_percent_define_flag_if([[global_tokens_and_yystype]], [],
|
||||
[m4_define([b4_pre_epilogue],
|
||||
[[/* The user is using the C++ token kind, not the C one. */
|
||||
#undef ]b4_symbol(0, [id])
|
||||
])])[
|
||||
|
||||
# Hijack the epilogue to define implementations (yyerror, parser member
|
||||
# Inserted before the epilogue to define implementations (yyerror, parser member
|
||||
# functions etc.).
|
||||
]m4_append([b4_epilogue],
|
||||
]m4_define([b4_glr_cc_pre_epilogue],
|
||||
[b4_syncline([@oline@], [@ofile@])dnl
|
||||
[
|
||||
/*------------------.
|
||||
@@ -222,6 +210,57 @@ b4_namespace_close[]dnl
|
||||
])
|
||||
|
||||
|
||||
m4_define([b4_define_symbol_kind],
|
||||
[m4_format([#define %-15s %s],
|
||||
b4_symbol($][1, kind_base),
|
||||
b4_namespace_ref[::]b4_parser_class[::symbol_kind::]b4_symbol($1, kind_base))
|
||||
])
|
||||
|
||||
# b4_glr_cc_setup
|
||||
# ---------------
|
||||
# Setup redirections for glr.c: Map the names used in c.m4 to the ones used
|
||||
# in c++.m4.
|
||||
m4_define([b4_glr_cc_setup],
|
||||
[[#undef ]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])[
|
||||
#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
|
||||
# define ]b4_api_PREFIX[STYPE ]b4_namespace_ref[::]b4_parser_class[::semantic_type
|
||||
#endif
|
||||
#ifndef ]b4_api_PREFIX[LTYPE
|
||||
# define ]b4_api_PREFIX[LTYPE ]b4_namespace_ref[::]b4_parser_class[::location_type
|
||||
#endif
|
||||
|
||||
typedef ]b4_namespace_ref[::]b4_parser_class[::symbol_kind_type yysymbol_kind_t;
|
||||
|
||||
// Expose C++ symbol kinds to C.
|
||||
]b4_define_symbol_kind(-2)dnl
|
||||
b4_symbol_foreach([b4_define_symbol_kind])])[
|
||||
]])
|
||||
|
||||
|
||||
m4_define([b4_undef_symbol_kind],
|
||||
[[#undef ]b4_symbol($1, kind_base)[
|
||||
]])
|
||||
|
||||
|
||||
# b4_glr_cc_cleanup
|
||||
# -----------------
|
||||
# Remove redirections for glr.c.
|
||||
m4_define([b4_glr_cc_cleanup],
|
||||
[[#undef ]b4_symbol(-2, [id])[
|
||||
#undef ]b4_symbol(0, [id])[
|
||||
#undef ]b4_symbol(1, [id])[
|
||||
|
||||
]b4_undef_symbol_kind(-2)dnl
|
||||
b4_symbol_foreach([b4_undef_symbol_kind])dnl
|
||||
])
|
||||
|
||||
|
||||
# b4_shared_declarations(hh|cc)
|
||||
# -----------------------------
|
||||
# Declaration that might either go into the header (if --defines, $1 = hh)
|
||||
@@ -333,48 +372,22 @@ b4_percent_code_get([[requires]])[
|
||||
]b4_parse_param_vars[
|
||||
};
|
||||
|
||||
]dnl Redirections for glr.c.
|
||||
b4_percent_define_flag_if([[global_tokens_and_yystype]],
|
||||
[b4_token_defines
|
||||
])[
|
||||
]b4_namespace_close[
|
||||
|
||||
]dnl Map the name used in c.m4 to the one used in c++.m4.
|
||||
[#undef ]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])[
|
||||
#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
|
||||
# define ]b4_api_PREFIX[STYPE ]b4_namespace_ref[::]b4_parser_class[::semantic_type
|
||||
#endif
|
||||
#ifndef ]b4_api_PREFIX[LTYPE
|
||||
# define ]b4_api_PREFIX[LTYPE ]b4_namespace_ref[::]b4_parser_class[::location_type
|
||||
#endif
|
||||
|
||||
]m4_define([b4_declare_symbol_enum],
|
||||
[[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[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[YYUNDEF ]b4_namespace_ref[::]b4_parser_class[::symbol_kind::]b4_symbol_prefix[YYUNDEF
|
||||
]])[
|
||||
]b4_percent_code_get([[provides]])[
|
||||
]m4_popdef([b4_parse_param])dnl
|
||||
])
|
||||
])[
|
||||
|
||||
b4_defines_if(
|
||||
]b4_defines_if(
|
||||
[b4_output_begin([b4_spec_header_file])
|
||||
b4_copyright([Skeleton interface for Bison GLR parsers in C++],
|
||||
[2002-2015, 2018-2020])[
|
||||
// C++ GLR parser skeleton written by Akim Demaille.
|
||||
|
||||
]b4_disclaimer[
|
||||
]b4_cpp_guard_open([b4_spec_header_file])[
|
||||
]b4_cpp_guard_open([b4_spec_mapped_header_file])[
|
||||
]b4_shared_declarations[
|
||||
]b4_cpp_guard_close([b4_spec_header_file])[
|
||||
]b4_cpp_guard_close([b4_spec_mapped_header_file])[
|
||||
]b4_output_end])
|
||||
|
||||
# Let glr.c (and b4_shared_declarations) believe that the user
|
||||
|
||||
+12
-5
@@ -143,7 +143,7 @@ m4_define([b4_token_enum],
|
||||
]],
|
||||
b4_symbol([$1], [tag]),
|
||||
b4_symbol([$1], [id]),
|
||||
b4_symbol([$1], b4_api_token_raw_if([[number]], [[user_number]])))])])
|
||||
b4_symbol([$1], b4_api_token_raw_if([[number]], [[code]])))])])
|
||||
|
||||
|
||||
# b4_token_enums
|
||||
@@ -159,13 +159,20 @@ b4_symbol_foreach([b4_token_enum])])])
|
||||
## Symbol kinds. ##
|
||||
## -------------- ##
|
||||
|
||||
|
||||
# b4_symbol_kind(NUM)
|
||||
# -------------------
|
||||
m4_define([b4_symbol_kind],
|
||||
[SymbolKind.b4_symbol_kind_base($@)])
|
||||
|
||||
|
||||
# b4_symbol_enum(SYMBOL-NUM)
|
||||
# --------------------------
|
||||
# Output the definition of this symbol as an enum.
|
||||
m4_define([b4_symbol_enum],
|
||||
[m4_format([ %-30s %s],
|
||||
m4_format([[%s(%s)%s]],
|
||||
b4_symbol([$1], [kind]),
|
||||
b4_symbol([$1], [kind_base]),
|
||||
[$1],
|
||||
m4_if([$1], b4_last_symbol, [[;]], [[,]])),
|
||||
[b4_symbol_tag_comment([$1])])])
|
||||
@@ -255,11 +262,11 @@ m4_define([b4_declare_symbol_enum],
|
||||
|
||||
|
||||
|
||||
# b4_case(ID, CODE)
|
||||
# -----------------
|
||||
# b4_case(ID, CODE, [COMMENTS])
|
||||
# -----------------------------
|
||||
# We need to fool Java's stupid unreachable code detection.
|
||||
m4_define([b4_case],
|
||||
[ case $1:
|
||||
[ case $1:m4_ifval([$3], [ b4_comment([$3])])
|
||||
if (yyn == $1)
|
||||
$2;
|
||||
break;
|
||||
|
||||
+22
-23
@@ -59,6 +59,13 @@ m4_define([b4_integral_parser_table_define],
|
||||
};dnl
|
||||
])
|
||||
|
||||
|
||||
# b4_symbol_kind(NUM)
|
||||
# -------------------
|
||||
m4_define([b4_symbol_kind],
|
||||
[symbol_kind::b4_symbol_kind_base($@)])
|
||||
|
||||
|
||||
# b4_symbol_value_template(VAL, SYMBOL-NUM, [TYPE])
|
||||
# -------------------------------------------------
|
||||
# Same as b4_symbol_value, but used in a template method. It makes
|
||||
@@ -486,14 +493,6 @@ m4_define([b4_shared_declarations],
|
||||
]b4_public_types_define([$1])])[
|
||||
]b4_namespace_close[
|
||||
|
||||
]b4_percent_define_flag_if([[global_tokens_and_yystype]],
|
||||
[b4_token_defines
|
||||
|
||||
#ifndef ]b4_api_PREFIX[STYPE
|
||||
// Redirection for backward compatibility.
|
||||
# define ]b4_api_PREFIX[STYPE b4_namespace_ref::b4_parser_class::semantic_type
|
||||
#endif
|
||||
])[
|
||||
]b4_percent_code_get([[provides]])[
|
||||
]])
|
||||
|
||||
@@ -506,16 +505,16 @@ b4_defines_if(
|
||||
b4_copyright([Skeleton interface for Bison LALR(1) parsers in C++])
|
||||
[
|
||||
/**
|
||||
** \file ]b4_spec_header_file[
|
||||
** \file ]b4_spec_mapped_header_file[
|
||||
** Define the ]b4_namespace_ref[::parser class.
|
||||
*/
|
||||
|
||||
// C++ LALR(1) parser skeleton written by Akim Demaille.
|
||||
|
||||
]b4_disclaimer[
|
||||
]b4_cpp_guard_open([b4_spec_header_file])[
|
||||
]b4_cpp_guard_open([b4_spec_mapped_header_file])[
|
||||
]b4_shared_declarations(hh)[
|
||||
]b4_cpp_guard_close([b4_spec_header_file])[
|
||||
]b4_cpp_guard_close([b4_spec_mapped_header_file])[
|
||||
]b4_output_end[
|
||||
]])
|
||||
|
||||
@@ -666,7 +665,7 @@ m4_if(b4_prefix, [yy], [],
|
||||
]b4_parser_class[::by_state::kind () const YY_NOEXCEPT
|
||||
{
|
||||
if (state == empty_state)
|
||||
return symbol_kind::]b4_symbol(-2, kind)[;
|
||||
return ]b4_symbol(-2, kind)[;
|
||||
else
|
||||
return YY_CAST (symbol_kind_type, yystos_[+state]);
|
||||
}
|
||||
@@ -691,7 +690,7 @@ m4_if(b4_prefix, [yy], [],
|
||||
b4_symbol_variant([that.kind ()],
|
||||
[value], [move], [YY_MOVE (that.value)])])[
|
||||
// that is emptied.
|
||||
that.kind_ = symbol_kind::]b4_symbol(-2, kind)[;
|
||||
that.kind_ = ]b4_symbol(-2, kind)[;
|
||||
}
|
||||
|
||||
#if YY_CPLUSPLUS < 201103L
|
||||
@@ -920,13 +919,13 @@ b4_dollar_popdef])[]dnl
|
||||
}
|
||||
YY_SYMBOL_PRINT ("Next token is", yyla);
|
||||
|
||||
if (yyla.kind () == ]symbol_kind::b4_symbol(1, kind)[)
|
||||
if (yyla.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)[;
|
||||
yyla.kind_ = ]b4_symbol(2, kind)[;
|
||||
goto yyerrlab1;
|
||||
}
|
||||
|
||||
@@ -1063,7 +1062,7 @@ b4_dollar_popdef])[]dnl
|
||||
error, discard it. */
|
||||
|
||||
// Return failure if at end of input.
|
||||
if (yyla.kind () == symbol_kind::]b4_symbol_prefix[YYEOF)
|
||||
if (yyla.kind () == ]b4_symbol(0, kind)[)
|
||||
YYABORT;
|
||||
else if (!yyla.empty ())
|
||||
{
|
||||
@@ -1104,9 +1103,9 @@ b4_dollar_popdef])[]dnl
|
||||
yyn = yypact_[+yystack_[0].state];
|
||||
if (!yy_pact_value_is_default_ (yyn))
|
||||
{
|
||||
yyn += symbol_kind::]b4_symbol(1, kind)[;
|
||||
yyn += ]b4_symbol(1, kind)[;
|
||||
if (0 <= yyn && yyn <= yylast_
|
||||
&& yycheck_[yyn] == symbol_kind::]b4_symbol(1, kind)[)
|
||||
&& yycheck_[yyn] == ]b4_symbol(1, kind)[)
|
||||
{
|
||||
yyn = yytable_[yyn];
|
||||
if (0 < yyn)
|
||||
@@ -1298,8 +1297,8 @@ b4_dollar_popdef])[]dnl
|
||||
for (int yyx = 0; yyx < YYNTOKENS; ++yyx)
|
||||
{
|
||||
symbol_kind_type yysym = YY_CAST (symbol_kind_type, yyx);
|
||||
if (yysym != symbol_kind::]b4_symbol(1, kind)[
|
||||
&& yysym != symbol_kind::]b4_symbol_prefix[YYUNDEF
|
||||
if (yysym != ]b4_symbol(1, kind)[
|
||||
&& yysym != ]b4_symbol(2, kind)[
|
||||
&& yyparser_.yy_lac_check_ (yysym))
|
||||
{
|
||||
if (!yyarg)
|
||||
@@ -1321,7 +1320,7 @@ b4_dollar_popdef])[]dnl
|
||||
int yychecklim = yylast_ - yyn + 1;
|
||||
int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
|
||||
for (int yyx = yyxbegin; yyx < yyxend; ++yyx)
|
||||
if (yycheck_[yyx + yyn] == yyx && yyx != symbol_kind::]b4_symbol(1, kind)[
|
||||
if (yycheck_[yyx + yyn] == yyx && yyx != ]b4_symbol(1, kind)[
|
||||
&& !yy_table_value_is_error_ (yytable_[yyx + yyn]))
|
||||
{
|
||||
if (!yyarg)
|
||||
@@ -1334,7 +1333,7 @@ b4_dollar_popdef])[]dnl
|
||||
}
|
||||
]])[
|
||||
if (yyarg && yycount == 0 && 0 < yyargn)
|
||||
yyarg[0] = symbol_kind::]b4_symbol(-2, kind)[;
|
||||
yyarg[0] = ]b4_symbol(-2, kind)[;
|
||||
return yycount;
|
||||
}
|
||||
|
||||
@@ -1411,7 +1410,7 @@ b4_dollar_popdef])[]dnl
|
||||
: yylac_stack_.back ());
|
||||
// Push the resulting state of the reduction.
|
||||
state_type state = yy_lr_goto_state_ (top_state, yyr1_[yyrule]);
|
||||
YYCDEBUG << " G" << state;
|
||||
YYCDEBUG << " G" << int (state);
|
||||
yylac_stack_.push_back (state);
|
||||
}
|
||||
}
|
||||
|
||||
+15
-15
@@ -430,7 +430,7 @@ b4_locations_if([, ref ]b4_location_type[ yylocationp])[)
|
||||
{
|
||||
/// Lookahead and lookahead in internal form.
|
||||
int yychar = TokenKind.YYEMPTY;
|
||||
SymbolKind yytoken = SymbolKind.]b4_symbol(-2, kind)[;
|
||||
SymbolKind yytoken = ]b4_symbol(-2, kind)[;
|
||||
|
||||
/* State. */
|
||||
int yyn = 0;
|
||||
@@ -509,14 +509,14 @@ m4_popdef([b4_at_dollar])])dnl
|
||||
yytoken = yytranslate_ (yychar);]b4_parse_trace_if([[
|
||||
yy_symbol_print ("Next token is", yytoken, yylval]b4_locations_if([, yylloc])[);]])[
|
||||
|
||||
if (yytoken == SymbolKind.]b4_symbol(1, kind)[)
|
||||
if (yytoken == ]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. */
|
||||
yychar = TokenKind.YYUNDEF;
|
||||
yytoken = SymbolKind.]b4_symbol_prefix[YYUNDEF;]b4_locations_if([[
|
||||
yychar = TokenKind.]b4_symbol(2, id)[;
|
||||
yytoken = ]b4_symbol(2, kind)[;]b4_locations_if([[
|
||||
yyerrloc = yylloc;]])[
|
||||
label = YYERRLAB1;
|
||||
}
|
||||
@@ -587,8 +587,8 @@ m4_popdef([b4_at_dollar])])dnl
|
||||
if (yyerrstatus_ == 0)
|
||||
{
|
||||
++yynerrs_;
|
||||
if (yychar == TokenKind.YYEMPTY)
|
||||
yytoken = SymbolKind.]b4_symbol(-2, kind)[;
|
||||
if (yychar == TokenKind.]b4_symbol(-2, id)[)
|
||||
yytoken = ]b4_symbol(-2, kind)[;
|
||||
yyerror (]b4_locations_if([yylloc, ])[yysyntax_error (yystate, yytoken));
|
||||
}
|
||||
]b4_locations_if([
|
||||
@@ -638,8 +638,8 @@ m4_popdef([b4_at_dollar])])dnl
|
||||
yyn = yypact_[yystate];
|
||||
if (!yy_pact_value_is_default_ (yyn))
|
||||
{
|
||||
yyn += SymbolKind.]b4_symbol(1, kind)[;
|
||||
if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == SymbolKind.]b4_symbol(1, kind)[)
|
||||
yyn += ]b4_symbol(1, kind)[;
|
||||
if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == ]b4_symbol(1, kind)[)
|
||||
{
|
||||
yyn = yytable_[yyn];
|
||||
if (0 < yyn)
|
||||
@@ -726,7 +726,7 @@ m4_popdef([b4_at_dollar])])dnl
|
||||
will still contain any token that will not be accepted due
|
||||
to an error action in a later state.
|
||||
*/
|
||||
if (tok != SymbolKind.]b4_symbol(-2, kind)[)
|
||||
if (tok != ]b4_symbol(-2, kind)[)
|
||||
{
|
||||
// FIXME: This method of building the message is not compatible
|
||||
// with internationalization.
|
||||
@@ -745,14 +745,14 @@ m4_popdef([b4_at_dollar])])dnl
|
||||
int yyxend = yychecklim < yyntokens_ ? yychecklim : yyntokens_;
|
||||
int count = 0;
|
||||
for (int x = yyxbegin; x < yyxend; ++x)
|
||||
if (yycheck_[x + yyn] == x && x != SymbolKind.]b4_symbol(1, kind)[
|
||||
if (yycheck_[x + yyn] == x && x != ]b4_symbol(1, kind)[
|
||||
&& !yy_table_value_is_error_ (yytable_[x + yyn]))
|
||||
++count;
|
||||
if (count < 5)
|
||||
{
|
||||
count = 0;
|
||||
for (int x = yyxbegin; x < yyxend; ++x)
|
||||
if (yycheck_[x + yyn] == x && x != SymbolKind.]b4_symbol(1, kind)[
|
||||
if (yycheck_[x + yyn] == x && x != ]b4_symbol(1, kind)[
|
||||
&& !yy_table_value_is_error_ (yytable_[x + yyn]))
|
||||
{
|
||||
res ~= count++ == 0 ? ", expecting " : " or ";
|
||||
@@ -841,17 +841,17 @@ m4_popdef([b4_at_dollar])])dnl
|
||||
]b4_translate[
|
||||
@};
|
||||
|
||||
immutable int user_token_number_max_ = ]b4_user_token_number_max[;
|
||||
immutable int code_max_ = ]b4_code_max[;
|
||||
|
||||
if (t <= 0)
|
||||
return SymbolKind.]b4_symbol_prefix[YYEOF;
|
||||
else if (t <= user_token_number_max_)
|
||||
return ]b4_symbol(0, kind)[;
|
||||
else if (t <= code_max_)
|
||||
{
|
||||
import std.conv : to;
|
||||
return to!SymbolKind (translate_table[t]);
|
||||
}
|
||||
else
|
||||
return SymbolKind.]b4_symbol_prefix[YYUNDEF;]])[
|
||||
return ]b4_symbol(2, kind)[;]])[
|
||||
}
|
||||
|
||||
private static immutable int yylast_ = ]b4_last[;
|
||||
|
||||
+25
-25
@@ -79,7 +79,7 @@ m4_define([b4_define_state],[[
|
||||
]b4_copyright([Skeleton implementation for Bison LALR(1) parsers in Java],
|
||||
[2007-2015, 2018-2020])[
|
||||
]b4_disclaimer[
|
||||
]b4_percent_define_ifdef([package], [package b4_percent_define_get([package]);[
|
||||
]b4_percent_define_ifdef([api.package], [package b4_percent_define_get([api.package]);[
|
||||
]])[
|
||||
]b4_user_pre_prologue[
|
||||
]b4_user_post_prologue[
|
||||
@@ -602,9 +602,9 @@ b4_dollar_popdef[]dnl
|
||||
push_token_consumed = false;]], [b4_parse_trace_if([[
|
||||
yycdebug ("Reading a token");]])[
|
||||
yychar = yylexer.yylex ();
|
||||
yylval = yylexer.getLVal ();]b4_locations_if([
|
||||
yylloc = new b4_location_type (yylexer.getStartPos (),
|
||||
yylexer.getEndPos ());])[
|
||||
yylval = yylexer.getLVal();]b4_locations_if([[
|
||||
yylloc = new ]b4_location_type[(yylexer.getStartPos(),
|
||||
yylexer.getEndPos());]])[
|
||||
]])[
|
||||
}
|
||||
|
||||
@@ -613,14 +613,14 @@ b4_dollar_popdef[]dnl
|
||||
yySymbolPrint("Next token is", yytoken,
|
||||
yylval]b4_locations_if([, yylloc])[);]])[
|
||||
|
||||
if (yytoken == SymbolKind.]b4_symbol_prefix[YYerror)
|
||||
if (yytoken == ]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. */
|
||||
yychar = Lexer.]b4_percent_define_get([api.token.prefix])[YYUNDEF;
|
||||
yytoken = SymbolKind.]b4_symbol_prefix[YYUNDEF;]b4_locations_if([[
|
||||
yychar = Lexer.]b4_symbol(2, id)[;
|
||||
yytoken = ]b4_symbol(2, kind)[;]b4_locations_if([[
|
||||
yyerrloc = yylloc;]])[
|
||||
label = YYERRLAB1;
|
||||
}
|
||||
@@ -628,8 +628,8 @@ b4_dollar_popdef[]dnl
|
||||
{
|
||||
/* If the proper action on seeing token YYTOKEN is to reduce or to
|
||||
detect an error, take that action. */
|
||||
yyn += yytoken.getCode ();
|
||||
if (yyn < 0 || YYLAST_ < yyn || yycheck_[yyn] != yytoken.getCode ())
|
||||
yyn += yytoken.getCode();
|
||||
if (yyn < 0 || YYLAST_ < yyn || yycheck_[yyn] != yytoken.getCode())
|
||||
label = YYDEFAULT;
|
||||
|
||||
/* <= 0 means reduce or error. */
|
||||
@@ -744,9 +744,9 @@ b4_dollar_popdef[]dnl
|
||||
yyn = yypact_[yystate];
|
||||
if (!yyPactValueIsDefault (yyn))
|
||||
{
|
||||
yyn += SymbolKind.]b4_symbol(1, kind)[.getCode ();
|
||||
yyn += ]b4_symbol(1, kind)[.getCode();
|
||||
if (0 <= yyn && yyn <= YYLAST_
|
||||
&& yycheck_[yyn] == SymbolKind.]b4_symbol(1, kind)[.getCode ())
|
||||
&& yycheck_[yyn] == ]b4_symbol(1, kind)[.getCode())
|
||||
{
|
||||
yyn = yytable_[yyn];
|
||||
if (0 < yyn)
|
||||
@@ -779,7 +779,7 @@ b4_dollar_popdef[]dnl
|
||||
yystack.pop (2);]])[
|
||||
|
||||
/* 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])[);]])[
|
||||
|
||||
yystate = yyn;
|
||||
@@ -933,15 +933,15 @@ b4_dollar_popdef[]dnl
|
||||
int yychecklim = YYLAST_ - yyn + 1;
|
||||
int yyxend = yychecklim < NTOKENS ? yychecklim : NTOKENS;
|
||||
for (int yyx = yyxbegin; yyx < yyxend; ++yyx)
|
||||
if (yycheck_[yyx + yyn] == yyx && yyx != SymbolKind.]b4_symbol(1, kind)[.getCode ()
|
||||
&& !yyTableValueIsError (yytable_[yyx + yyn]))
|
||||
if (yycheck_[yyx + yyn] == yyx && yyx != ]b4_symbol(1, kind)[.getCode()
|
||||
&& !yyTableValueIsError(yytable_[yyx + yyn]))
|
||||
{
|
||||
if (yyarg == null)
|
||||
yycount += 1;
|
||||
else if (yycount == yyargn)
|
||||
return 0; // FIXME: this is incorrect.
|
||||
else
|
||||
yyarg[yycount++] = SymbolKind.get (yyx);
|
||||
yyarg[yycount++] = SymbolKind.get(yyx);
|
||||
}
|
||||
}
|
||||
if (yyarg != null && yycount == yyoffset && yyoffset < yyargn)
|
||||
@@ -981,12 +981,12 @@ b4_dollar_popdef[]dnl
|
||||
to an error action in a later state.
|
||||
*/
|
||||
int yycount = 0;
|
||||
if (yyctx.getToken () != null)
|
||||
if (yyctx.getToken() != null)
|
||||
{
|
||||
if (yyarg != null)
|
||||
yyarg[yycount] = yyctx.getToken ();
|
||||
yyarg[yycount] = yyctx.getToken();
|
||||
yycount += 1;
|
||||
yycount += yyctx.getExpectedTokens (yyarg, 1, yyargn);
|
||||
yycount += yyctx.getExpectedTokens(yyarg, 1, yyargn);
|
||||
}
|
||||
return yycount;
|
||||
}
|
||||
@@ -1071,7 +1071,7 @@ b4_dollar_popdef[]dnl
|
||||
/* The symbols being reduced. */
|
||||
for (int yyi = 0; yyi < yynrhs; yyi++)
|
||||
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_location(yynrhs, yyi + 1)])[);
|
||||
}]])[
|
||||
@@ -1081,17 +1081,17 @@ b4_dollar_popdef[]dnl
|
||||
private static final SymbolKind yytranslate_ (int t)
|
||||
]b4_api_token_raw_if(dnl
|
||||
[[ {
|
||||
return SymbolKind.get (t);
|
||||
return SymbolKind.get(t);
|
||||
}
|
||||
]],
|
||||
[[ {
|
||||
int user_token_number_max_ = ]b4_user_token_number_max[;
|
||||
int code_max_ = ]b4_code_max[;
|
||||
if (t <= 0)
|
||||
return SymbolKind.]b4_symbol_prefix[YYEOF;
|
||||
else if (t <= user_token_number_max_)
|
||||
return SymbolKind.get (yytranslate_table_[t]);
|
||||
return ]b4_symbol(0, kind)[;
|
||||
else if (t <= code_max_)
|
||||
return SymbolKind.get(yytranslate_table_[t]);
|
||||
else
|
||||
return SymbolKind.]b4_symbol_prefix[YYUNDEF;
|
||||
return ]b4_symbol(2, kind)[;
|
||||
}
|
||||
]b4_integral_parser_table_define([translate_table], [b4_translate])[
|
||||
]])[
|
||||
|
||||
@@ -48,7 +48,7 @@ m4_ifdef([b4_location_file],
|
||||
["b4_location_file"])])
|
||||
m4_define([b4_location_path],
|
||||
b4_percent_define_get([[api.location.include]],
|
||||
["b4_dir_prefix[]b4_location_file"]))
|
||||
["b4_mapped_dir_prefix[]b4_location_file"]))
|
||||
m4_define([b4_location_path],
|
||||
m4_substr(m4_defn([b4_location_path]), 1, m4_eval(m4_len(m4_defn([b4_location_path])) - 2)))
|
||||
])
|
||||
@@ -63,11 +63,13 @@ m4_define([b4_location_define],
|
||||
class position
|
||||
{
|
||||
public:
|
||||
/// Type for file name.
|
||||
typedef ]b4_percent_define_get([[api.filename.type]])[ filename_type;
|
||||
/// Type for line and column numbers.
|
||||
typedef int counter_type;
|
||||
]m4_ifdef([b4_location_constructors], [[
|
||||
/// Construct a position.
|
||||
explicit position (]b4_percent_define_get([[filename_type]])[* f = YY_NULLPTR,
|
||||
explicit position (filename_type* f = YY_NULLPTR,
|
||||
counter_type l = ]b4_location_initial_line[,
|
||||
counter_type c = ]b4_location_initial_column[)
|
||||
: filename (f)
|
||||
@@ -77,7 +79,7 @@ m4_define([b4_location_define],
|
||||
|
||||
]])[
|
||||
/// Initialization.
|
||||
void initialize (]b4_percent_define_get([[filename_type]])[* fn = YY_NULLPTR,
|
||||
void initialize (filename_type* fn = YY_NULLPTR,
|
||||
counter_type l = ]b4_location_initial_line[,
|
||||
counter_type c = ]b4_location_initial_column[)
|
||||
{
|
||||
@@ -106,7 +108,7 @@ m4_define([b4_location_define],
|
||||
/** \} */
|
||||
|
||||
/// File name to which this position refers.
|
||||
]b4_percent_define_get([[filename_type]])[* filename;
|
||||
filename_type* filename;
|
||||
/// Current line number.
|
||||
counter_type line;
|
||||
/// Current column number.
|
||||
@@ -184,6 +186,8 @@ m4_define([b4_location_define],
|
||||
class location
|
||||
{
|
||||
public:
|
||||
/// Type for file name.
|
||||
typedef position::filename_type filename_type;
|
||||
/// Type for line and column numbers.
|
||||
typedef position::counter_type counter_type;
|
||||
]m4_ifdef([b4_location_constructors], [
|
||||
@@ -200,7 +204,7 @@ m4_define([b4_location_define],
|
||||
{}
|
||||
|
||||
/// Construct a 0-width location in \a f, \a l, \a c.
|
||||
explicit location (]b4_percent_define_get([[filename_type]])[* f,
|
||||
explicit location (filename_type* f,
|
||||
counter_type l = ]b4_location_initial_line[,
|
||||
counter_type c = ]b4_location_initial_column[)
|
||||
: begin (f, l, c)
|
||||
@@ -209,7 +213,7 @@ m4_define([b4_location_define],
|
||||
|
||||
])[
|
||||
/// Initialization.
|
||||
void initialize (]b4_percent_define_get([[filename_type]])[* f = YY_NULLPTR,
|
||||
void initialize (filename_type* f = YY_NULLPTR,
|
||||
counter_type l = ]b4_location_initial_line[,
|
||||
counter_type c = ]b4_location_initial_column[)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
dnl GNU M4 treats -dV in a position-independent manner.
|
||||
m4_debugmode(V)m4_traceon()dnl
|
||||
@@ -392,7 +392,7 @@ m4_define([_b4_type_clause],
|
||||
[b4_symbol_if([$1], [is_token],
|
||||
[b4_symbol_if([$1], [has_id],
|
||||
[tok == token::b4_symbol([$1], [id])],
|
||||
[tok == b4_symbol([$1], [user_number])])])])
|
||||
[tok == b4_symbol([$1], [code])])])])
|
||||
|
||||
|
||||
# _b4_token_constructor_define(SYMBOL-NUM...)
|
||||
|
||||
+90
-93
@@ -176,68 +176,47 @@ YYLTYPE yylloc]b4_yyloc_default[;]])[
|
||||
int yynerrs;]])])
|
||||
|
||||
|
||||
# b4_declare_parser_state_variables
|
||||
# ---------------------------------
|
||||
# b4_declare_parser_state_variables([INIT])
|
||||
# -----------------------------------------
|
||||
# Declare all the variables that are needed to maintain the parser state
|
||||
# between calls to yypush_parse.
|
||||
# If INIT is non-null, initialize these variables.
|
||||
m4_define([b4_declare_parser_state_variables],
|
||||
[b4_pure_if([[
|
||||
/* Number of syntax errors so far. */
|
||||
int yynerrs;
|
||||
int yynerrs]m4_ifval([$1], [ = 0])[;
|
||||
]])[
|
||||
yy_state_fast_t yystate;
|
||||
yy_state_fast_t yystate]m4_ifval([$1], [ = 0])[;
|
||||
/* Number of tokens to shift before error messages enabled. */
|
||||
int yyerrstatus;
|
||||
int yyerrstatus]m4_ifval([$1], [ = 0])[;
|
||||
|
||||
/* The stacks and their tools:
|
||||
'yyss': related to states.
|
||||
'yyvs': related to semantic values.]b4_locations_if([[
|
||||
'yyls': related to locations.]])[
|
||||
|
||||
Refer to the stacks through separate pointers, to allow yyoverflow
|
||||
/* Refer to the stacks through separate pointers, to allow yyoverflow
|
||||
to reallocate them elsewhere. */
|
||||
|
||||
/* Their size. */
|
||||
YYPTRDIFF_T yystacksize;
|
||||
YYPTRDIFF_T yystacksize]m4_ifval([$1], [ = YYINITDEPTH])[;
|
||||
|
||||
/* The state stack. */
|
||||
/* The state stack: array, bottom, top. */
|
||||
yy_state_t yyssa[YYINITDEPTH];
|
||||
yy_state_t *yyss;
|
||||
yy_state_t *yyssp;
|
||||
yy_state_t *yyss]m4_ifval([$1], [ = yyssa])[;
|
||||
yy_state_t *yyssp]m4_ifval([$1], [ = yyss])[;
|
||||
|
||||
/* The semantic value stack. */
|
||||
/* The semantic value stack: array, bottom, top. */
|
||||
YYSTYPE yyvsa[YYINITDEPTH];
|
||||
YYSTYPE *yyvs;
|
||||
YYSTYPE *yyvsp;]b4_locations_if([[
|
||||
YYSTYPE *yyvs]m4_ifval([$1], [ = yyvsa])[;
|
||||
YYSTYPE *yyvsp]m4_ifval([$1], [ = yyvs])[;]b4_locations_if([[
|
||||
|
||||
/* The location stack. */
|
||||
/* The location stack: array, bottom, top. */
|
||||
YYLTYPE yylsa[YYINITDEPTH];
|
||||
YYLTYPE *yyls;
|
||||
YYLTYPE *yylsp;]])[]b4_lac_if([[
|
||||
YYLTYPE *yyls]m4_ifval([$1], [ = yylsa])[;
|
||||
YYLTYPE *yylsp]m4_ifval([$1], [ = yyls])[;]])[]b4_lac_if([[
|
||||
|
||||
yy_state_t yyesa@{]b4_percent_define_get([[parse.lac.es-capacity-initial]])[@};
|
||||
yy_state_t *yyes;
|
||||
YYPTRDIFF_T yyes_capacity;]])])
|
||||
|
||||
|
||||
# b4_initialize_parser_state_variables
|
||||
# ------------------------------------
|
||||
# Initialize these variables.
|
||||
m4_define([b4_initialize_parser_state_variables],
|
||||
[[ yynerrs = 0;
|
||||
yystate = 0;
|
||||
yyerrstatus = 0;
|
||||
|
||||
yystacksize = YYINITDEPTH;
|
||||
yyssp = yyss = yyssa;
|
||||
yyvsp = yyvs = yyvsa;]b4_locations_if([[
|
||||
yylsp = yyls = yylsa;]])[]b4_lac_if([[
|
||||
|
||||
yyes = yyesa;
|
||||
yyes_capacity = ]b4_percent_define_get([[parse.lac.es-capacity-initial]])[;
|
||||
if (YYMAXDEPTH < yyes_capacity)
|
||||
yyes_capacity = YYMAXDEPTH;]])[
|
||||
]])
|
||||
yy_state_t *yyes]m4_ifval([$1], [ = yyesa])[;
|
||||
YYPTRDIFF_T yyes_capacity][]m4_ifval([$1],
|
||||
[m4_do([ = b4_percent_define_get([[parse.lac.es-capacity-initial]]) < YYMAXDEPTH],
|
||||
[ ? b4_percent_define_get([[parse.lac.es-capacity-initial]])],
|
||||
[ : YYMAXDEPTH])])[;]])])
|
||||
|
||||
|
||||
m4_define([b4_macro_define],
|
||||
@@ -313,14 +292,14 @@ m4_define([b4_declare_yyparse],
|
||||
# Declaration that might either go into the header (if --defines)
|
||||
# or open coded in the parser body.
|
||||
m4_define([b4_shared_declarations],
|
||||
[b4_cpp_guard_open([b4_spec_header_file])[
|
||||
[b4_cpp_guard_open([b4_spec_mapped_header_file])[
|
||||
]b4_declare_yydebug[
|
||||
]b4_percent_code_get([[requires]])[
|
||||
]b4_token_enums_defines[
|
||||
]b4_declare_yylstype[
|
||||
]b4_declare_yyparse[
|
||||
]b4_percent_code_get([[provides]])[
|
||||
]b4_cpp_guard_close([b4_spec_header_file])[]dnl
|
||||
]b4_cpp_guard_close([b4_spec_mapped_header_file])[]dnl
|
||||
])
|
||||
|
||||
|
||||
@@ -335,7 +314,7 @@ m4_define([b4_header_include_if],
|
||||
[$2])],
|
||||
[$2])])
|
||||
|
||||
m4_if(b4_spec_header_file, [[y.tab.h]],
|
||||
m4_if(b4_spec_header_file, [y.tab.h], [],
|
||||
[b4_percent_define_default([[api.header.include]],
|
||||
[["@basename(]b4_spec_header_file[@)"]])])
|
||||
|
||||
@@ -592,7 +571,7 @@ union yyalloc
|
||||
/* YYNSTATES -- Number of states. */
|
||||
#define YYNSTATES ]b4_states_number[
|
||||
|
||||
#define YYMAXUTOK ]b4_user_token_number_max[
|
||||
#define YYMAXUTOK ]b4_code_max[
|
||||
|
||||
|
||||
/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
|
||||
@@ -829,7 +808,8 @@ int yydebug;
|
||||
/* Parser data structure. */
|
||||
struct yypstate
|
||||
{]b4_declare_parser_state_variables[
|
||||
/* Whether this instance has not started parsing yet. */
|
||||
/* Whether this instance has not started parsing yet.
|
||||
* If 2, it corresponds to a finished parsing. */
|
||||
int yynew;
|
||||
};]b4_pure_if([], [[
|
||||
|
||||
@@ -1444,49 +1424,54 @@ yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg,
|
||||
int
|
||||
yyparse (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[)
|
||||
{
|
||||
return yypull_parse (YY_NULLPTR]b4_user_args[);
|
||||
yypstate *yyps = yypstate_new ();
|
||||
if (!yyps)
|
||||
{]b4_pure_if([b4_locations_if([[
|
||||
static YYLTYPE yyloc_default][]b4_yyloc_default[;
|
||||
YYLTYPE yylloc = yyloc_default;]])[
|
||||
yyerror (]b4_yyerror_args[YY_("memory exhausted"));]], [[
|
||||
if (!yypstate_allocated)
|
||||
yyerror (]b4_yyerror_args[YY_("memory exhausted"));]])[
|
||||
return 2;
|
||||
}
|
||||
int yystatus = yypull_parse (yyps]b4_user_args[);
|
||||
yypstate_delete (yyps);
|
||||
return yystatus;
|
||||
}
|
||||
|
||||
int
|
||||
yypull_parse (yypstate *yyps]b4_user_formals[)
|
||||
{]b4_pure_if([b4_locations_if([[
|
||||
{
|
||||
YY_ASSERT (yyps);]b4_pure_if([b4_locations_if([[
|
||||
static YYLTYPE yyloc_default][]b4_yyloc_default[;
|
||||
YYLTYPE yylloc = yyloc_default;]])])[
|
||||
yypstate *yyps_local;
|
||||
if (yyps)
|
||||
yyps_local = yyps;
|
||||
else
|
||||
{
|
||||
yyps_local = yypstate_new ();
|
||||
if (!yyps_local)
|
||||
{]b4_pure_if([[
|
||||
yyerror (]b4_yyerror_args[YY_("memory exhausted"));]], [[
|
||||
if (!yypstate_allocated)
|
||||
yyerror (]b4_yyerror_args[YY_("memory exhausted"));]])[
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
int yystatus;
|
||||
do {
|
||||
]b4_pure_if([[ YYSTYPE yylval;
|
||||
int ]])[yychar = ]b4_lex[;
|
||||
yystatus = yypush_parse (yyps_local]b4_pure_if([[, yychar, &yylval]b4_locations_if([[, &yylloc]])])m4_ifset([b4_parse_param], [, b4_args(b4_parse_param)])[);
|
||||
yystatus = yypush_parse (yyps]b4_pure_if([[, yychar, &yylval]b4_locations_if([[, &yylloc]])])m4_ifset([b4_parse_param], [, b4_args(b4_parse_param)])[);
|
||||
} while (yystatus == YYPUSH_MORE);
|
||||
if (!yyps)
|
||||
yypstate_delete (yyps_local);
|
||||
return yystatus;
|
||||
}]])[
|
||||
|
||||
]b4_parse_state_variable_macros([b4_pstate_macro_define])[
|
||||
|
||||
/* Initialize the parser data structure. */
|
||||
void
|
||||
static void
|
||||
yypstate_clear (yypstate *yyps)
|
||||
{
|
||||
]b4_initialize_parser_state_variables[
|
||||
yynerrs = 0;
|
||||
yystate = 0;
|
||||
yyerrstatus = 0;
|
||||
|
||||
yyssp = yyss;
|
||||
yyvsp = yyvs;]b4_locations_if([[
|
||||
yylsp = yyls;]])[
|
||||
|
||||
/* Initialize the state stack, in case yypcontext_expected_tokens is
|
||||
called before the first call to yyparse. */
|
||||
*yyssp = 0;
|
||||
yyps->yynew = 1;
|
||||
}
|
||||
|
||||
/* Initialize the parser data structure. */
|
||||
@@ -1498,9 +1483,16 @@ yypstate_new (void)
|
||||
return YY_NULLPTR;]])[
|
||||
yyps = YY_CAST (yypstate *, malloc (sizeof *yyps));
|
||||
if (!yyps)
|
||||
return YY_NULLPTR;
|
||||
yyps->yynew = 1;]b4_pure_if([], [[
|
||||
return YY_NULLPTR;]b4_pure_if([], [[
|
||||
yypstate_allocated = 1;]])[
|
||||
yystacksize = YYINITDEPTH;
|
||||
yyss = yyssa;
|
||||
yyvs = yyvsa;]b4_locations_if([[
|
||||
yyls = yylsa;]])[]b4_lac_if([[
|
||||
yyes = yyesa;
|
||||
yyes_capacity = ]b4_percent_define_get([[parse.lac.es-capacity-initial]])[;
|
||||
if (YYMAXDEPTH < yyes_capacity)
|
||||
yyes_capacity = YYMAXDEPTH;]])[
|
||||
yypstate_clear (yyps);
|
||||
return yyps;
|
||||
}
|
||||
@@ -1513,10 +1505,10 @@ yypstate_delete (yypstate *yyps)
|
||||
#ifndef yyoverflow
|
||||
/* If the stack was reallocated but the parse did not complete, then the
|
||||
stack still needs to be freed. */
|
||||
if (!yyps->yynew && yyss != yyssa)
|
||||
if (yyss != yyssa)
|
||||
YYSTACK_FREE (yyss);
|
||||
#endif]b4_lac_if([[
|
||||
if (!yyps->yynew && yyes != yyesa)
|
||||
if (yyes != yyesa)
|
||||
YYSTACK_FREE (yyes);]])[
|
||||
free (yyps);]b4_pure_if([], [[
|
||||
yypstate_allocated = 0;]])[
|
||||
@@ -1545,7 +1537,7 @@ yyparse (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[)]])[
|
||||
YYSTYPE yypushed_val = yylval;]b4_locations_if([[
|
||||
YYLTYPE yypushed_loc = yylloc;]])
|
||||
])],
|
||||
[b4_declare_parser_state_variables
|
||||
[b4_declare_parser_state_variables([init])
|
||||
])b4_lac_if([[
|
||||
/* Whether LAC context is established. A Boolean. */
|
||||
int yy_lac_established = 0;]])[
|
||||
@@ -1572,14 +1564,19 @@ yyparse (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[)]])[
|
||||
|
||||
/* The number of symbols on the RHS of the reduced rule.
|
||||
Keep to zero when no symbol should be popped. */
|
||||
int yylen = 0;
|
||||
]b4_push_if([[
|
||||
if (!yyps->yynew)
|
||||
int yylen = 0;]b4_push_if([[
|
||||
|
||||
switch (yyps->yynew)
|
||||
{
|
||||
case 2:
|
||||
yypstate_clear (yyps);
|
||||
goto case_0;
|
||||
|
||||
case_0:
|
||||
case 0:
|
||||
yyn = yypact[yystate];
|
||||
goto yyread_pushed_token;
|
||||
}]], [
|
||||
b4_initialize_parser_state_variables])[
|
||||
}]])[
|
||||
|
||||
YYDPRINTF ((stderr, "Starting parse\n"));
|
||||
|
||||
@@ -2048,13 +2045,13 @@ yyabortlab:
|
||||
yyexhaustedlab:
|
||||
yyerror (]b4_yyerror_args[YY_("memory exhausted"));
|
||||
yyresult = 2;
|
||||
/* Fall through. */
|
||||
goto yyreturn;
|
||||
#endif
|
||||
|
||||
|
||||
/*-----------------------------------------------------.
|
||||
| yyreturn -- parsing is finished, return the result. |
|
||||
`-----------------------------------------------------*/
|
||||
/*-------------------------------------------------------.
|
||||
| yyreturn -- parsing is finished, clean up and return. |
|
||||
`-------------------------------------------------------*/
|
||||
yyreturn:
|
||||
if (yychar != ]b4_symbol(-2, id)[)
|
||||
{
|
||||
@@ -2073,21 +2070,21 @@ yyreturn:
|
||||
yydestruct ("Cleanup: popping",
|
||||
YY_ACCESSING_SYMBOL (+*yyssp), yyvsp]b4_locations_if([, yylsp])[]b4_user_args[);
|
||||
YYPOPSTACK (1);
|
||||
}
|
||||
}]b4_push_if([[
|
||||
yyps->yynew = 2;
|
||||
goto yypushreturn;
|
||||
|
||||
|
||||
/*-------------------------.
|
||||
| yypushreturn -- return. |
|
||||
`-------------------------*/
|
||||
yypushreturn:]], [[
|
||||
#ifndef yyoverflow
|
||||
if (yyss != yyssa)
|
||||
YYSTACK_FREE (yyss);
|
||||
#endif]b4_lac_if([[
|
||||
if (yyes != yyesa)
|
||||
YYSTACK_FREE (yyes);]])b4_push_if([[
|
||||
yypstate_clear (yyps);
|
||||
yyps->yynew = 1;
|
||||
|
||||
|
||||
/*-----------------------------------------.
|
||||
| yypushreturn -- ask for the next token. |
|
||||
`-----------------------------------------*/
|
||||
yypushreturn:]])[
|
||||
YYSTACK_FREE (yyes);]])])[
|
||||
]b4_parse_error_bmatch([detailed\|verbose],
|
||||
[[ if (yymsg != yymsgbuf)
|
||||
YYSTACK_FREE (yymsg);]])[
|
||||
|
||||
@@ -159,7 +159,7 @@
|
||||
<xsl:param name="prev-rule-number"
|
||||
select="preceding-sibling::item[1]/@rule-number"/>
|
||||
<xsl:apply-templates select="key('bison:ruleByNumber', @rule-number)">
|
||||
<xsl:with-param name="point" select="@point"/>
|
||||
<xsl:with-param name="dot" select="@dot"/>
|
||||
<xsl:with-param name="num" select="@rule-number"/>
|
||||
<xsl:with-param name="prev-lhs"
|
||||
select="key('bison:ruleByNumber', $prev-rule-number)/lhs[text()]"
|
||||
@@ -169,7 +169,7 @@
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="rule">
|
||||
<xsl:param name="point"/>
|
||||
<xsl:param name="dot"/>
|
||||
<xsl:param name="num"/>
|
||||
<xsl:param name="prev-lhs"/>
|
||||
<xsl:text> </xsl:text>
|
||||
@@ -198,14 +198,14 @@
|
||||
<xsl:text>:</xsl:text>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<xsl:if test="$point = 0">
|
||||
<xsl:if test="$dot = 0">
|
||||
<xsl:text> .</xsl:text>
|
||||
</xsl:if>
|
||||
|
||||
<!-- RHS -->
|
||||
<xsl:for-each select="rhs/symbol|rhs/empty">
|
||||
<xsl:apply-templates select="."/>
|
||||
<xsl:if test="$point = position()">
|
||||
<xsl:if test="$dot = position()">
|
||||
<xsl:text> .</xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
|
||||
@@ -300,7 +300,7 @@
|
||||
name="prev-lhs"
|
||||
select="key('bison:ruleByNumber', $prev-rule-number)/lhs[text()]"
|
||||
/>
|
||||
<xsl:with-param name="point" select="@point"/>
|
||||
<xsl:with-param name="dot" select="@dot"/>
|
||||
<xsl:with-param name="lookaheads">
|
||||
<xsl:apply-templates select="lookaheads"/>
|
||||
</xsl:with-param>
|
||||
@@ -311,7 +311,7 @@
|
||||
<xsl:param name="itemset"/>
|
||||
<xsl:param name="pad"/>
|
||||
<xsl:param name="prev-lhs"/>
|
||||
<xsl:param name="point"/>
|
||||
<xsl:param name="dot"/>
|
||||
<xsl:param name="lookaheads"/>
|
||||
|
||||
<xsl:if test="$itemset != 'true' and not($prev-lhs = lhs[text()])">
|
||||
@@ -347,11 +347,11 @@
|
||||
|
||||
<!-- RHS -->
|
||||
<xsl:for-each select="rhs/*">
|
||||
<xsl:if test="position() = $point + 1">
|
||||
<xsl:if test="position() = $dot + 1">
|
||||
<xsl:text> .</xsl:text>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates select="."/>
|
||||
<xsl:if test="position() = last() and position() = $point">
|
||||
<xsl:if test="position() = last() and position() = $dot">
|
||||
<xsl:text> .</xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
ol.lower-alpha {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
.point {
|
||||
.dot {
|
||||
color: #cc0000;
|
||||
}
|
||||
#footer {
|
||||
@@ -457,7 +457,7 @@
|
||||
<xsl:with-param name="prev-lhs"
|
||||
select="key('bison:ruleByNumber', $prev-rule-number)/lhs[text()]"
|
||||
/>
|
||||
<xsl:with-param name="point" select="@point"/>
|
||||
<xsl:with-param name="dot" select="@dot"/>
|
||||
<xsl:with-param name="lookaheads">
|
||||
<xsl:apply-templates select="lookaheads"/>
|
||||
</xsl:with-param>
|
||||
@@ -468,7 +468,7 @@
|
||||
<xsl:param name="itemset"/>
|
||||
<xsl:param name="pad"/>
|
||||
<xsl:param name="prev-lhs"/>
|
||||
<xsl:param name="point"/>
|
||||
<xsl:param name="dot"/>
|
||||
<xsl:param name="lookaheads"/>
|
||||
|
||||
<xsl:if test="$itemset != 'true' and not($prev-lhs = lhs[text()])">
|
||||
@@ -529,14 +529,14 @@
|
||||
|
||||
<!-- RHS -->
|
||||
<xsl:for-each select="rhs/*">
|
||||
<xsl:if test="position() = $point + 1">
|
||||
<xsl:if test="position() = $dot + 1">
|
||||
<xsl:text> </xsl:text>
|
||||
<span class="point">.</span>
|
||||
<span class="dot">•</span>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates select="."/>
|
||||
<xsl:if test="position() = last() and position() = $point">
|
||||
<xsl:if test="position() = last() and position() = $dot">
|
||||
<xsl:text> </xsl:text>
|
||||
<span class="point">.</span>
|
||||
<span class="dot">•</span>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
<xsl:if test="$lookaheads">
|
||||
|
||||
+19
-14
@@ -1,4 +1,4 @@
|
||||
# Doxyfile 1.8.17
|
||||
# Doxyfile 1.8.18
|
||||
|
||||
# This file describes the settings to be used by the documentation system
|
||||
# doxygen (www.doxygen.org) for a project.
|
||||
@@ -253,12 +253,6 @@ TAB_SIZE = 8
|
||||
|
||||
ALIASES =
|
||||
|
||||
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
||||
# A mapping has the form "name=value". For example adding "class=itcl::class"
|
||||
# will allow you to use the command class in the itcl::class meaning.
|
||||
|
||||
TCL_SUBST =
|
||||
|
||||
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
|
||||
# only. Doxygen will then generate output that is more tailored for C. For
|
||||
# instance, some of the names that are used will be different. The list of all
|
||||
@@ -300,13 +294,13 @@ OPTIMIZE_OUTPUT_SLICE = NO
|
||||
# extension. Doxygen has a built-in mapping, but you can override or extend it
|
||||
# using this tag. The format is ext=language, where ext is a file extension, and
|
||||
# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
|
||||
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
|
||||
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL,
|
||||
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
|
||||
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
|
||||
# tries to guess whether the code is fixed or free formatted code, this is the
|
||||
# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat
|
||||
# .inc files as Fortran files (default is PHP), and .f files as C (default is
|
||||
# Fortran), use: inc=Fortran f=C.
|
||||
# default for Fortran type files). For instance to make doxygen treat .inc files
|
||||
# as Fortran files (default is PHP), and .f files as C (default is Fortran),
|
||||
# use: inc=Fortran f=C.
|
||||
#
|
||||
# Note: For files without extension you can use no_extension as a placeholder.
|
||||
#
|
||||
@@ -844,7 +838,7 @@ INPUT_ENCODING = UTF-8
|
||||
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
|
||||
# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
|
||||
# *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen
|
||||
# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f, *.for, *.tcl, *.vhd,
|
||||
# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
|
||||
# *.vhdl, *.ucf, *.qsf and *.ice.
|
||||
|
||||
FILE_PATTERNS = *.c \
|
||||
@@ -1490,6 +1484,17 @@ TREEVIEW_WIDTH = 250
|
||||
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
|
||||
# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
|
||||
# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
|
||||
# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
|
||||
# the HTML output. These images will generally look nicer at scaled resolutions.
|
||||
# Possible values are: png The default and svg Looks nicer but requires the
|
||||
# pdf2svg tool.
|
||||
# The default value is: png.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_FORMULA_FORMAT = png
|
||||
|
||||
# Use this tag to change the font size of LaTeX formulas included as images in
|
||||
# the HTML documentation. When you change the font size after a successful
|
||||
# doxygen run you need to manually remove any form_*.png images from the HTML
|
||||
@@ -1545,7 +1550,7 @@ MATHJAX_FORMAT = HTML-CSS
|
||||
# Content Delivery Network so you can quickly see the result without installing
|
||||
# MathJax. However, it is strongly recommended to install a local copy of
|
||||
# MathJax from https://www.mathjax.org before deployment.
|
||||
# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.
|
||||
# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
|
||||
@@ -1715,7 +1720,7 @@ COMPACT_LATEX = NO
|
||||
# The default value is: a4.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
PAPER_TYPE = a4wide
|
||||
PAPER_TYPE = a4
|
||||
|
||||
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
|
||||
# that should be included in the LaTeX output. The package can be specified just
|
||||
|
||||
+640
-240
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@ digraph "reduce.y"
|
||||
node [fontname=courier shape=box]
|
||||
edge [fontname=courier]
|
||||
|
||||
1 [label="State 1\n 3 a: \"0\" . [\".\"]\l 4 b: \"0\" . [\";\"]\l"]
|
||||
1 [label="State 1\n 3 a: \"0\" • [\".\"]\l 4 b: \"0\" • [\";\"]\l"]
|
||||
1 -> "1R3" [label="" style=solid]
|
||||
"1R3" [style=filled shape=diamond fillcolor=yellowgreen label="R3"]
|
||||
1 -> "1R4" [label="[\";\"]" style=solid]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.------------------.
|
||||
| State 1 |
|
||||
| 3 a: "0" . [";"] |
|
||||
| 4 b: "0" . ["."] |
|
||||
| 3 a: "0" • [";"] |
|
||||
| 4 b: "0" • ["."] |
|
||||
`------------------'
|
||||
/ \
|
||||
/ \ ["."]
|
||||
|
||||
@@ -3,7 +3,7 @@ digraph "shift.y"
|
||||
node [fontname=courier shape=box]
|
||||
edge [fontname=courier]
|
||||
|
||||
3 [label="State 3\n 1 exp: a . \".\"\l"]
|
||||
3 [label="State 3\n 1 exp: a • \".\"\l"]
|
||||
3 -> 6 [style=solid label="\".\""]
|
||||
6 [label="State 6\n 1 exp: a \".\" .\l"]
|
||||
6 [label="State 6\n 1 exp: a \".\" •\l"]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.----------------.
|
||||
| State 3 |
|
||||
| 1 exp: a . ";" |
|
||||
| 1 exp: a • ";" |
|
||||
`----------------'
|
||||
|
|
||||
| ";"
|
||||
@@ -8,5 +8,5 @@
|
||||
v
|
||||
.----------------.
|
||||
| State 6 |
|
||||
| 1 exp: a ";" . |
|
||||
| 1 exp: a ";" • |
|
||||
`----------------'
|
||||
|
||||
+9
-9
@@ -2,34 +2,34 @@
|
||||
// Report bugs to <[email protected]>.
|
||||
// Home page: <http://www.gnu.org/software/bison/>.
|
||||
|
||||
digraph "/tmp/fo.y"
|
||||
digraph "example.y"
|
||||
{
|
||||
node [fontname = courier, shape = box, colorscheme = paired6]
|
||||
edge [fontname = courier]
|
||||
|
||||
0 [label="State 0\n\l 0 $accept: . exp $end\l 1 exp: . a \";\"\l 2 | . b \".\"\l 3 a: . \"0\"\l 4 b: . \"0\"\l"]
|
||||
0 [label="State 0\n\l 0 $accept: • exp $end\l 1 exp: • a \";\"\l 2 | • b \".\"\l 3 a: • \"0\"\l 4 b: • \"0\"\l"]
|
||||
0 -> 1 [style=solid label="\"0\""]
|
||||
0 -> 2 [style=dashed label="exp"]
|
||||
0 -> 3 [style=dashed label="a"]
|
||||
0 -> 4 [style=dashed label="b"]
|
||||
1 [label="State 1\n\l 3 a: \"0\" . [\";\"]\l 4 b: \"0\" . [\".\"]\l"]
|
||||
1 [label="State 1\n\l 3 a: \"0\" • [\";\"]\l 4 b: \"0\" • [\".\"]\l"]
|
||||
1 -> "1R3" [style=solid]
|
||||
"1R3" [label="R3", fillcolor=3, shape=diamond, style=filled]
|
||||
1 -> "1R4" [label="[\".\"]", style=solid]
|
||||
"1R4" [label="R4", fillcolor=3, shape=diamond, style=filled]
|
||||
2 [label="State 2\n\l 0 $accept: exp . $end\l"]
|
||||
2 [label="State 2\n\l 0 $accept: exp • $end\l"]
|
||||
2 -> 5 [style=solid label="$end"]
|
||||
3 [label="State 3\n\l 1 exp: a . \";\"\l"]
|
||||
3 [label="State 3\n\l 1 exp: a • \";\"\l"]
|
||||
3 -> 6 [style=solid label="\";\""]
|
||||
4 [label="State 4\n\l 2 exp: b . \".\"\l"]
|
||||
4 [label="State 4\n\l 2 exp: b • \".\"\l"]
|
||||
4 -> 7 [style=solid label="\".\""]
|
||||
5 [label="State 5\n\l 0 $accept: exp $end .\l"]
|
||||
5 [label="State 5\n\l 0 $accept: exp $end •\l"]
|
||||
5 -> "5R0" [style=solid]
|
||||
"5R0" [label="Acc", fillcolor=1, shape=diamond, style=filled]
|
||||
6 [label="State 6\n\l 1 exp: a \";\" .\l"]
|
||||
6 [label="State 6\n\l 1 exp: a \";\" •\l"]
|
||||
6 -> "6R1" [style=solid]
|
||||
"6R1" [label="R1", fillcolor=3, shape=diamond, style=filled]
|
||||
7 [label="State 7\n\l 2 exp: b \".\" .\l"]
|
||||
7 [label="State 7\n\l 2 exp: b \".\" •\l"]
|
||||
7 -> "7R2" [style=solid]
|
||||
"7R2" [label="R2", fillcolor=3, shape=diamond, style=filled]
|
||||
}
|
||||
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
* bench.pl
|
||||
A primitive Perl script to run benches. Currently its only bench is
|
||||
the usual calculator: it has a lightweight processing part (but not
|
||||
null), so it is really emphasizing the cost of the whole parsing
|
||||
(including scanning and I/O).
|
||||
|
||||
Set the envvars BISON and CC to the programs and flags you want to
|
||||
use. They default to bison and gcc. To run a non-installed bison
|
||||
from a tarball built in _build, I suggest the following.
|
||||
|
||||
BISON=_build/tests/bison CC='gcc -O2' ./bench.pl
|
||||
|
||||
(The _build/tests/bison wrapper makes sure that _build/src/bison will
|
||||
use the tarballs' skeletons, not those already installed as a
|
||||
straightforward use of _build/src/bison would.)
|
||||
|
||||
--
|
||||
|
||||
Copyright (C) 2006, 2009-2015, 2018-2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Compiler Compiler.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Local Variables:
|
||||
mode: outline
|
||||
End:
|
||||
@@ -0,0 +1,36 @@
|
||||
# bench.pl
|
||||
A primitive Perl script to run benches. Currently its only bench is the
|
||||
usual calculator: it has a lightweight processing part (but not null), so it
|
||||
is really emphasizing the cost of the whole parsing (including scanning and
|
||||
I/O).
|
||||
|
||||
Set the envvars `BISON` and `CC` to the programs and flags you want to use.
|
||||
They default to `bison` and `gcc`. To run a non-installed bison from a
|
||||
tarball built in _build, I suggest the following.
|
||||
|
||||
BISON=_build/tests/bison CC='gcc -O2' ./bench.pl
|
||||
|
||||
(The `_build/tests/bison` wrapper makes sure that `_build/src/bison` will
|
||||
use the tarballs' skeletons, not those already installed as a
|
||||
straightforward use of `_build/src/bison` would.)
|
||||
|
||||
<!--
|
||||
|
||||
Local Variables:
|
||||
mode: markdown
|
||||
fill-column: 76
|
||||
ispell-dictionary: "american"
|
||||
End:
|
||||
|
||||
Copyright (C) 2006, 2009-2015, 2018-2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Compiler Compiler.
|
||||
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.3 or
|
||||
any later version published by the Free Software Foundation; with no
|
||||
Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
|
||||
Texts. A copy of the license is included in the "GNU Free
|
||||
Documentation License" file as part of this distribution.
|
||||
|
||||
-->
|
||||
+81
-22
@@ -498,7 +498,8 @@ yylex (void)
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
{
|
||||
int nchars = 0;
|
||||
sscanf (input - 1, "%d%n", &yylval.NUM, &nchars);
|
||||
int n = sscanf (input - 1, "%d%n", &yylval.NUM, &nchars);
|
||||
assert (n == 1);
|
||||
input += nchars - 1;
|
||||
return NUM;
|
||||
}
|
||||
@@ -775,7 +776,31 @@ sub run ($)
|
||||
|
||||
##################################################################
|
||||
|
||||
=item C<compile ($base)>
|
||||
=item C<language ($base)>
|
||||
|
||||
The language to use depending on the %language specification in
|
||||
C<$base.y>: C<c> or C<c++>.
|
||||
|
||||
=cut
|
||||
|
||||
sub language ($)
|
||||
{
|
||||
my ($base) = @_;
|
||||
if ($gbench)
|
||||
{
|
||||
"c++";
|
||||
}
|
||||
else
|
||||
{
|
||||
my $language = `sed -ne '/%language "\\(.*\\)"/{s//\\1/;p;q;}' $base.y`;
|
||||
chomp $language;
|
||||
$language eq 'C++' ? "c++" : "c";
|
||||
}
|
||||
}
|
||||
|
||||
##################################################################
|
||||
|
||||
=item C<compiler ($base)>
|
||||
|
||||
The compiler to use depending on the %language specification in
|
||||
C<$base.y>.
|
||||
@@ -785,16 +810,12 @@ C<$base.y>.
|
||||
sub compiler ($)
|
||||
{
|
||||
my ($base) = @_;
|
||||
if ($gbench)
|
||||
{
|
||||
$cxx;
|
||||
}
|
||||
else
|
||||
{
|
||||
my $language = `sed -ne '/%language "\\(.*\\)"/{s//\\1/;p;q;}' $base.y`;
|
||||
chomp $language;
|
||||
$language eq 'C++' ? $cxx : $cc;
|
||||
}
|
||||
my %compiler =
|
||||
(
|
||||
'c++' => $cxx,
|
||||
'c' => $cc,
|
||||
);
|
||||
$compiler{language ($base)};
|
||||
}
|
||||
|
||||
##################################################################
|
||||
@@ -805,21 +826,38 @@ Compile C<$base.y> to an executable.
|
||||
|
||||
=cut
|
||||
|
||||
sub compile ($)
|
||||
sub compile ($$)
|
||||
{
|
||||
my ($base) = @_;
|
||||
my ($makefile, $base) = @_;
|
||||
my $compiler = compiler ($base);
|
||||
|
||||
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");
|
||||
my %ext =
|
||||
(
|
||||
'c++' => 'cc',
|
||||
'c' => 'c',
|
||||
);
|
||||
my $ext = $ext{language ($base)};
|
||||
if ($gbench)
|
||||
{
|
||||
run "$compiler -c -o $base.o $cflags $base.c";
|
||||
print $makefile <<EOF;
|
||||
$base.$ext: $base.y
|
||||
\t@{[length $my_bison ? $my_bison : $bison]} $base.y -o $base.$ext
|
||||
|
||||
$base.o: $base.$ext
|
||||
\t$compiler -c -o $base.o $cflags $base.$ext
|
||||
EOF
|
||||
}
|
||||
else
|
||||
{
|
||||
run "$compiler -o $base $cflags $base.c";
|
||||
print $makefile <<EOF;
|
||||
$base.$ext: $base.y
|
||||
\t@{[length $my_bison ? $my_bison : $bison]} $base.y -o $base.$ext
|
||||
|
||||
$base: $base.$ext
|
||||
\t$compiler -o $base $cflags $base.$ext
|
||||
EOF
|
||||
}
|
||||
}
|
||||
|
||||
@@ -849,11 +887,13 @@ sub bench_with_timethese ($@)
|
||||
# For each bench, capture the size.
|
||||
my %size;
|
||||
|
||||
my $makefile = new IO::File ">Makefile";
|
||||
while (my ($name, $directives) = each %bench)
|
||||
{
|
||||
generate_grammar ($grammar, $name, $directives);
|
||||
# Compile the executable.
|
||||
compile ($name);
|
||||
compile ($makefile, $name);
|
||||
run "make $name";
|
||||
$bench{$name} = "system ('./$name');";
|
||||
chop($size{$name} = `wc -c <$name`);
|
||||
}
|
||||
@@ -906,6 +946,20 @@ sub bench_with_gbenchmark ($@)
|
||||
my $readme = new IO::File ">README.md";
|
||||
print $readme <<EOF;
|
||||
compiler: $compiler $cflags
|
||||
EOF
|
||||
|
||||
my $makefile = new IO::File ">Makefile";
|
||||
print $makefile <<EOF;
|
||||
.PHONY: bench
|
||||
bench: main
|
||||
\t./main \$(BENCHFLAGS) | tee -a README.md
|
||||
|
||||
# Link the bench cases in a different order to run the bench case in a
|
||||
# different order.
|
||||
.PHONY: rand
|
||||
rand:
|
||||
\t-rm main
|
||||
\tmake bench OBJECTS="\$\$(shuf -e \$(OBJECTS) | xargs)"
|
||||
EOF
|
||||
|
||||
my @obj = ();
|
||||
@@ -916,19 +970,24 @@ EOF
|
||||
print $m;
|
||||
print $readme $m;
|
||||
generate_grammar ($grammar, $base, $directive[$i]);
|
||||
compile ($base);
|
||||
compile ($makefile, $base);
|
||||
push @obj, "$base.o";
|
||||
}
|
||||
|
||||
my $out = new IO::File ">main.c";
|
||||
my $out = new IO::File ">main.cc";
|
||||
print $out <<EOF;
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
EOF
|
||||
|
||||
run "$compiler -o main $cflags main.c @obj -lbenchmark";
|
||||
run "./main | tee -a README.md";
|
||||
print $makefile <<EOF;
|
||||
OBJECTS = @{obj}
|
||||
main: \$(OBJECTS)
|
||||
\t$compiler -o main $cflags main.cc \$(OBJECTS) -lbenchmark
|
||||
EOF
|
||||
|
||||
run "make";
|
||||
}
|
||||
|
||||
######################################################################
|
||||
|
||||
+2
-1
@@ -14,4 +14,5 @@
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
nodist_noinst_SCRIPTS = etc/bench.pl
|
||||
dist_noinst_DATA = %D%/README.md
|
||||
nodist_noinst_SCRIPTS = %D%/bench.pl
|
||||
|
||||
@@ -13,8 +13,8 @@ semantic value.
|
||||
|
||||
Run as `./simple`.
|
||||
|
||||
Extracted from the documentation: "A Simple C++ Example".
|
||||
https://www.gnu.org/software/bison/manual/html_node/A-Simple-C_002b_002b-Example.html
|
||||
Extracted from the documentation: [A Simple C++
|
||||
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
|
||||
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
|
||||
examples.
|
||||
|
||||
Extracted from the documentation: "A Complete C++ Example".
|
||||
https://www.gnu.org/software/bison/manual/html_node/A-Complete-C_002b_002b-Example.html
|
||||
Extracted from the documentation: [A Complete C++
|
||||
Example](https://www.gnu.org/software/bison/manual/html_node/A-Complete-C_002b_002b-Example.html).
|
||||
|
||||
<!---
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
Read the corresponding chapter in the documentation: "A Complete C++
|
||||
Example". It is also available on line (maybe with a different version of
|
||||
Bison):
|
||||
https://www.gnu.org/software/bison/manual/html_node/A-Complete-C_002b_002b-Example.html
|
||||
Example". It is also available [on
|
||||
line](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
|
||||
compile the executable, and try it. It is a simple calculator which accepts
|
||||
|
||||
@@ -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
|
||||
provides a good starting point, since operator precedence is not an issue.
|
||||
|
||||
Extracted from the documentation: "Reverse Polish Notation Calculator"
|
||||
https://www.gnu.org/software/bison/manual/html_node/RPN-Calc.html
|
||||
Extracted from the documentation: [Reverse Polish Notation
|
||||
Calculator](https://www.gnu.org/software/bison/manual/html_node/RPN-Calc.html).
|
||||
|
||||
## calc - Simple Calculator
|
||||
This example is slightly more complex than rpcalc: it features infix
|
||||
@@ -24,8 +24,8 @@ A more complete C example: a multi-function calculator. More complex than
|
||||
the previous example. Using precedence directives to support infix
|
||||
operators.
|
||||
|
||||
Extracted from the documentation: "Multi-Function Calculator: mfcalc".
|
||||
https://www.gnu.org/software/bison/manual/html_node/Multi_002dfunction-Calc.html
|
||||
Extracted from the documentation: [Multi-Function Calculator:
|
||||
mfcalc](https://www.gnu.org/software/bison/manual/html_node/Multi_002dfunction-Calc.html).
|
||||
|
||||
## lexcalc - calculator with Flex and Bison
|
||||
The calculator with precedence directives and location tracking. It uses
|
||||
|
||||
@@ -45,7 +45,7 @@ echo >perfect '> 0
|
||||
echo >ok '0'
|
||||
echo '0' | prog >effective
|
||||
|
||||
echo "checking for readline output"
|
||||
echo "checking for readline output..."
|
||||
if diff perfect effective; then
|
||||
# Alles ist gut.
|
||||
strip_prompt=false
|
||||
@@ -269,8 +269,8 @@ 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"
|
||||
case `uname -s` in
|
||||
echo "checking for kernel name... $(uname -s)"
|
||||
case $(uname -s) in
|
||||
(MSYS*)
|
||||
echo "SKIP: this is Windows/MSYS"
|
||||
exit $status
|
||||
@@ -306,3 +306,25 @@ end of file exit exp ''
|
||||
0
|
||||
> ''
|
||||
err: '
|
||||
|
||||
# Check that completion prints valid locations even when there is an error.
|
||||
sed -e 's/\\t/ /g' >input <<EOF
|
||||
1++\t
|
||||
EOF
|
||||
run -n 0 '> 1++ ''
|
||||
> ''
|
||||
err: 1.1: syntax error: expected - or ( or number or function or variable before +
|
||||
err: 1.3: syntax error: expected - or ( or number or function or variable before +
|
||||
'
|
||||
|
||||
# And even when the error was recovered from.
|
||||
sed -e 's/\\t/ /g' >input <<EOF
|
||||
(1++2) + 3 +\t\t
|
||||
EOF
|
||||
run -n 0 '> (1++2) + 3 + ''
|
||||
> ''
|
||||
err: 1.1: syntax error: expected - or ( or number or function or variable before +
|
||||
err: 1.1: syntax error: expected - or ( or number or function or variable before +
|
||||
err: 1.4: syntax error: expected - or ( or number or function or variable before +
|
||||
err: 1.15: syntax error: expected - or ( or number or function or variable before end of file
|
||||
'
|
||||
|
||||
@@ -31,6 +31,7 @@ if ENABLE_BISTROMATHIC
|
||||
-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
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
%require "3.6"
|
||||
|
||||
%code top {
|
||||
#include <assert.h>
|
||||
#include <ctype.h> // isdigit
|
||||
#include <locale.h> // LC_ALL
|
||||
#include <math.h> // cos, sin, etc.
|
||||
@@ -218,7 +217,7 @@ getsym (char const *name)
|
||||
}
|
||||
|
||||
// How many symbols are registered.
|
||||
int
|
||||
static int
|
||||
symbol_count (void)
|
||||
{
|
||||
int res = 0;
|
||||
@@ -268,7 +267,8 @@ yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc)
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
{
|
||||
int nchars = 0;
|
||||
sscanf (*line - 1, "%lf%n", &yylval->TOK_NUM, &nchars);
|
||||
if (sscanf (*line - 1, "%lf%n", &yylval->TOK_NUM, &nchars) != 1)
|
||||
abort ();
|
||||
*line += nchars - 1;
|
||||
yylloc->last_column += nchars - 1;
|
||||
return TOK_NUM;
|
||||
@@ -284,7 +284,8 @@ yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc)
|
||||
{
|
||||
int nchars = 0;
|
||||
char buf[100];
|
||||
sscanf (*line - 1, "%99[a-z]%n", buf, &nchars);
|
||||
if (sscanf (*line - 1, "%99[a-z]%n", buf, &nchars) != 1)
|
||||
abort ();
|
||||
*line += nchars - 1;
|
||||
yylloc->last_column += nchars - 1;
|
||||
if (strcmp (buf, "exit") == 0)
|
||||
@@ -312,7 +313,7 @@ yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc)
|
||||
`---------*/
|
||||
|
||||
|
||||
const char *
|
||||
static const char *
|
||||
error_format_string (int argc)
|
||||
{
|
||||
switch (argc)
|
||||
@@ -407,7 +408,8 @@ xstrndup (const char *string, size_t n)
|
||||
const char *end = memchr (string, '\0', n);
|
||||
size_t len = end ? (size_t) (end - string) : n;
|
||||
char *new = malloc (len + 1);
|
||||
assert (new);
|
||||
if (!new)
|
||||
abort ();
|
||||
new[len] = '\0';
|
||||
return memcpy (new, string, len);
|
||||
}
|
||||
@@ -418,7 +420,8 @@ xstrndup (const char *string, size_t n)
|
||||
`-----------*/
|
||||
|
||||
// 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 ();
|
||||
int status = 0;
|
||||
@@ -433,7 +436,8 @@ int process_line (YYLTYPE *lloc, const char *line)
|
||||
}
|
||||
|
||||
// Get the list of possible tokens after INPUT was read.
|
||||
int
|
||||
// Returns a nonnegative.
|
||||
static int
|
||||
expected_tokens (const char *input,
|
||||
int *tokens, int ntokens)
|
||||
{
|
||||
@@ -443,7 +447,7 @@ expected_tokens (const char *input,
|
||||
yypstate *ps = yypstate_new ();
|
||||
int status = 0;
|
||||
do {
|
||||
YYLTYPE lloc;
|
||||
YYLTYPE lloc = { 1, 1, 1, 1 };
|
||||
YYSTYPE lval;
|
||||
int token = yylex (&input, &lval, &lloc);
|
||||
// Don't let the parse know when we reach the end of input.
|
||||
@@ -452,8 +456,15 @@ expected_tokens (const char *input,
|
||||
status = yypush_parse (ps, token, &lval, &lloc);
|
||||
} while (status == YYPUSH_MORE);
|
||||
|
||||
// Then query for the accepted tokens at this point.
|
||||
int res = yypstate_expected_tokens (ps, tokens, ntokens);
|
||||
int res = 0;
|
||||
// If there were parse errors, don't propose completions.
|
||||
if (!ps->yynerrs)
|
||||
{
|
||||
// Then query for the accepted tokens at this point.
|
||||
res = yypstate_expected_tokens (ps, tokens, ntokens);
|
||||
if (res < 0)
|
||||
abort ();
|
||||
}
|
||||
yypstate_delete (ps);
|
||||
return res;
|
||||
}
|
||||
@@ -463,7 +474,7 @@ expected_tokens (const char *input,
|
||||
// TEXT is the word to complete. We can use the entire contents of
|
||||
// rl_line_buffer in case we want to do some simple parsing. Return
|
||||
// the array of matches, or NULL if there aren't any.
|
||||
char **
|
||||
static char **
|
||||
completion (const char *text, int start, int end)
|
||||
{
|
||||
YYDPRINTF ((stderr, "completion (\"%.*s[%.*s]%s\")\n",
|
||||
@@ -473,14 +484,17 @@ completion (const char *text, int start, int end)
|
||||
|
||||
// Get list of token numbers.
|
||||
int tokens[YYNTOKENS];
|
||||
char *line = xstrndup (rl_line_buffer, start);
|
||||
char *line = xstrndup (rl_line_buffer, (size_t) start);
|
||||
int ntokens = expected_tokens (line, tokens, YYNTOKENS);
|
||||
free (line);
|
||||
|
||||
// Build MATCHES, the list of possible completions.
|
||||
const int len = strlen (text);
|
||||
const size_t len = strlen (text);
|
||||
// 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;
|
||||
for (int i = 0; i < ntokens; ++i)
|
||||
switch (tokens[i])
|
||||
@@ -510,9 +524,9 @@ completion (const char *text, int start, int end)
|
||||
matches[0] = strdup (text);
|
||||
else
|
||||
{
|
||||
int lcplen = strlen (matches[1]);
|
||||
size_t lcplen = strlen (matches[1]);
|
||||
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])
|
||||
lcplen = j;
|
||||
matches[0] = xstrndup (matches[1], lcplen);
|
||||
@@ -536,7 +550,8 @@ completion (const char *text, int start, int end)
|
||||
return matches;
|
||||
}
|
||||
|
||||
void init_readline (void)
|
||||
static void
|
||||
init_readline (void)
|
||||
{
|
||||
// Allow conditional parsing of the ~/.inputrc file.
|
||||
rl_readline_name = "bistromathic";
|
||||
@@ -555,7 +570,8 @@ void init_readline (void)
|
||||
| Main. |
|
||||
`-------*/
|
||||
|
||||
int main (int argc, char const* argv[])
|
||||
int
|
||||
main (int argc, char const* argv[])
|
||||
{
|
||||
#if defined ENABLE_NLS && ENABLE_NLS
|
||||
// Set up internationalization.
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
%code top {
|
||||
#include <assert.h>
|
||||
#include <ctype.h> /* isdigit. */
|
||||
#include <stdio.h> /* For printf, etc. */
|
||||
#include <stdio.h> /* printf. */
|
||||
#include <stdlib.h> /* abort. */
|
||||
#include <string.h> /* strcmp. */
|
||||
|
||||
int yylex (void);
|
||||
@@ -73,7 +75,8 @@ yylex (void)
|
||||
if (c == '.' || isdigit (c))
|
||||
{
|
||||
ungetc (c, stdin);
|
||||
scanf ("%lf", &yylval.NUM);
|
||||
if (scanf ("%lf", &yylval.NUM) != 1)
|
||||
abort ();
|
||||
return NUM;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ nodist_%C%_calc_SOURCES = %D%/calc.y
|
||||
|
||||
# Don't use gnulib's system headers.
|
||||
%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
|
||||
CLEANFILES += %D%/calc.[ch] %D%/calc.output %D%/scan.c
|
||||
|
||||
@@ -25,6 +25,8 @@ if FLEX_WORKS
|
||||
nodist_%C%_lexcalc_SOURCES = %D%/parse.y %D%/parse.h %D%/scan.l
|
||||
# Don't use gnulib's system headers.
|
||||
%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
|
||||
|
||||
%D%/parse.c: $(dependencies)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
%option nodefault noinput nounput noyywrap
|
||||
|
||||
%{
|
||||
#include <errno.h> /* errno, ERANGE */
|
||||
#include <errno.h> /* errno, ERANGE */
|
||||
#include <limits.h> /* INT_MIN */
|
||||
#include <stdlib.h> /* strtol */
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
// Each time a rule is matched, advance the end cursor/position.
|
||||
#define YY_USER_ACTION \
|
||||
yylloc->last_column += yyleng;
|
||||
yylloc->last_column += (int) yyleng;
|
||||
|
||||
// Move the first position onto the last.
|
||||
#define LOCATION_STEP() \
|
||||
|
||||
@@ -31,6 +31,7 @@ nodist_%C%_mfcalc_SOURCES = $(mfcalc_sources)
|
||||
%D%/mfcalc.c: $(dependencies)
|
||||
# Don't use gnulib's system headers.
|
||||
%C%_mfcalc_CPPFLAGS = -I$(top_srcdir)/%D% -I$(top_builddir)/%D%
|
||||
%C%_mfcalc_CFLAGS = $(TEST_CFLAGS)
|
||||
%C%_mfcalc_LDADD = -lm
|
||||
|
||||
dist_TESTS += %D%/mfcalc.test
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
%code top {
|
||||
#include <ctype.h> /* isdigit. */
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h> /* For printf, etc. */
|
||||
#include <stdio.h> /* printf. */
|
||||
#include <stdlib.h> /* abort. */
|
||||
#include <string.h> /* strcmp. */
|
||||
}
|
||||
|
||||
@@ -81,7 +81,8 @@ yylex (YYSTYPE *yylval)
|
||||
if (c == '.' || isdigit (c))
|
||||
{
|
||||
ungetc (c, stdin);
|
||||
scanf ("%lf", &yylval->NUM);
|
||||
if (scanf ("%lf", &yylval->NUM) != 1)
|
||||
abort ();
|
||||
return NUM;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ nodist_%C%_calc_SOURCES = %D%/calc.y
|
||||
|
||||
# Don't use gnulib's system headers.
|
||||
%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
|
||||
CLEANFILES += %D%/calc.[ch] %D%/calc.output
|
||||
|
||||
@@ -26,6 +26,8 @@ if FLEX_WORKS
|
||||
BUILT_SOURCES += $(nodist_%C%_reccalc_SOURCES)
|
||||
# Don't use gnulib's system headers.
|
||||
%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
|
||||
|
||||
%D%/parse.c: $(dependencies)
|
||||
|
||||
@@ -32,9 +32,9 @@
|
||||
do \
|
||||
capacity = capacity ? 2 * capacity : 128; \
|
||||
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; \
|
||||
assert (size < capacity); \
|
||||
} while (0)
|
||||
|
||||
@@ -31,6 +31,7 @@ nodist_%C%_rpcalc_SOURCES = $(rpcalc_sources)
|
||||
%D%/rpcalc.c: $(dependencies)
|
||||
# Don't use gnulib's system headers.
|
||||
%C%_rpcalc_CPPFLAGS = -I$(top_builddir)/%D%
|
||||
%C%_rpcalc_CFLAGS = $(TEST_CFLAGS)
|
||||
%C%_rpcalc_LDADD = -lm
|
||||
|
||||
dist_TESTS += %D%/rpcalc.test
|
||||
|
||||
@@ -35,6 +35,9 @@
|
||||
dist_noinst_SCRIPTS = %D%/extexi %D%/test
|
||||
TEST_LOG_COMPILER = $(SHELL) $(top_srcdir)/%D%/test
|
||||
|
||||
TEST_CFLAGS = \
|
||||
$(WARN_CFLAGS) $(WARN_CFLAGS_TEST) $(WERROR_CFLAGS)
|
||||
|
||||
AM_CXXFLAGS = \
|
||||
$(WARN_CXXFLAGS) $(WARN_CXXFLAGS_TEST) $(WERROR_CXXFLAGS)
|
||||
|
||||
|
||||
+2
-1
@@ -36,10 +36,11 @@ 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"
|
||||
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.
|
||||
abs_medir=$cwd/examples/$medir
|
||||
|
||||
+1
-1
Submodule gnulib updated: 2ac33b29fc...845d69187a
@@ -18,6 +18,7 @@
|
||||
/asnprintf.c
|
||||
/asprintf.c
|
||||
/assure.h
|
||||
/attribute.h
|
||||
/basename-lgpl.c
|
||||
/basename.c
|
||||
/binary-io.c
|
||||
@@ -117,10 +118,31 @@
|
||||
/gettext.h
|
||||
/gettime.c
|
||||
/gettimeofday.c
|
||||
/gl_anyhash1.h
|
||||
/gl_anyhash2.h
|
||||
/gl_anyhash_primes.h
|
||||
/gl_anylinked_list1.h
|
||||
/gl_anylinked_list2.h
|
||||
/gl_anyrbtree_list1.h
|
||||
/gl_anyrbtree_list2.h
|
||||
/gl_anytree_list1.h
|
||||
/gl_anytree_list2.h
|
||||
/gl_anytree_oset.h
|
||||
/gl_anytreehash_list1.h
|
||||
/gl_anytreehash_list2.h
|
||||
/gl_array_list.c
|
||||
/gl_array_list.h
|
||||
/gl_linked_list.c
|
||||
/gl_linked_list.h
|
||||
/gl_list.c
|
||||
/gl_list.h
|
||||
/gl_oset.c
|
||||
/gl_oset.h
|
||||
/gl_rbtree_ordered.h
|
||||
/gl_rbtree_oset.c
|
||||
/gl_rbtree_oset.h
|
||||
/gl_rbtreehash_list.c
|
||||
/gl_rbtreehash_list.h
|
||||
/gl_xlist.c
|
||||
/gl_xlist.h
|
||||
/gnulib.mk
|
||||
@@ -128,6 +150,23 @@
|
||||
/hard-locale.h
|
||||
/hash.c
|
||||
/hash.h
|
||||
/iconv.c
|
||||
/iconv.h
|
||||
/iconv.in.h
|
||||
/iconv_close.c
|
||||
/iconv_open-aix.gperf
|
||||
/iconv_open-aix.h
|
||||
/iconv_open-hpux.gperf
|
||||
/iconv_open-hpux.h
|
||||
/iconv_open-irix.gperf
|
||||
/iconv_open-irix.h
|
||||
/iconv_open-osf.gperf
|
||||
/iconv_open-osf.h
|
||||
/iconv_open-solaris.gperf
|
||||
/iconv_open-solaris.h
|
||||
/iconv_open-zos.gperf
|
||||
/iconv_open-zos.h
|
||||
/iconv_open.c
|
||||
/intprops.h
|
||||
/inttypes.h
|
||||
/inttypes.in.h
|
||||
@@ -305,11 +344,16 @@
|
||||
/timespec.h
|
||||
/timevar.c
|
||||
/timevar.h
|
||||
/unicodeio.c
|
||||
/unicodeio.h
|
||||
/unistd--.h
|
||||
/unistd-safer.h
|
||||
/unistd.c
|
||||
/unistd.h
|
||||
/unistd.in.h
|
||||
/unistr.h
|
||||
/unistr.in.h
|
||||
/unistr/
|
||||
/unitypes.h
|
||||
/unitypes.in.h
|
||||
/uniwidth
|
||||
@@ -318,6 +362,7 @@
|
||||
/unlink.c
|
||||
/unlocked-io.h
|
||||
/unsetenv.c
|
||||
/unused-parameter.h
|
||||
/vasnprintf.c
|
||||
/vasnprintf.h
|
||||
/vasprintf.c
|
||||
|
||||
+6
-1
@@ -1,4 +1,3 @@
|
||||
/extern-inline.m4~
|
||||
/*~
|
||||
/00gnulib.m4
|
||||
/__inline.m4
|
||||
@@ -6,6 +5,7 @@
|
||||
/alloca.m4
|
||||
/asm-underscore.m4
|
||||
/assert.m4
|
||||
/builtin-expect.m4
|
||||
/calloc.m4
|
||||
/canonicalize.m4
|
||||
/clock_time.m4
|
||||
@@ -25,6 +25,7 @@
|
||||
/exponentl.m4
|
||||
/extensions.m4
|
||||
/extern-inline.m4
|
||||
/extern-inline.m4~
|
||||
/fatal-signal.m4
|
||||
/fcntl-o.m4
|
||||
/fcntl.m4
|
||||
@@ -57,7 +58,10 @@
|
||||
/gnulib-tool.m4
|
||||
/host-cpu-c-abi.m4
|
||||
/iconv.m4
|
||||
/iconv_h.m4
|
||||
/iconv_open.m4
|
||||
/include_next.m4
|
||||
/inline.m4
|
||||
/intdiv0.m4
|
||||
/intl.m4
|
||||
/intldir.m4
|
||||
@@ -192,6 +196,7 @@
|
||||
/timespec.m4
|
||||
/tls.m4
|
||||
/uintmax_t.m4
|
||||
/unicodeio.m4
|
||||
/unistd-safer.m4
|
||||
/unistd_h.m4
|
||||
/unlink.m4
|
||||
|
||||
@@ -2,6 +2,7 @@ examples/c/bistromathic/parse.y
|
||||
examples/java/calc/Calc.y
|
||||
src/complain.c
|
||||
src/conflicts.c
|
||||
src/counterexample.c
|
||||
src/files.c
|
||||
src/fixits.c
|
||||
src/getargs.c
|
||||
|
||||
+160
-175
@@ -18,11 +18,13 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <config.h>
|
||||
#include "system.h"
|
||||
|
||||
#include "AnnotationList.h"
|
||||
#include "lalr.h"
|
||||
|
||||
#include "system.h"
|
||||
|
||||
#include "ielr.h"
|
||||
#include "lalr.h"
|
||||
|
||||
/**
|
||||
* \pre
|
||||
@@ -38,15 +40,14 @@ static AnnotationList*
|
||||
AnnotationList__alloc_on_obstack (ContributionIndex contribution_count,
|
||||
struct obstack *annotations_obstackp)
|
||||
{
|
||||
AnnotationList *result;
|
||||
size_t contributions_size =
|
||||
contribution_count * sizeof result->contributions[0];
|
||||
result = obstack_alloc (annotations_obstackp,
|
||||
offsetof (AnnotationList, contributions)
|
||||
+ contributions_size);
|
||||
result->next = NULL;
|
||||
result->inadequacyNode = NULL;
|
||||
return result;
|
||||
AnnotationList *res;
|
||||
size_t contributions_size = contribution_count * sizeof res->contributions[0];
|
||||
res = obstack_alloc (annotations_obstackp,
|
||||
offsetof (AnnotationList, contributions)
|
||||
+ contributions_size);
|
||||
res->next = NULL;
|
||||
res->inadequacyNode = NULL;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,13 +103,12 @@ AnnotationList__insertInto (AnnotationList *self, AnnotationList **list,
|
||||
for (node = list; *node; node = &(*node)->next)
|
||||
{
|
||||
int cmp = 0;
|
||||
ContributionIndex ci;
|
||||
if (self->inadequacyNode->id < (*node)->inadequacyNode->id)
|
||||
cmp = 1;
|
||||
else if ((*node)->inadequacyNode->id < self->inadequacyNode->id)
|
||||
cmp = -1;
|
||||
else
|
||||
for (ci = 0;
|
||||
for (ContributionIndex ci = 0;
|
||||
cmp == 0 && ci < self->inadequacyNode->contributionCount;
|
||||
++ci)
|
||||
{
|
||||
@@ -120,19 +120,16 @@ AnnotationList__insertInto (AnnotationList *self, AnnotationList **list,
|
||||
else if (AnnotationList__isContributionAlways (*node, ci))
|
||||
cmp = 1;
|
||||
else
|
||||
{
|
||||
size_t item;
|
||||
for (item = 0; cmp == 0 && item < nitems; ++item)
|
||||
{
|
||||
if (!Sbitset__test (self->contributions[ci], item))
|
||||
{
|
||||
if (Sbitset__test ((*node)->contributions[ci], item))
|
||||
cmp = -1;
|
||||
}
|
||||
else if (!Sbitset__test ((*node)->contributions[ci], item))
|
||||
cmp = 1;
|
||||
}
|
||||
}
|
||||
for (size_t item = 0; cmp == 0 && item < nitems; ++item)
|
||||
{
|
||||
if (!Sbitset__test (self->contributions[ci], item))
|
||||
{
|
||||
if (Sbitset__test ((*node)->contributions[ci], item))
|
||||
cmp = -1;
|
||||
}
|
||||
else if (!Sbitset__test ((*node)->contributions[ci], item))
|
||||
cmp = 1;
|
||||
}
|
||||
}
|
||||
if (cmp < 0)
|
||||
{
|
||||
@@ -188,7 +185,7 @@ AnnotationList__compute_conflicted_tokens (bitset shift_tokens,
|
||||
}
|
||||
|
||||
static bool
|
||||
AnnotationList__compute_lhs_contributions (state *s, rule *the_rule,
|
||||
AnnotationList__compute_lhs_contributions (state *s, const rule *the_rule,
|
||||
symbol_number conflicted_token,
|
||||
bitsetv follow_kernel_items,
|
||||
bitsetv always_follows,
|
||||
@@ -232,115 +229,110 @@ AnnotationList__computePredecessorAnnotations (
|
||||
annotation_node->inadequacyNode = self->inadequacyNode;
|
||||
bool potential_contribution = false;
|
||||
bitset *lookaheads = NULL;
|
||||
{
|
||||
for (ContributionIndex ci = 0; ci < self->inadequacyNode->contributionCount; ++ci)
|
||||
{
|
||||
symbol_number contribution_token =
|
||||
InadequacyList__getContributionToken (self->inadequacyNode, ci)
|
||||
->content->number;
|
||||
if (AnnotationList__isContributionAlways (self, ci))
|
||||
{
|
||||
annotation_node->contributions[ci] = NULL;
|
||||
continue;
|
||||
}
|
||||
annotation_node->contributions[ci] =
|
||||
Sbitset__new_on_obstack ((*predecessor)->nitems,
|
||||
annotations_obstackp);
|
||||
|
||||
for (ContributionIndex ci = 0; ci < self->inadequacyNode->contributionCount; ++ci)
|
||||
{
|
||||
symbol_number contribution_token =
|
||||
InadequacyList__getContributionToken (self->inadequacyNode, ci)
|
||||
->content->number;
|
||||
if (AnnotationList__isContributionAlways (self, ci))
|
||||
{
|
||||
size_t predecessor_item = 0;
|
||||
Sbitset sbiter_item;
|
||||
Sbitset__Index self_item;
|
||||
SBITSET__FOR_EACH (self->contributions[ci], s->nitems,
|
||||
sbiter_item, self_item)
|
||||
{
|
||||
/* If this kernel item is the beginning of a RHS, it must be
|
||||
the kernel item in the start state, and so it has an empty
|
||||
lookahead set. Thus, it can't contribute to inadequacies,
|
||||
and so it should never have been identified as a
|
||||
contribution. If, instead, this kernel item is the
|
||||
successor of the start state's kernel item, the lookahead
|
||||
set is still empty, and so it also should never have been
|
||||
identified as a contribution. This situation is fortunate
|
||||
because we want to avoid the - 2 below in both cases. */
|
||||
aver (s->items[self_item] > 1);
|
||||
/* If this kernel item is next to the beginning of the RHS,
|
||||
then check all of the predecessor's goto follows for the
|
||||
LHS. */
|
||||
if (item_number_is_rule_number (ritem[s->items[self_item]
|
||||
- 2]))
|
||||
{
|
||||
int rulei;
|
||||
for (rulei = s->items[self_item];
|
||||
!item_number_is_rule_number (ritem[rulei]);
|
||||
++rulei)
|
||||
continue;
|
||||
Sbitset items;
|
||||
if (AnnotationList__compute_lhs_contributions (
|
||||
*predecessor,
|
||||
&rules[item_number_as_rule_number (ritem[rulei])],
|
||||
contribution_token,
|
||||
follow_kernel_items, always_follows, predecessors,
|
||||
item_lookahead_sets, &items, annotations_obstackp))
|
||||
{
|
||||
obstack_free (annotations_obstackp,
|
||||
annotation_node->contributions[ci]);
|
||||
annotation_node->contributions[ci] = NULL;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Sbitset__or (annotation_node->contributions[ci],
|
||||
annotation_node->contributions[ci],
|
||||
items, (*predecessor)->nitems);
|
||||
obstack_free (annotations_obstackp, items);
|
||||
}
|
||||
}
|
||||
/* If this kernel item is later in the RHS, then check the
|
||||
predecessor item's lookahead set. */
|
||||
else
|
||||
{
|
||||
/* We don't have to start the predecessor item search at
|
||||
the beginning every time because items from both
|
||||
states are sorted by their indices in ritem. */
|
||||
for (;
|
||||
predecessor_item < (*predecessor)->nitems;
|
||||
++predecessor_item)
|
||||
if ((*predecessor)->items[predecessor_item]
|
||||
== s->items[self_item] - 1)
|
||||
break;
|
||||
aver (predecessor_item != (*predecessor)->nitems);
|
||||
if (ielr_item_has_lookahead (*predecessor, 0,
|
||||
predecessor_item,
|
||||
contribution_token,
|
||||
predecessors,
|
||||
item_lookahead_sets))
|
||||
Sbitset__set (annotation_node->contributions[ci],
|
||||
predecessor_item);
|
||||
}
|
||||
}
|
||||
annotation_node->contributions[ci] = NULL;
|
||||
continue;
|
||||
}
|
||||
if (annotation_node->contributions[ci])
|
||||
annotation_node->contributions[ci] =
|
||||
Sbitset__new_on_obstack ((*predecessor)->nitems,
|
||||
annotations_obstackp);
|
||||
{
|
||||
size_t predecessor_item = 0;
|
||||
Sbitset sbiter_item;
|
||||
Sbitset__Index self_item;
|
||||
SBITSET__FOR_EACH (self->contributions[ci], s->nitems,
|
||||
sbiter_item, self_item)
|
||||
{
|
||||
Sbitset biter;
|
||||
Sbitset__Index i;
|
||||
SBITSET__FOR_EACH (annotation_node->contributions[ci],
|
||||
(*predecessor)->nitems, biter, i)
|
||||
/* If this kernel item is the beginning of a RHS, it must be
|
||||
the kernel item in the start state, and so it has an empty
|
||||
lookahead set. Thus, it can't contribute to inadequacies,
|
||||
and so it should never have been identified as a
|
||||
contribution. If, instead, this kernel item is the
|
||||
successor of the start state's kernel item, the lookahead
|
||||
set is still empty, and so it also should never have been
|
||||
identified as a contribution. This situation is fortunate
|
||||
because we want to avoid the - 2 below in both cases. */
|
||||
aver (s->items[self_item] > 1);
|
||||
/* If this kernel item is next to the beginning of the RHS,
|
||||
then check all of the predecessor's goto follows for the
|
||||
LHS. */
|
||||
if (item_number_is_rule_number (ritem[s->items[self_item] - 2]))
|
||||
{
|
||||
potential_contribution = true;
|
||||
if (!lookaheads)
|
||||
Sbitset items;
|
||||
if (AnnotationList__compute_lhs_contributions (
|
||||
*predecessor,
|
||||
item_rule (&ritem[s->items[self_item]]),
|
||||
contribution_token,
|
||||
follow_kernel_items, always_follows, predecessors,
|
||||
item_lookahead_sets, &items, annotations_obstackp))
|
||||
{
|
||||
lookaheads = xnmalloc ((*predecessor)->nitems,
|
||||
sizeof *lookaheads);
|
||||
for (size_t j = 0; j < (*predecessor)->nitems; ++j)
|
||||
lookaheads[j] = NULL;
|
||||
obstack_free (annotations_obstackp,
|
||||
annotation_node->contributions[ci]);
|
||||
annotation_node->contributions[ci] = NULL;
|
||||
// "Break" out of SBITSET__FOR_EACH.
|
||||
goto after_sbitset__for_each;
|
||||
}
|
||||
if (!lookaheads[i])
|
||||
lookaheads[i] = bitset_create (ntokens, BITSET_FIXED);
|
||||
bitset_set (lookaheads[i], contribution_token);
|
||||
else
|
||||
{
|
||||
Sbitset__or (annotation_node->contributions[ci],
|
||||
annotation_node->contributions[ci],
|
||||
items, (*predecessor)->nitems);
|
||||
obstack_free (annotations_obstackp, items);
|
||||
}
|
||||
}
|
||||
/* If this kernel item is later in the RHS, then check the
|
||||
predecessor item's lookahead set. */
|
||||
else
|
||||
{
|
||||
/* We don't have to start the predecessor item search at
|
||||
the beginning every time because items from both
|
||||
states are sorted by their indices in ritem. */
|
||||
for (;
|
||||
predecessor_item < (*predecessor)->nitems;
|
||||
++predecessor_item)
|
||||
if ((*predecessor)->items[predecessor_item]
|
||||
== s->items[self_item] - 1)
|
||||
break;
|
||||
aver (predecessor_item != (*predecessor)->nitems);
|
||||
if (ielr_item_has_lookahead (*predecessor, 0,
|
||||
predecessor_item,
|
||||
contribution_token,
|
||||
predecessors,
|
||||
item_lookahead_sets))
|
||||
Sbitset__set (annotation_node->contributions[ci],
|
||||
predecessor_item);
|
||||
}
|
||||
}
|
||||
after_sbitset__for_each:;
|
||||
}
|
||||
}
|
||||
if (annotation_node->contributions[ci])
|
||||
{
|
||||
Sbitset biter;
|
||||
Sbitset__Index i;
|
||||
SBITSET__FOR_EACH (annotation_node->contributions[ci],
|
||||
(*predecessor)->nitems, biter, i)
|
||||
{
|
||||
potential_contribution = true;
|
||||
if (!lookaheads)
|
||||
{
|
||||
lookaheads = xnmalloc ((*predecessor)->nitems,
|
||||
sizeof *lookaheads);
|
||||
for (size_t j = 0; j < (*predecessor)->nitems; ++j)
|
||||
lookaheads[j] = NULL;
|
||||
}
|
||||
if (!lookaheads[i])
|
||||
lookaheads[i] = bitset_create (ntokens, BITSET_FIXED);
|
||||
bitset_set (lookaheads[i], contribution_token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If the predecessor has any contributions besides just "always" and
|
||||
"never" contributions:
|
||||
@@ -425,11 +417,7 @@ AnnotationList__compute_from_inadequacies (
|
||||
BITSET_FOR_EACH (biter_conflict, conflicted_tokens, conflicted_token, 0)
|
||||
{
|
||||
AnnotationList *annotation_node;
|
||||
/* FIXME: Would a BITSET_FRUGAL or BITEST_SPARSE be more efficient? Now
|
||||
or convert it inside InadequacyList__new_conflict? */
|
||||
bitset actions = bitset_create (s->reductions->num + 1, BITSET_FIXED);
|
||||
ContributionIndex contribution_count = 0;
|
||||
bool potential_contribution = false;
|
||||
|
||||
/* Allocate the annotation node. */
|
||||
{
|
||||
@@ -444,6 +432,11 @@ AnnotationList__compute_from_inadequacies (
|
||||
annotations_obstackp);
|
||||
}
|
||||
|
||||
/* FIXME: Would a BITSET_FRUGAL or BITEST_SPARSE be more efficient? Now
|
||||
or convert it inside InadequacyList__new_conflict? */
|
||||
bitset actions = bitset_create (s->reductions->num + 1, BITSET_FIXED);
|
||||
bool potential_contribution = false;
|
||||
|
||||
/* Add a contribution for each reduction that has conflicted_token as a
|
||||
lookahead. */
|
||||
{
|
||||
@@ -464,11 +457,8 @@ AnnotationList__compute_from_inadequacies (
|
||||
annotations_obstackp);
|
||||
/* Catch item_i up to rule_i. This works because both are
|
||||
sorted on rule number. */
|
||||
while (!item_number_is_rule_number (
|
||||
ritem[s->items[item_i]])
|
||||
|| item_number_as_rule_number (
|
||||
ritem[s->items[item_i]])
|
||||
!= the_rule->number)
|
||||
while (!item_number_is_rule_number (ritem[s->items[item_i]])
|
||||
|| item_number_as_rule_number (ritem[s->items[item_i]]) != the_rule->number)
|
||||
{
|
||||
++item_i;
|
||||
aver (item_i < s->nitems);
|
||||
@@ -571,44 +561,40 @@ AnnotationList__debug (AnnotationList const *self, size_t nitems, int spaces)
|
||||
AnnotationIndex ai;
|
||||
for (a = self, ai = 0; a; a = a->next, ++ai)
|
||||
{
|
||||
for (int j = 0; j < spaces; ++j)
|
||||
putc (' ', stderr);
|
||||
fprintf (stderr, "Annotation %d (manifesting state %d):\n",
|
||||
fprintf (stderr, "%*sAnnotation %d (manifesting state %d):\n",
|
||||
spaces, "",
|
||||
ai, a->inadequacyNode->manifestingState->number);
|
||||
{
|
||||
bitset_bindex rulei
|
||||
= bitset_first (a->inadequacyNode->inadequacy.conflict.actions);
|
||||
for (ContributionIndex ci = 0; ci < a->inadequacyNode->contributionCount; ++ci)
|
||||
{
|
||||
symbol_number token =
|
||||
InadequacyList__getContributionToken (a->inadequacyNode, ci)
|
||||
->content->number;
|
||||
for (int j = 0; j < spaces+2; ++j)
|
||||
putc (' ', stderr);
|
||||
if (ci == InadequacyList__getShiftContributionIndex (
|
||||
a->inadequacyNode))
|
||||
fprintf (stderr, "Contributes shift of token %d.\n", token);
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "Contributes token %d", token);
|
||||
aver (rulei != BITSET_BINDEX_MAX);
|
||||
fprintf (stderr, " as lookahead, rule number %d",
|
||||
a->inadequacyNode->manifestingState
|
||||
->reductions->rules[rulei]->number);
|
||||
rulei =
|
||||
bitset_next (a->inadequacyNode->inadequacy.conflict.actions,
|
||||
rulei+1);
|
||||
if (AnnotationList__isContributionAlways (a, ci))
|
||||
fprintf (stderr, " always.");
|
||||
else
|
||||
{
|
||||
fprintf (stderr, ", items: ");
|
||||
Sbitset__fprint (a->contributions[ci], nitems, stderr);
|
||||
}
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
bitset_bindex rulei
|
||||
= bitset_first (a->inadequacyNode->inadequacy.conflict.actions);
|
||||
for (ContributionIndex ci = 0; ci < a->inadequacyNode->contributionCount; ++ci)
|
||||
{
|
||||
symbol_number token =
|
||||
InadequacyList__getContributionToken (a->inadequacyNode, ci)
|
||||
->content->number;
|
||||
fprintf (stderr, "%*s", spaces+2, "");
|
||||
if (ci == InadequacyList__getShiftContributionIndex (
|
||||
a->inadequacyNode))
|
||||
fprintf (stderr, "Contributes shift of token %d.\n", token);
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "Contributes token %d", token);
|
||||
aver (rulei != BITSET_BINDEX_MAX);
|
||||
fprintf (stderr, " as lookahead, rule number %d",
|
||||
a->inadequacyNode->manifestingState
|
||||
->reductions->rules[rulei]->number);
|
||||
rulei =
|
||||
bitset_next (a->inadequacyNode->inadequacy.conflict.actions,
|
||||
rulei+1);
|
||||
if (AnnotationList__isContributionAlways (a, ci))
|
||||
fprintf (stderr, " always.");
|
||||
else
|
||||
{
|
||||
fprintf (stderr, ", items: ");
|
||||
Sbitset__fprint (a->contributions[ci], nitems, stderr);
|
||||
}
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -775,8 +761,7 @@ AnnotationList__computeDominantContribution (AnnotationList const *self,
|
||||
/* R/R conflict, so the reduction with the lowest rule number dominates.
|
||||
Fortunately, contributions are sorted by rule number. */
|
||||
for (ContributionIndex ci = 0; ci < self->inadequacyNode->contributionCount; ++ci)
|
||||
if (AnnotationList__stateMakesContribution (self, nitems, ci,
|
||||
lookaheads))
|
||||
if (AnnotationList__stateMakesContribution (self, nitems, ci, lookaheads))
|
||||
{
|
||||
if (require_split_stable
|
||||
&& !AnnotationList__isContributionAlways (self, ci))
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
# define ANNOTATION_LIST_H_
|
||||
|
||||
# include <bitsetv.h>
|
||||
|
||||
# include "Sbitset.h"
|
||||
# include "InadequacyList.h"
|
||||
# include "state.h"
|
||||
|
||||
@@ -81,6 +81,8 @@ void Sbitset__fprint (Sbitset self, Sbitset__Index nbits, FILE *file);
|
||||
*ptr_self = *ptr_other1 | *ptr_other2; \
|
||||
} while (0)
|
||||
|
||||
/* ATTENTION: there are *two* loops here, "break" and "continue" will
|
||||
not apply to the whole loop, just the inner one. */
|
||||
# define SBITSET__FOR_EACH(SELF, NBITS, ITER, INDEX) \
|
||||
for ((ITER) = (SELF); (ITER) < (SELF) + Sbitset__nbytes (NBITS); ++(ITER)) \
|
||||
if (*(ITER) != 0) \
|
||||
|
||||
+20
-20
@@ -32,7 +32,7 @@
|
||||
#include "symtab.h"
|
||||
|
||||
/* NITEMSET is the size of the array ITEMSET. */
|
||||
item_number *itemset;
|
||||
item_index *itemset;
|
||||
size_t nitemset;
|
||||
|
||||
/* RULESET contains a bit for each rule. CLOSURE sets the bits for
|
||||
@@ -54,16 +54,16 @@ static bitsetv firsts = NULL;
|
||||
`-----------------*/
|
||||
|
||||
static void
|
||||
closure_print (char const *title, item_number const *array, size_t size)
|
||||
closure_print (char const *title, item_index const *array, size_t size)
|
||||
{
|
||||
fprintf (stderr, "Closure: %s\n", title);
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
fprintf (stderr, " %2d: .", array[i]);
|
||||
item_number *rp;
|
||||
for (rp = &ritem[array[i]]; *rp >= 0; ++rp)
|
||||
for (rp = &ritem[array[i]]; 0 <= *rp; ++rp)
|
||||
fprintf (stderr, " %s", symbols[*rp]->tag);
|
||||
fprintf (stderr, " (rule %d)\n", -*rp - 1);
|
||||
fprintf (stderr, " (rule %d)\n", item_number_as_rule_number (*rp));
|
||||
}
|
||||
fputs ("\n\n", stderr);
|
||||
}
|
||||
@@ -104,21 +104,21 @@ print_fderives (void)
|
||||
fprintf (stderr, "\n\n");
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------.
|
||||
| Set FIRSTS to be an NVARS array of NVARS bitsets indicating which |
|
||||
| items can represent the beginning of the input corresponding to |
|
||||
| which other items. |
|
||||
| |
|
||||
| For example, if some rule expands symbol 5 into the sequence of |
|
||||
| symbols 8 3 20, the symbol 8 can be the beginning of the data for |
|
||||
| symbol 5, so the bit [8 - ntokens] in first[5 - ntokens] (= FIRST |
|
||||
| (5)) is set. |
|
||||
`------------------------------------------------------------------*/
|
||||
/*-------------------------------------------------------------------.
|
||||
| Set FIRSTS to be an NNTERMS array of NNTERMS bitsets indicating |
|
||||
| which items can represent the beginning of the input corresponding |
|
||||
| to which other items. |
|
||||
| |
|
||||
| For example, if some rule expands symbol 5 into the sequence of |
|
||||
| symbols 8 3 20, the symbol 8 can be the beginning of the data for |
|
||||
| symbol 5, so the bit [8 - ntokens] in first[5 - ntokens] (= FIRST |
|
||||
| (5)) is set. |
|
||||
`-------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
set_firsts (void)
|
||||
{
|
||||
firsts = bitsetv_create (nvars, nvars, BITSET_FIXED);
|
||||
firsts = bitsetv_create (nnterms, nnterms, BITSET_FIXED);
|
||||
|
||||
for (symbol_number i = ntokens; i < nsyms; ++i)
|
||||
for (symbol_number j = 0; derives[i - ntokens][j]; ++j)
|
||||
@@ -139,8 +139,8 @@ set_firsts (void)
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------.
|
||||
| Set FDERIVES to an NVARS by NRULES matrix of bits indicating which |
|
||||
| rules can help derive the beginning of the data for each |
|
||||
| Set FDERIVES to an NNTERMS by NRULES matrix of bits indicating |
|
||||
| which rules can help derive the beginning of the data for each |
|
||||
| nonterminal. |
|
||||
| |
|
||||
| For example, if symbol 5 can be derived as the sequence of symbols |
|
||||
@@ -151,7 +151,7 @@ set_firsts (void)
|
||||
static void
|
||||
set_fderives (void)
|
||||
{
|
||||
fderives = bitsetv_create (nvars, nrules, BITSET_FIXED);
|
||||
fderives = bitsetv_create (nnterms, nrules, BITSET_FIXED);
|
||||
|
||||
set_firsts ();
|
||||
|
||||
@@ -182,7 +182,7 @@ closure_new (int n)
|
||||
|
||||
|
||||
void
|
||||
closure (item_number const *core, size_t n)
|
||||
closure (item_index const *core, size_t n)
|
||||
{
|
||||
if (trace_flag & trace_closure)
|
||||
closure_print ("input", core, n);
|
||||
@@ -203,7 +203,7 @@ closure (item_number const *core, size_t n)
|
||||
bitset_iterator iter;
|
||||
BITSET_FOR_EACH (iter, ruleset, ruleno, 0)
|
||||
{
|
||||
item_number itemno = rules[ruleno].rhs - ritem;
|
||||
item_index itemno = rules[ruleno].rhs - ritem;
|
||||
while (c < n && core[c] < itemno)
|
||||
{
|
||||
itemset[nitemset] = core[c];
|
||||
|
||||
+4
-4
@@ -30,12 +30,12 @@
|
||||
void closure_new (int n);
|
||||
|
||||
|
||||
/* Given the kernel (aka core) of a state (a sorted vector of item numbers
|
||||
/* Given the kernel (aka core) of a state (a sorted vector of item indices
|
||||
ITEMS, of length N), set up RULESET and ITEMSET to indicate what
|
||||
rules could be run and which items could be accepted when those
|
||||
items are the active ones. */
|
||||
|
||||
void closure (item_number const *items, size_t n);
|
||||
void closure (item_index const *items, size_t n);
|
||||
|
||||
|
||||
/* Free ITEMSET, RULESET and internal data. */
|
||||
@@ -43,12 +43,12 @@ void closure (item_number const *items, size_t n);
|
||||
void closure_free (void);
|
||||
|
||||
|
||||
/* ITEMSET is a sorted vector of item numbers; NITEMSET is its size
|
||||
/* ITEMSET is a sorted vector of item indices; NITEMSET is its size
|
||||
(actually, points to just beyond the end of the part of it that is
|
||||
significant). CLOSURE places there the indices of all items which
|
||||
represent units of input that could arrive next. */
|
||||
|
||||
extern item_number *itemset;
|
||||
extern item_index *itemset;
|
||||
extern size_t nitemset;
|
||||
|
||||
#endif /* !CLOSURE_H_ */
|
||||
|
||||
+33
-16
@@ -104,6 +104,23 @@ flush (FILE *out)
|
||||
fflush (out);
|
||||
}
|
||||
|
||||
bool
|
||||
is_styled (FILE *out)
|
||||
{
|
||||
if (out != stderr)
|
||||
return false;
|
||||
if (color_debug)
|
||||
return true;
|
||||
#if HAVE_LIBTEXTSTYLE
|
||||
return (color_mode == color_yes
|
||||
|| color_mode == color_html
|
||||
|| (color_mode == color_tty && isatty (STDERR_FILENO)));
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*------------------------.
|
||||
| --warnings's handling. |
|
||||
`------------------------*/
|
||||
@@ -114,6 +131,7 @@ static const argmatch_warning_doc argmatch_warning_docs[] =
|
||||
{
|
||||
{ "conflicts-sr", N_("S/R conflicts (enabled by default)") },
|
||||
{ "conflicts-rr", N_("R/R conflicts (enabled by default)") },
|
||||
{ "counterexamples", N_("generate conflict counterexamples") },
|
||||
{ "dangling-alias", N_("string aliases not attached to a symbol") },
|
||||
{ "deprecated", N_("obsolete constructs") },
|
||||
{ "empty-rule", N_("empty rules without %empty") },
|
||||
@@ -121,7 +139,7 @@ static const argmatch_warning_doc argmatch_warning_docs[] =
|
||||
{ "precedence", N_("useless precedence and associativity") },
|
||||
{ "yacc", N_("incompatibilities with POSIX Yacc") },
|
||||
{ "other", N_("all other warnings (enabled by default)") },
|
||||
{ "all", N_("all the warnings except 'dangling-alias' and 'yacc'") },
|
||||
{ "all", N_("all the warnings except 'counterexamples', 'dangling-alias' and 'yacc'") },
|
||||
{ "no-CATEGORY", N_("turn off warnings in CATEGORY") },
|
||||
{ "none", N_("turn off all the warnings") },
|
||||
{ "error[=CATEGORY]", N_("treat warnings as errors") },
|
||||
@@ -130,18 +148,19 @@ static const argmatch_warning_doc argmatch_warning_docs[] =
|
||||
|
||||
static const argmatch_warning_arg argmatch_warning_args[] =
|
||||
{
|
||||
{ "all", Wall },
|
||||
{ "conflicts-rr", Wconflicts_rr },
|
||||
{ "conflicts-sr", Wconflicts_sr },
|
||||
{ "dangling-alias", Wdangling_alias },
|
||||
{ "deprecated", Wdeprecated },
|
||||
{ "empty-rule", Wempty_rule },
|
||||
{ "everything", Weverything },
|
||||
{ "midrule-values", Wmidrule_values },
|
||||
{ "none", Wnone },
|
||||
{ "other", Wother },
|
||||
{ "precedence", Wprecedence },
|
||||
{ "yacc", Wyacc },
|
||||
{ "all", Wall },
|
||||
{ "conflicts-rr", Wconflicts_rr },
|
||||
{ "conflicts-sr", Wconflicts_sr },
|
||||
{ "counterexamples", Wcounterexamples }, { "cex", Wcounterexamples }, // Show cex second.
|
||||
{ "dangling-alias", Wdangling_alias },
|
||||
{ "deprecated", Wdeprecated },
|
||||
{ "empty-rule", Wempty_rule },
|
||||
{ "everything", Weverything },
|
||||
{ "midrule-values", Wmidrule_values },
|
||||
{ "none", Wnone },
|
||||
{ "other", Wother },
|
||||
{ "precedence", Wprecedence },
|
||||
{ "yacc", Wyacc },
|
||||
{ NULL, Wnone }
|
||||
};
|
||||
|
||||
@@ -286,9 +305,7 @@ void
|
||||
complain_init_color (void)
|
||||
{
|
||||
#if HAVE_LIBTEXTSTYLE
|
||||
if (color_mode == color_yes
|
||||
|| color_mode == color_html
|
||||
|| (color_mode == color_tty && isatty (STDERR_FILENO)))
|
||||
if (is_styled (stderr))
|
||||
{
|
||||
style_file_prepare ("BISON_STYLE", "BISON_STYLEDIR", pkgdatadir (),
|
||||
"bison-default.css");
|
||||
|
||||
+9
-3
@@ -19,6 +19,8 @@
|
||||
#ifndef COMPLAIN_H_
|
||||
# define COMPLAIN_H_ 1
|
||||
|
||||
# include <attribute.h>
|
||||
|
||||
# include "location.h"
|
||||
|
||||
/*---------------.
|
||||
@@ -34,6 +36,8 @@ void end_use_class (const char *style, FILE *out);
|
||||
/** Flush \a out. */
|
||||
void flush (FILE *out);
|
||||
|
||||
/** Whether there's styling on OUT. */
|
||||
bool is_styled (FILE *out);
|
||||
|
||||
/*-------------.
|
||||
| --warnings. |
|
||||
@@ -44,6 +48,7 @@ typedef enum
|
||||
{
|
||||
warning_conflicts_rr,
|
||||
warning_conflicts_sr,
|
||||
warning_counterexamples,
|
||||
warning_dangling_alias,
|
||||
warning_deprecated,
|
||||
warning_empty_rule,
|
||||
@@ -104,6 +109,7 @@ typedef enum
|
||||
|
||||
Wconflicts_rr = 1 << warning_conflicts_rr,
|
||||
Wconflicts_sr = 1 << warning_conflicts_sr,
|
||||
Wcounterexamples = 1 << warning_counterexamples,
|
||||
Wdangling_alias = 1 << warning_dangling_alias,
|
||||
Wdeprecated = 1 << warning_deprecated,
|
||||
Wempty_rule = 1 << warning_empty_rule,
|
||||
@@ -120,7 +126,7 @@ typedef enum
|
||||
|
||||
/**< All above warnings. */
|
||||
Weverything = ~complaint & ~fatal & ~silent,
|
||||
Wall = Weverything & ~Wdangling_alias & ~Wyacc
|
||||
Wall = Weverything & ~Wcounterexamples & ~Wdangling_alias & ~Wyacc
|
||||
} warnings;
|
||||
|
||||
/** Whether the warnings of \a flags are all unset.
|
||||
@@ -132,7 +138,7 @@ bool warning_is_enabled (warnings flags);
|
||||
|
||||
/** Make a complaint, with maybe a location. */
|
||||
void complain (location const *loc, warnings flags, char const *message, ...)
|
||||
__attribute__ ((__format__ (__printf__, 3, 4)));
|
||||
ATTRIBUTE_FORMAT ((__printf__, 3, 4));
|
||||
|
||||
/** Likewise, but with an \a argc/argv interface. */
|
||||
void complain_args (location const *loc, warnings w,
|
||||
@@ -141,7 +147,7 @@ void complain_args (location const *loc, warnings w,
|
||||
/** Make a subcomplain with location and note. */
|
||||
void subcomplain (location const *loc, warnings flags,
|
||||
char const *message, ...)
|
||||
__attribute__ ((__format__ (__printf__, 3, 4)));
|
||||
ATTRIBUTE_FORMAT ((__printf__, 3, 4));
|
||||
|
||||
|
||||
/** GNU Bison extension not valid with POSIX Yacc. */
|
||||
|
||||
+66
-31
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "complain.h"
|
||||
#include "conflicts.h"
|
||||
#include "counterexample.h"
|
||||
#include "files.h"
|
||||
#include "getargs.h"
|
||||
#include "gram.h"
|
||||
@@ -48,6 +49,12 @@ static struct obstack solved_conflicts_xml_obstack;
|
||||
static bitset shift_set;
|
||||
static bitset lookahead_set;
|
||||
|
||||
bool
|
||||
has_conflicts (const state *s)
|
||||
{
|
||||
return conflicts[s->number];
|
||||
}
|
||||
|
||||
|
||||
|
||||
enum conflict_resolution
|
||||
@@ -219,7 +226,7 @@ log_resolution (rule *r, symbol_number token,
|
||||
|
||||
/*------------------------------------------------------------------.
|
||||
| Turn off the shift recorded for the specified token in the |
|
||||
| specified state. Used when we resolve a shift-reduce conflict in |
|
||||
| specified state. Used when we resolve a shift/reduce conflict in |
|
||||
| favor of the reduction or as an error (%nonassoc). |
|
||||
`------------------------------------------------------------------*/
|
||||
|
||||
@@ -238,7 +245,7 @@ flush_shift (state *s, int token)
|
||||
|
||||
/*--------------------------------------------------------------------.
|
||||
| Turn off the reduce recorded for the specified token in the |
|
||||
| specified lookahead set. Used when we resolve a shift-reduce |
|
||||
| specified lookahead set. Used when we resolve a shift/reduce |
|
||||
| conflict in favor of the shift or as an error (%nonassoc). |
|
||||
`--------------------------------------------------------------------*/
|
||||
|
||||
@@ -250,7 +257,7 @@ flush_reduce (bitset lookahead_tokens, int token)
|
||||
|
||||
|
||||
/*------------------------------------------------------------------.
|
||||
| Attempt to resolve shift-reduce conflict for one rule by means of |
|
||||
| Attempt to resolve shift/reduce conflict for one rule by means of |
|
||||
| precedence declarations. It has already been checked that the |
|
||||
| rule has a precedence. A conflict is resolved by modifying the |
|
||||
| shift or reduce tables so that there is no longer a conflict. |
|
||||
@@ -275,7 +282,7 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
|
||||
&& bitset_test (lookahead_set, i)
|
||||
&& symbols[i]->content->prec)
|
||||
{
|
||||
/* Shift-reduce conflict occurs for token number i
|
||||
/* Shift/reduce conflict occurs for token number i
|
||||
and it has a precedence.
|
||||
The precedence of shifting is that of token i. */
|
||||
if (symbols[i]->content->prec < redprec)
|
||||
@@ -357,10 +364,11 @@ set_conflicts (state *s, symbol **errors)
|
||||
}
|
||||
|
||||
/* Loop over all rules which require lookahead in this state. First
|
||||
check for shift-reduce conflict, and try to resolve using
|
||||
check for shift/reduce conflict, and try to resolve using
|
||||
precedence. */
|
||||
for (int i = 0; i < reds->num; ++i)
|
||||
if (reds->rules[i]->prec && reds->rules[i]->prec->prec
|
||||
if (reds->rules[i]->prec
|
||||
&& reds->rules[i]->prec->prec
|
||||
&& !bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set))
|
||||
resolve_sr_conflict (s, i, errors, &nerrs);
|
||||
|
||||
@@ -624,12 +632,20 @@ conflicts_total_count (void)
|
||||
return count_sr_conflicts () + count_rr_conflicts ();
|
||||
}
|
||||
|
||||
/*------------------------------.
|
||||
| Reporting per-rule conflicts. |
|
||||
`------------------------------*/
|
||||
static void
|
||||
report_counterexamples (void)
|
||||
{
|
||||
for (state_number sn = 0; sn < nstates; ++sn)
|
||||
if (conflicts[sn])
|
||||
counterexample_report_state (states[sn], stderr, "");
|
||||
}
|
||||
|
||||
/*------------------------------------------------.
|
||||
| Report per-rule %expect/%expect-rr mismatches. |
|
||||
`------------------------------------------------*/
|
||||
|
||||
static void
|
||||
rule_conflicts_print (void)
|
||||
report_rule_expectation_mismatches (void)
|
||||
{
|
||||
for (rule_number i = 0; i < nrules; i += 1)
|
||||
{
|
||||
@@ -644,13 +660,13 @@ rule_conflicts_print (void)
|
||||
complain (&r->location, complaint,
|
||||
_("shift/reduce conflicts for rule %d:"
|
||||
" %d found, %d expected"),
|
||||
r->user_number, sr, expected_sr);
|
||||
r->code, sr, expected_sr);
|
||||
int rr = count_rule_rr_conflicts (r);
|
||||
if (rr != expected_rr && (rr != 0 || expected_rr != -1))
|
||||
complain (&r->location, complaint,
|
||||
_("reduce/reduce conflicts for rule %d:"
|
||||
" %d found, %d expected"),
|
||||
r->user_number, rr, expected_rr);
|
||||
r->code, rr, expected_rr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -662,7 +678,7 @@ rule_conflicts_print (void)
|
||||
void
|
||||
conflicts_print (void)
|
||||
{
|
||||
rule_conflicts_print ();
|
||||
report_rule_expectation_mismatches ();
|
||||
|
||||
if (! glr_parser && expected_rr_conflicts != -1)
|
||||
{
|
||||
@@ -670,8 +686,9 @@ conflicts_print (void)
|
||||
expected_rr_conflicts = -1;
|
||||
}
|
||||
|
||||
/* Screams for factoring, but almost useless because of the
|
||||
different strings to translate. */
|
||||
bool has_unexpected_conflicts = false;
|
||||
/* The following two blocks scream for factoring, but i18n support
|
||||
would make it ugly. */
|
||||
{
|
||||
int total = count_sr_conflicts ();
|
||||
/* If %expect is not used, but %expect-rr is, then expect 0 sr. */
|
||||
@@ -682,16 +699,22 @@ conflicts_print (void)
|
||||
if (expected != -1)
|
||||
{
|
||||
if (expected != total)
|
||||
complain (NULL, complaint,
|
||||
_("shift/reduce conflicts: %d found, %d expected"),
|
||||
total, expected);
|
||||
{
|
||||
complain (NULL, complaint,
|
||||
_("shift/reduce conflicts: %d found, %d expected"),
|
||||
total, expected);
|
||||
has_unexpected_conflicts = true;
|
||||
}
|
||||
}
|
||||
else if (total)
|
||||
complain (NULL, Wconflicts_sr,
|
||||
ngettext ("%d shift/reduce conflict",
|
||||
"%d shift/reduce conflicts",
|
||||
total),
|
||||
total);
|
||||
{
|
||||
complain (NULL, Wconflicts_sr,
|
||||
ngettext ("%d shift/reduce conflict",
|
||||
"%d shift/reduce conflicts",
|
||||
total),
|
||||
total);
|
||||
has_unexpected_conflicts = true;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
@@ -704,17 +727,29 @@ conflicts_print (void)
|
||||
if (expected != -1)
|
||||
{
|
||||
if (expected != total)
|
||||
complain (NULL, complaint,
|
||||
_("reduce/reduce conflicts: %d found, %d expected"),
|
||||
total, expected);
|
||||
{
|
||||
complain (NULL, complaint,
|
||||
_("reduce/reduce conflicts: %d found, %d expected"),
|
||||
total, expected);
|
||||
has_unexpected_conflicts = true;
|
||||
}
|
||||
}
|
||||
else if (total)
|
||||
complain (NULL, Wconflicts_rr,
|
||||
ngettext ("%d reduce/reduce conflict",
|
||||
"%d reduce/reduce conflicts",
|
||||
total),
|
||||
total);
|
||||
{
|
||||
complain (NULL, Wconflicts_rr,
|
||||
ngettext ("%d reduce/reduce conflict",
|
||||
"%d reduce/reduce conflicts",
|
||||
total),
|
||||
total);
|
||||
has_unexpected_conflicts = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (warning_is_enabled (Wcounterexamples))
|
||||
report_counterexamples ();
|
||||
else if (has_unexpected_conflicts)
|
||||
complain (NULL, Wother,
|
||||
_("rerun with option '-Wcounterexamples' to generate conflict counterexamples"));
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -41,6 +41,8 @@ int conflicts_total_count (void);
|
||||
void conflicts_output (FILE *out);
|
||||
void conflicts_free (void);
|
||||
|
||||
bool has_conflicts (const state *s);
|
||||
|
||||
/* Were there conflicts? */
|
||||
extern int expected_sr_conflicts;
|
||||
extern int expected_rr_conflicts;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,30 @@
|
||||
/* Conflict counterexample generation
|
||||
|
||||
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Compiler Compiler.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef COUNTEREXAMPLE_H
|
||||
# define COUNTEREXAMPLE_H
|
||||
|
||||
# include "state-item.h"
|
||||
|
||||
void counterexample_init (void);
|
||||
void counterexample_free (void);
|
||||
|
||||
void counterexample_report_state (const state *s, FILE *out, const char *prefix);
|
||||
|
||||
#endif /* COUNTEREXAMPLE_H */
|
||||
@@ -0,0 +1,213 @@
|
||||
/* Counterexample derivation trees
|
||||
|
||||
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Compiler Compiler.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "derivation.h"
|
||||
|
||||
#include <gl_linked_list.h>
|
||||
|
||||
#include "system.h"
|
||||
#include "complain.h"
|
||||
|
||||
struct derivation
|
||||
{
|
||||
symbol_number sym;
|
||||
gl_list_t children;
|
||||
int reference_count;
|
||||
};
|
||||
|
||||
static derivation d_dot = { -1, NULL, -1 };
|
||||
|
||||
derivation *
|
||||
derivation_dot (void)
|
||||
{
|
||||
return &d_dot;
|
||||
}
|
||||
|
||||
void
|
||||
derivation_list_append (derivation_list dl, derivation *d)
|
||||
{
|
||||
derivation_retain (d);
|
||||
gl_list_add_last (dl, d);
|
||||
}
|
||||
|
||||
void
|
||||
derivation_list_prepend (derivation_list dl, derivation *d)
|
||||
{
|
||||
derivation_retain (d);
|
||||
gl_list_add_first (dl, d);
|
||||
}
|
||||
|
||||
void derivation_list_free (derivation_list dl)
|
||||
{
|
||||
derivation *d = NULL;
|
||||
for (gl_list_iterator_t it = gl_list_iterator (dl);
|
||||
derivation_list_next (&it, &d);
|
||||
)
|
||||
if (d != &d_dot)
|
||||
derivation_free (d);
|
||||
gl_list_free (dl);
|
||||
}
|
||||
|
||||
derivation *
|
||||
derivation_new (symbol_number sym, derivation_list children)
|
||||
{
|
||||
derivation *deriv = xmalloc (sizeof (derivation));
|
||||
deriv->sym = sym;
|
||||
deriv->children = children;
|
||||
deriv->reference_count = 0;
|
||||
return deriv;
|
||||
}
|
||||
|
||||
void
|
||||
derivation_retain (derivation *d)
|
||||
{
|
||||
++d->reference_count;
|
||||
}
|
||||
|
||||
void
|
||||
derivation_free (derivation *d)
|
||||
{
|
||||
if (!d)
|
||||
return;
|
||||
derivation_list free_queue =
|
||||
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true,
|
||||
1, (const void **)&d);
|
||||
while (gl_list_size (free_queue) > 0)
|
||||
{
|
||||
derivation *deriv = (derivation *) gl_list_get_at (free_queue, 0);
|
||||
if (--deriv->reference_count == 0)
|
||||
{
|
||||
if (deriv->children)
|
||||
{
|
||||
derivation *child = NULL;
|
||||
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
|
||||
derivation_list_next (&it, &child);
|
||||
)
|
||||
if (child != &d_dot)
|
||||
gl_list_add_last (free_queue, child);
|
||||
gl_list_free (deriv->children);
|
||||
}
|
||||
free (deriv);
|
||||
}
|
||||
gl_list_remove_at (free_queue, 0);
|
||||
}
|
||||
gl_list_free (free_queue);
|
||||
}
|
||||
|
||||
size_t
|
||||
derivation_size (const derivation *deriv)
|
||||
{
|
||||
if (!deriv->children)
|
||||
return 1;
|
||||
int size = 1;
|
||||
derivation *child = NULL;
|
||||
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
|
||||
derivation_list_next (&it, &child);
|
||||
)
|
||||
size += derivation_size (child);
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Print DERIV, colored according to COUNTER.
|
||||
Return false if nothing is printed. */
|
||||
static bool
|
||||
derivation_print_impl (const derivation *deriv, FILE *f,
|
||||
bool leaves_only,
|
||||
int *counter, const char *prefix)
|
||||
{
|
||||
if (deriv->children)
|
||||
{
|
||||
const symbol *sym = symbols[deriv->sym];
|
||||
char style[20];
|
||||
snprintf (style, 20, "cex-%d", *counter);
|
||||
++*counter;
|
||||
begin_use_class (style, f);
|
||||
|
||||
if (!leaves_only)
|
||||
{
|
||||
fputs (prefix, f);
|
||||
begin_use_class ("cex-step", f);
|
||||
fprintf (f, "%s ::=[ ", sym->tag);
|
||||
end_use_class ("cex-step", f);
|
||||
prefix = "";
|
||||
}
|
||||
bool res = false;
|
||||
derivation *child;
|
||||
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
|
||||
derivation_list_next (&it, &child);
|
||||
)
|
||||
{
|
||||
if (derivation_print_impl (child, f, leaves_only, counter, prefix))
|
||||
{
|
||||
prefix = " ";
|
||||
res = true;
|
||||
}
|
||||
else if (!leaves_only)
|
||||
prefix = " ";
|
||||
}
|
||||
if (!leaves_only)
|
||||
{
|
||||
begin_use_class ("cex-step", f);
|
||||
if (res)
|
||||
fputs (" ]", f);
|
||||
else
|
||||
fputs ("]", f);
|
||||
end_use_class ("cex-step", f);
|
||||
}
|
||||
end_use_class (style, f);
|
||||
return res;
|
||||
}
|
||||
else if (deriv == &d_dot)
|
||||
{
|
||||
fputs (prefix, f);
|
||||
begin_use_class ("cex-dot", f);
|
||||
print_dot (f);
|
||||
end_use_class ("cex-dot", f);
|
||||
}
|
||||
else // leaf.
|
||||
{
|
||||
fputs (prefix, f);
|
||||
const symbol *sym = symbols[deriv->sym];
|
||||
begin_use_class ("cex-leaf", f);
|
||||
fprintf (f, "%s", sym->tag);
|
||||
end_use_class ("cex-leaf", f);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
derivation_print (const derivation *deriv, FILE *out, const char *prefix)
|
||||
{
|
||||
int counter = 0;
|
||||
fputs (prefix, out);
|
||||
derivation_print_impl (deriv, out, false, &counter, "");
|
||||
fputc ('\n', out);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
derivation_print_leaves (const derivation *deriv, FILE *out, const char *prefix)
|
||||
{
|
||||
int counter = 0;
|
||||
fputs (prefix, out);
|
||||
derivation_print_impl (deriv, out, true, &counter, "");
|
||||
fputc ('\n', out);
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/* Counterexample derivation trees
|
||||
|
||||
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Compiler Compiler.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef DERIVATION_H
|
||||
# define DERIVATION_H
|
||||
|
||||
# include <gl_linked_list.h>
|
||||
# include <gl_xlist.h>
|
||||
|
||||
# include "gram.h"
|
||||
|
||||
/* Derivations are trees of symbols such that each nonterminal's
|
||||
children are symbols that produce that nonterminal if they are
|
||||
relevant to the counterexample. The leaves of a derivation form a
|
||||
counterexample when printed. */
|
||||
|
||||
typedef gl_list_t derivation_list;
|
||||
typedef struct derivation derivation;
|
||||
|
||||
static inline derivation_list derivation_list_new (void)
|
||||
{
|
||||
return gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
derivation_list_next (gl_list_iterator_t *it, derivation **d)
|
||||
{
|
||||
const void *p = NULL;
|
||||
bool res = gl_list_iterator_next (it, &p, NULL);
|
||||
if (res)
|
||||
*d = (derivation *) p;
|
||||
else
|
||||
gl_list_iterator_free (it);
|
||||
return res;
|
||||
}
|
||||
|
||||
void derivation_list_append (derivation_list dl, derivation *d);
|
||||
void derivation_list_prepend (derivation_list dl, derivation *d);
|
||||
void derivation_list_free (derivation_list dl);
|
||||
|
||||
derivation *derivation_new (symbol_number sym, derivation_list children);
|
||||
|
||||
static inline derivation *derivation_new_leaf (symbol_number sym)
|
||||
{
|
||||
return derivation_new (sym, NULL);
|
||||
}
|
||||
size_t derivation_size (const derivation *deriv);
|
||||
void derivation_print (const derivation *deriv, FILE *out, const char *prefix);
|
||||
void derivation_print_leaves (const derivation *deriv, FILE *out, const char *prefix);
|
||||
void derivation_free (derivation *deriv);
|
||||
void derivation_retain (derivation *deriv);
|
||||
|
||||
derivation *derivation_dot (void);
|
||||
|
||||
#endif /* DERIVATION_H */
|
||||
+4
-4
@@ -47,7 +47,7 @@ print_derives (void)
|
||||
fprintf (stderr, " %s derives\n", symbols[i]->tag);
|
||||
for (rule **rp = derives[i - ntokens]; *rp; ++rp)
|
||||
{
|
||||
fprintf (stderr, " %3d ", (*rp)->user_number);
|
||||
fprintf (stderr, " %3d ", (*rp)->code);
|
||||
rule_rhs_print (*rp, stderr);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
@@ -62,7 +62,7 @@ derives_compute (void)
|
||||
{
|
||||
/* DSET[NTERM - NTOKENS] -- A linked list of the numbers of the rules
|
||||
whose LHS is NTERM. */
|
||||
rule_list **dset = xcalloc (nvars, sizeof *dset);
|
||||
rule_list **dset = xcalloc (nnterms, sizeof *dset);
|
||||
|
||||
/* DELTS[RULE] -- There are NRULES rule number to attach to nterms.
|
||||
Instead of performing NRULES allocations for each, have an array
|
||||
@@ -82,9 +82,9 @@ derives_compute (void)
|
||||
/* DSET contains what we need under the form of a linked list. Make
|
||||
it a single array. */
|
||||
|
||||
derives = xnmalloc (nvars, sizeof *derives);
|
||||
derives = xnmalloc (nnterms, sizeof *derives);
|
||||
/* Q is the storage for DERIVES[...] (DERIVES[0] = q). */
|
||||
rule **q = xnmalloc (nvars + nrules, sizeof *q);
|
||||
rule **q = xnmalloc (nnterms + nrules, sizeof *q);
|
||||
|
||||
for (symbol_number i = ntokens; i < nsyms; ++i)
|
||||
{
|
||||
|
||||
+106
-2
@@ -22,13 +22,18 @@
|
||||
#include "system.h"
|
||||
|
||||
#include <configmake.h> /* PKGDATADIR */
|
||||
#include <error.h>
|
||||
#include <dirname.h>
|
||||
#include <error.h>
|
||||
#include <get-errno.h>
|
||||
#include <gl_array_list.h>
|
||||
#include <gl_xlist.h>
|
||||
#include <quote.h>
|
||||
#include <quotearg.h>
|
||||
#include <relocatable.h> /* relocate2 */
|
||||
#include <stdio-safer.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <xstrndup.h>
|
||||
|
||||
#include "complain.h"
|
||||
@@ -52,6 +57,7 @@ char *spec_verbose_file = NULL; /* for --verbose. */
|
||||
char *spec_graph_file = NULL; /* for -g. */
|
||||
char *spec_xml_file = NULL; /* for -x. */
|
||||
char *spec_header_file = NULL; /* for --defines. */
|
||||
char *spec_mapped_header_file = NULL;
|
||||
char *parser_file_name;
|
||||
|
||||
/* All computed output file names. */
|
||||
@@ -70,7 +76,7 @@ static int generated_files_size = 0;
|
||||
uniqstr grammar_file = NULL;
|
||||
|
||||
/* If --output=dir/foo.c was specified,
|
||||
DIR_PREFIX is 'dir/' and ALL_BUT_EXT and ALL_BUT_TAB_EXT are 'dir/foo'.
|
||||
DIR_PREFIX gis 'dir/' and ALL_BUT_EXT and ALL_BUT_TAB_EXT are 'dir/foo'.
|
||||
|
||||
If --output=dir/foo.tab.c was specified, DIR_PREFIX is 'dir/',
|
||||
ALL_BUT_EXT is 'dir/foo.tab', and ALL_BUT_TAB_EXT is 'dir/foo'.
|
||||
@@ -88,11 +94,20 @@ uniqstr grammar_file = NULL;
|
||||
char *all_but_ext;
|
||||
static char *all_but_tab_ext;
|
||||
char *dir_prefix;
|
||||
char *mapped_dir_prefix;
|
||||
|
||||
/* C source file extension (the parser source). */
|
||||
static char *src_extension = NULL;
|
||||
/* Header file extension (if option '`-d'' is specified). */
|
||||
static char *header_extension = NULL;
|
||||
|
||||
struct prefix_map
|
||||
{
|
||||
char *oldprefix;
|
||||
char *newprefix;
|
||||
};
|
||||
|
||||
static gl_list_t prefix_maps = NULL;
|
||||
|
||||
/*-----------------------------------------------------------------.
|
||||
| Return a newly allocated string composed of the concatenation of |
|
||||
@@ -156,6 +171,70 @@ xfdopen (int fd, char const *mode)
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Given an input file path, returns a dynamically allocated string that
|
||||
contains the path with the file prefix mapping rules applied, or NULL if
|
||||
the input was NULL. */
|
||||
char *
|
||||
map_file_name (char const *filename)
|
||||
{
|
||||
if (!filename)
|
||||
return NULL;
|
||||
|
||||
struct prefix_map const *p = NULL;
|
||||
if (prefix_maps)
|
||||
{
|
||||
void const *ptr;
|
||||
gl_list_iterator_t iter = gl_list_iterator (prefix_maps);
|
||||
while (gl_list_iterator_next (&iter, &ptr, NULL))
|
||||
{
|
||||
p = ptr;
|
||||
if (strncmp (p->oldprefix, filename, strlen (p->oldprefix)) == 0)
|
||||
break;
|
||||
p = NULL;
|
||||
}
|
||||
gl_list_iterator_free (&iter);
|
||||
}
|
||||
|
||||
if (!p)
|
||||
return xstrdup (filename);
|
||||
|
||||
size_t oldprefix_len = strlen (p->oldprefix);
|
||||
size_t newprefix_len = strlen (p->newprefix);
|
||||
char *s = xmalloc (newprefix_len + strlen (filename) - oldprefix_len + 1);
|
||||
|
||||
char *end = stpcpy (s, p->newprefix);
|
||||
stpcpy (end, filename + oldprefix_len);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static void
|
||||
prefix_map_free (struct prefix_map *p)
|
||||
{
|
||||
free (p->oldprefix);
|
||||
free (p->newprefix);
|
||||
free (p);
|
||||
}
|
||||
|
||||
/* Adds a new file prefix mapping. If a file path starts with oldprefix, it
|
||||
will be replaced with newprefix */
|
||||
void
|
||||
add_prefix_map (char const *oldprefix, char const *newprefix)
|
||||
{
|
||||
if (!prefix_maps)
|
||||
prefix_maps = gl_list_create_empty (GL_ARRAY_LIST,
|
||||
/* equals */ NULL,
|
||||
/* hashcode */ NULL,
|
||||
(gl_listelement_dispose_fn) prefix_map_free,
|
||||
true);
|
||||
|
||||
struct prefix_map *p = xmalloc (sizeof (*p));
|
||||
p->oldprefix = xstrdup (oldprefix);
|
||||
p->newprefix = xstrdup (newprefix);
|
||||
|
||||
gl_list_add_last (prefix_maps, p);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------.
|
||||
| Compute ALL_BUT_EXT, ALL_BUT_TAB_EXT and output files extensions. |
|
||||
`------------------------------------------------------------------*/
|
||||
@@ -360,6 +439,9 @@ compute_output_file_names (void)
|
||||
output_file_name_check (&spec_verbose_file, false);
|
||||
}
|
||||
|
||||
spec_mapped_header_file = map_file_name (spec_header_file);
|
||||
mapped_dir_prefix = map_file_name (dir_prefix);
|
||||
|
||||
free (all_but_tab_ext);
|
||||
free (src_extension);
|
||||
free (header_extension);
|
||||
@@ -421,6 +503,23 @@ pkgdatadir (void)
|
||||
}
|
||||
}
|
||||
|
||||
char const *
|
||||
m4path (void)
|
||||
{
|
||||
char const *m4 = getenv ("M4");
|
||||
if (m4)
|
||||
return m4;
|
||||
|
||||
/* We don't use relocate2() to store the temporary buffer and re-use
|
||||
it, because m4path() is only called once. */
|
||||
char const *m4_relocated = relocate (M4);
|
||||
struct stat buf;
|
||||
if (stat (m4_relocated, &buf) == 0)
|
||||
return m4_relocated;
|
||||
|
||||
return M4;
|
||||
}
|
||||
|
||||
void
|
||||
output_file_names_free (void)
|
||||
{
|
||||
@@ -429,10 +528,15 @@ output_file_names_free (void)
|
||||
free (spec_graph_file);
|
||||
free (spec_xml_file);
|
||||
free (spec_header_file);
|
||||
free (spec_mapped_header_file);
|
||||
free (parser_file_name);
|
||||
free (dir_prefix);
|
||||
free (mapped_dir_prefix);
|
||||
for (int i = 0; i < generated_files_size; i++)
|
||||
free (generated_files[i].name);
|
||||
free (generated_files);
|
||||
free (relocate_buffer);
|
||||
|
||||
if (prefix_maps)
|
||||
gl_list_free (prefix_maps);
|
||||
}
|
||||
|
||||
+12
@@ -50,9 +50,15 @@ extern char *spec_xml_file;
|
||||
/* File name specified with --defines. */
|
||||
extern char *spec_header_file;
|
||||
|
||||
/* File name specified with --defines, adjusted for mapped prefixes. */
|
||||
extern char *spec_mapped_header_file;
|
||||
|
||||
/* Directory prefix of output file names. */
|
||||
extern char *dir_prefix;
|
||||
|
||||
/* Directory prefix of output file name, adjusted for mapped prefixes. */
|
||||
extern char *mapped_dir_prefix;
|
||||
|
||||
/* The file name as given on the command line.
|
||||
Not named "input_file" because Flex uses this name for an argument,
|
||||
and therefore GCC warns about a name clash. */
|
||||
@@ -64,6 +70,9 @@ extern char *all_but_ext;
|
||||
/* Where our data files are installed. */
|
||||
char const *pkgdatadir (void);
|
||||
|
||||
/* Where the m4 program is installed. */
|
||||
char const *m4path (void);
|
||||
|
||||
void compute_output_file_names (void);
|
||||
void output_file_names_free (void);
|
||||
|
||||
@@ -82,4 +91,7 @@ FILE *xfopen (const char *name, char const *mode);
|
||||
void xfclose (FILE *ptr);
|
||||
FILE *xfdopen (int fd, char const *mode);
|
||||
|
||||
char *map_file_name (char const *filename);
|
||||
void add_prefix_map (char const *oldprefix, char const *newprefix);
|
||||
|
||||
#endif /* !FILES_H_ */
|
||||
|
||||
+10
-10
@@ -21,19 +21,19 @@
|
||||
|
||||
#include "fixits.h"
|
||||
|
||||
#include <error.h>
|
||||
#include <get-errno.h>
|
||||
#include <gl_array_list.h>
|
||||
#include <gl_xlist.h>
|
||||
#include <progname.h>
|
||||
#include <quote.h>
|
||||
#include <quotearg.h>
|
||||
#include <vasnprintf.h>
|
||||
|
||||
#include "system.h"
|
||||
|
||||
#include "error.h"
|
||||
#include "get-errno.h"
|
||||
#include "getargs.h"
|
||||
#include "gl_array_list.h"
|
||||
#include "gl_xlist.h"
|
||||
#include "progname.h"
|
||||
#include "quote.h"
|
||||
#include "quotearg.h"
|
||||
#include "vasnprintf.h"
|
||||
|
||||
#include "files.h"
|
||||
#include "getargs.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
||||
+10
-7
@@ -94,22 +94,25 @@ int FLEX_PREFIX (lex_destroy) (void);
|
||||
keep (to construct ID, STRINGS etc.). Use the following macros to
|
||||
use it.
|
||||
|
||||
Use STRING_GROW to append what has just been matched, and
|
||||
STRING_FINISH to end the string (it puts the ending 0).
|
||||
STRING_FINISH also stores this string in LAST_STRING, which can be
|
||||
used, and which is used by STRING_FREE to free the last string. */
|
||||
Use STRING_GROW () to append what has just been matched, and
|
||||
STRING_FINISH () to end the string (it puts the ending 0).
|
||||
STRING_FINISH () also stores this string in LAST_STRING, which can be
|
||||
used, and which is used by STRING_FREE () to free the last string. */
|
||||
|
||||
#ifndef FLEX_NO_OBSTACK
|
||||
|
||||
static struct obstack obstack_for_string;
|
||||
|
||||
# define STRING_GROW \
|
||||
# define STRING_GROW() \
|
||||
obstack_grow (&obstack_for_string, yytext, yyleng)
|
||||
|
||||
# define STRING_FINISH \
|
||||
# define STRING_FINISH() \
|
||||
(last_string = obstack_finish0 (&obstack_for_string))
|
||||
|
||||
# define STRING_FREE \
|
||||
# define STRING_1GROW(Char) \
|
||||
obstack_1grow (&obstack_for_string, Char)
|
||||
|
||||
# define STRING_FREE() \
|
||||
obstack_free (&obstack_for_string, last_string)
|
||||
|
||||
#endif
|
||||
|
||||
+62
-34
@@ -151,8 +151,8 @@ flags_argmatch (const char *opt,
|
||||
*/
|
||||
#define FLAGS_ARGMATCH(FlagName, Args, All) \
|
||||
flags_argmatch ("--" #FlagName, \
|
||||
(xargmatch_fn*) argmatch_## FlagName ## _value, \
|
||||
argmatch_## FlagName ## _usage, \
|
||||
(xargmatch_fn*) argmatch_## FlagName ## _value, \
|
||||
argmatch_ ## FlagName ## _usage, \
|
||||
All, &FlagName ## _flag, Args)
|
||||
|
||||
/*---------------------.
|
||||
@@ -206,23 +206,26 @@ ARGMATCH_DEFINE_GROUP (report, enum report)
|
||||
|
||||
static const argmatch_report_doc argmatch_report_docs[] =
|
||||
{
|
||||
{ "states", N_("describe the states") },
|
||||
{ "itemsets", N_("complete the core item sets with their closure") },
|
||||
{ "lookaheads", N_("explicitly associate lookahead tokens to items") },
|
||||
{ "solved", N_("describe shift/reduce conflicts solving") },
|
||||
{ "all", N_("include all the above information") },
|
||||
{ "none", N_("disable the report") },
|
||||
{ "states", N_("describe the states") },
|
||||
{ "itemsets", N_("complete the core item sets with their closure") },
|
||||
{ "lookaheads", N_("explicitly associate lookahead tokens to items") },
|
||||
{ "solved", N_("describe shift/reduce conflicts solving") },
|
||||
{ "counterexamples", N_("generate conflict counterexamples") },
|
||||
{ "all", N_("include all the above information") },
|
||||
{ "none", N_("disable the report") },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
static const argmatch_report_arg argmatch_report_args[] =
|
||||
{
|
||||
{ "none", report_none },
|
||||
{ "states", report_states },
|
||||
{ "itemsets", report_states | report_itemsets },
|
||||
{ "lookaheads", report_states | report_lookahead_tokens },
|
||||
{ "solved", report_states | report_solved_conflicts },
|
||||
{ "all", report_all },
|
||||
{ "none", report_none },
|
||||
{ "states", report_states },
|
||||
{ "itemsets", report_states | report_itemsets },
|
||||
{ "lookaheads", report_states | report_lookahead_tokens },
|
||||
{ "solved", report_states | report_solved_conflicts },
|
||||
{ "counterexamples", report_cex },
|
||||
{ "cex", report_cex },
|
||||
{ "all", report_all },
|
||||
{ NULL, report_none },
|
||||
};
|
||||
|
||||
@@ -257,10 +260,12 @@ static const argmatch_trace_doc argmatch_trace_docs[] =
|
||||
{ "sets", "grammar sets: firsts, nullable etc." },
|
||||
{ "muscles", "m4 definitions passed to the skeleton" },
|
||||
{ "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" },
|
||||
{ "time", "time consumption" },
|
||||
{ "ielr", "IELR conversion" },
|
||||
{ "cex", "counterexample generation"},
|
||||
{ "all", "all of the above" },
|
||||
{ NULL, NULL},
|
||||
};
|
||||
@@ -279,10 +284,12 @@ static const argmatch_trace_arg argmatch_trace_args[] =
|
||||
{ "sets", trace_sets },
|
||||
{ "muscles", trace_muscles },
|
||||
{ "tools", trace_tools },
|
||||
{ "m4-early", trace_m4_early },
|
||||
{ "m4", trace_m4 },
|
||||
{ "skeleton", trace_skeleton },
|
||||
{ "time", trace_time },
|
||||
{ "ielr", trace_ielr },
|
||||
{ "cex", trace_cex },
|
||||
{ "all", trace_all },
|
||||
{ NULL, trace_none},
|
||||
};
|
||||
@@ -337,7 +344,8 @@ const argmatch_feature_group_type argmatch_feature_group =
|
||||
| Display the help message and exit STATUS. |
|
||||
`-------------------------------------------*/
|
||||
|
||||
static void usage (int) ATTRIBUTE_NORETURN;
|
||||
_Noreturn
|
||||
static void usage (int);
|
||||
|
||||
static void
|
||||
usage (int status)
|
||||
@@ -418,15 +426,17 @@ Tuning the Parser:\n\
|
||||
* won't assume that -d also takes an argument. */
|
||||
fputs (_("\
|
||||
Output Files:\n\
|
||||
--defines[=FILE] also produce a header file\n\
|
||||
-d likewise but cannot specify FILE (for POSIX Yacc)\n\
|
||||
-r, --report=THINGS also produce details on the automaton\n\
|
||||
--report-file=FILE write report to FILE\n\
|
||||
-v, --verbose same as '--report=state'\n\
|
||||
-b, --file-prefix=PREFIX specify a PREFIX for output files\n\
|
||||
-o, --output=FILE leave output to FILE\n\
|
||||
-g, --graph[=FILE] also output a graph of the automaton\n\
|
||||
-x, --xml[=FILE] also output an XML report of the automaton\n\
|
||||
--defines[=FILE] also produce a header file\n\
|
||||
-d likewise but cannot specify FILE (for POSIX Yacc)\n\
|
||||
-r, --report=THINGS also produce details on the automaton\n\
|
||||
--report-file=FILE write report to FILE\n\
|
||||
-v, --verbose same as '--report=state'\n\
|
||||
-b, --file-prefix=PREFIX specify a PREFIX for output files\n\
|
||||
-o, --output=FILE leave output to FILE\n\
|
||||
-g, --graph[=FILE] also output a graph of the automaton\n\
|
||||
-x, --xml[=FILE] also output an XML report of the automaton\n\
|
||||
-M, --file-prefix-map=OLD=NEW replace prefix OLD with NEW when writing file paths\n\
|
||||
in output files\n\
|
||||
"), stdout);
|
||||
putc ('\n', stdout);
|
||||
|
||||
@@ -547,6 +557,7 @@ static char const short_options[] =
|
||||
"h"
|
||||
"k"
|
||||
"l"
|
||||
"M:"
|
||||
"o:"
|
||||
"p:"
|
||||
"r:"
|
||||
@@ -598,14 +609,15 @@ static struct option const long_options[] =
|
||||
{ "yacc", no_argument, 0, 'y' },
|
||||
|
||||
/* Output Files. */
|
||||
{ "defines", optional_argument, 0, 'd' },
|
||||
{ "report", required_argument, 0, 'r' },
|
||||
{ "report-file", required_argument, 0, REPORT_FILE_OPTION },
|
||||
{ "verbose", no_argument, 0, 'v' },
|
||||
{ "file-prefix", required_argument, 0, 'b' },
|
||||
{ "output", required_argument, 0, 'o' },
|
||||
{ "graph", optional_argument, 0, 'g' },
|
||||
{ "xml", optional_argument, 0, 'x' },
|
||||
{ "defines", optional_argument, 0, 'd' },
|
||||
{ "report", required_argument, 0, 'r' },
|
||||
{ "report-file", required_argument, 0, REPORT_FILE_OPTION },
|
||||
{ "verbose", no_argument, 0, 'v' },
|
||||
{ "file-prefix", required_argument, 0, 'b' },
|
||||
{ "output", required_argument, 0, 'o' },
|
||||
{ "graph", optional_argument, 0, 'g' },
|
||||
{ "xml", optional_argument, 0, 'x' },
|
||||
{ "file-prefix-map", required_argument, 0, 'M' },
|
||||
|
||||
/* Hidden. */
|
||||
{ "fixed-output-files", no_argument, 0, FIXED_OUTPUT_FILES_OPTION },
|
||||
@@ -711,6 +723,22 @@ getargs (int argc, char *argv[])
|
||||
language_argmatch (optarg, command_line_prio, loc);
|
||||
break;
|
||||
|
||||
case 'M': // -MOLDPREFIX=NEWPREFIX
|
||||
{
|
||||
char *newprefix = strchr (optarg, '=');
|
||||
if (newprefix)
|
||||
{
|
||||
*newprefix = '\0';
|
||||
add_prefix_map (optarg, newprefix + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
complain (&loc, complaint, _("invalid argument for %s: %s"),
|
||||
quote ("--file-prefix-map"), quotearg_n (1, optarg));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
skeleton_arg (optarg, command_line_prio, loc);
|
||||
break;
|
||||
@@ -860,7 +888,7 @@ getargs (int argc, char *argv[])
|
||||
void
|
||||
tr (char *s, char from, char to)
|
||||
{
|
||||
for (; *s; s++)
|
||||
for (; *s; ++s)
|
||||
if (*s == from)
|
||||
*s = to;
|
||||
}
|
||||
|
||||
+8
-5
@@ -79,6 +79,7 @@ enum report
|
||||
report_itemsets = 1 << 1,
|
||||
report_lookahead_tokens = 1 << 2,
|
||||
report_solved_conflicts = 1 << 3,
|
||||
report_cex = 1 << 4,
|
||||
report_all = ~0
|
||||
};
|
||||
/** What appears in the *.output file. */
|
||||
@@ -100,11 +101,13 @@ enum trace
|
||||
trace_grammar = 1 << 7, /**< Reading, reducing the grammar. */
|
||||
trace_time = 1 << 8, /**< Time consumption. */
|
||||
trace_skeleton = 1 << 9, /**< Skeleton postprocessing. */
|
||||
trace_m4 = 1 << 10, /**< M4 traces. */
|
||||
trace_muscles = 1 << 11, /**< M4 definitions of the muscles. */
|
||||
trace_ielr = 1 << 12, /**< IELR conversion. */
|
||||
trace_closure = 1 << 13, /**< Input/output of closure(). */
|
||||
trace_locations = 1 << 14, /**< Full display of locations. */
|
||||
trace_m4_early = 1 << 10, /**< M4 early traces. */
|
||||
trace_m4 = 1 << 11, /**< M4 traces. */
|
||||
trace_muscles = 1 << 12, /**< M4 definitions of the muscles. */
|
||||
trace_ielr = 1 << 13, /**< IELR conversion. */
|
||||
trace_closure = 1 << 14, /**< Input/output of closure(). */
|
||||
trace_locations = 1 << 15, /**< Full display of locations. */
|
||||
trace_cex = 1 << 16, /**< Counterexample generation */
|
||||
trace_all = ~0 /**< All of the above. */
|
||||
};
|
||||
/** What debug items bison displays during its run. */
|
||||
|
||||
+24
-24
@@ -40,25 +40,14 @@ rule_number nrules = 0;
|
||||
symbol **symbols = NULL;
|
||||
int nsyms = 0;
|
||||
int ntokens = 1;
|
||||
int nvars = 0;
|
||||
int nnterms = 0;
|
||||
|
||||
symbol_number *token_translations = NULL;
|
||||
|
||||
int max_user_token_number = 256;
|
||||
int max_code = 256;
|
||||
|
||||
int required_version = 0;
|
||||
|
||||
rule const *
|
||||
item_rule (item_number const *item)
|
||||
{
|
||||
item_number const *sp = item;
|
||||
while (0 <= *sp)
|
||||
++sp;
|
||||
rule_number r = item_number_as_rule_number (*sp);
|
||||
return &rules[r];
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
item_print (item_number *item, rule const *previous_rule, FILE *out)
|
||||
{
|
||||
@@ -67,7 +56,8 @@ item_print (item_number *item, rule const *previous_rule, FILE *out)
|
||||
|
||||
for (item_number *sp = r->rhs; sp < item; sp++)
|
||||
fprintf (out, " %s", symbols[*sp]->tag);
|
||||
fputs (" .", out);
|
||||
putc (' ', out);
|
||||
print_dot (out);
|
||||
if (0 <= *r->rhs)
|
||||
for (item_number *sp = item; 0 <= *sp; ++sp)
|
||||
fprintf (out, " %s", symbols[*sp]->tag);
|
||||
@@ -202,10 +192,10 @@ grammar_rules_partial_print (FILE *out, const char *title,
|
||||
if (first)
|
||||
fprintf (out, "%s\n\n", title);
|
||||
else if (previous_rule && previous_rule->lhs != rules[r].lhs)
|
||||
fputc ('\n', out);
|
||||
putc ('\n', out);
|
||||
first = false;
|
||||
rule_print (&rules[r], previous_rule, out);
|
||||
fputc ('\n', out);
|
||||
putc ('\n', out);
|
||||
previous_rule = &rules[r];
|
||||
}
|
||||
if (!first)
|
||||
@@ -251,15 +241,25 @@ grammar_rules_print_xml (FILE *out, int level)
|
||||
xml_puts (out, level + 1, "<rules/>");
|
||||
}
|
||||
|
||||
static void
|
||||
section (FILE *out, const char *s)
|
||||
{
|
||||
fprintf (out, "%s\n", s);
|
||||
for (int i = strlen (s); 0 < i; --i)
|
||||
putc ('-', out);
|
||||
putc ('\n', out);
|
||||
putc ('\n', out);
|
||||
}
|
||||
|
||||
void
|
||||
grammar_dump (FILE *out, const char *title)
|
||||
{
|
||||
fprintf (out, "%s\n\n", title);
|
||||
fprintf (out,
|
||||
"ntokens = %d, nvars = %d, nsyms = %d, nrules = %d, nritems = %d\n\n",
|
||||
ntokens, nvars, nsyms, nrules, nritems);
|
||||
"ntokens = %d, nnterms = %d, nsyms = %d, nrules = %d, nritems = %d\n\n",
|
||||
ntokens, nnterms, nsyms, nrules, nritems);
|
||||
|
||||
fprintf (out, "Tokens\n------\n\n");
|
||||
section (out, "Tokens");
|
||||
{
|
||||
fprintf (out, "Value Sprec Sassoc Tag\n");
|
||||
|
||||
@@ -271,7 +271,7 @@ grammar_dump (FILE *out, const char *title)
|
||||
fprintf (out, "\n\n");
|
||||
}
|
||||
|
||||
fprintf (out, "Non terminals\n-------------\n\n");
|
||||
section (out, "Nonterminals");
|
||||
{
|
||||
fprintf (out, "Value Tag\n");
|
||||
|
||||
@@ -281,7 +281,7 @@ grammar_dump (FILE *out, const char *title)
|
||||
fprintf (out, "\n\n");
|
||||
}
|
||||
|
||||
fprintf (out, "Rules\n-----\n\n");
|
||||
section (out, "Rules");
|
||||
{
|
||||
fprintf (out,
|
||||
"Num (Prec, Assoc, Useful, UselessChain) Lhs"
|
||||
@@ -303,17 +303,17 @@ grammar_dump (FILE *out, const char *title)
|
||||
/* Dumped the RHS. */
|
||||
for (item_number *rhsp = rule_i->rhs; 0 <= *rhsp; ++rhsp)
|
||||
fprintf (out, " %3d", *rhsp);
|
||||
fputc ('\n', out);
|
||||
putc ('\n', out);
|
||||
}
|
||||
}
|
||||
fprintf (out, "\n\n");
|
||||
|
||||
fprintf (out, "Rules interpreted\n-----------------\n\n");
|
||||
section (out, "Rules interpreted");
|
||||
for (rule_number r = 0; r < nrules + nuseless_productions; ++r)
|
||||
{
|
||||
fprintf (out, "%-5d %s:", r, rules[r].lhs->symbol->tag);
|
||||
rule_rhs_print (&rules[r], out);
|
||||
fputc ('\n', out);
|
||||
putc ('\n', out);
|
||||
}
|
||||
fprintf (out, "\n\n");
|
||||
}
|
||||
|
||||
+41
-6
@@ -23,9 +23,9 @@
|
||||
|
||||
/* Representation of the grammar rules:
|
||||
|
||||
NTOKENS is the number of tokens, and NVARS is the number of
|
||||
NTOKENS is the number of tokens, and NNTERMS is the number of
|
||||
variables (nonterminals). NSYMS is the total number, ntokens +
|
||||
nvars.
|
||||
nnterms.
|
||||
|
||||
Each symbol (either token or variable) receives a symbol number.
|
||||
Numbers 0 to NTOKENS - 1 are for tokens, and NTOKENS to NSYMS - 1
|
||||
@@ -101,6 +101,10 @@
|
||||
|
||||
Associativities are recorded similarly in SYMBOLS[I]->assoc. */
|
||||
|
||||
# include "system.h"
|
||||
|
||||
# include <unicodeio.h>
|
||||
|
||||
# include "location.h"
|
||||
# include "symtab.h"
|
||||
|
||||
@@ -109,13 +113,17 @@
|
||||
|
||||
extern int nsyms;
|
||||
extern int ntokens;
|
||||
extern int nvars;
|
||||
extern int nnterms;
|
||||
|
||||
/* Elements of ritem. */
|
||||
typedef int item_number;
|
||||
# define ITEM_NUMBER_MAX INT_MAX
|
||||
extern item_number *ritem;
|
||||
extern int nritems;
|
||||
|
||||
/* Indices into ritem. */
|
||||
typedef unsigned int item_index;
|
||||
|
||||
/* There is weird relationship between OT1H item_number and OTOH
|
||||
symbol_number and rule_number: we store the latter in
|
||||
item_number. symbol_number values are stored as-is, while
|
||||
@@ -173,7 +181,7 @@ typedef struct
|
||||
{
|
||||
/* The number of the rule in the source. It is usually the index in
|
||||
RULES too, except if there are useless rules. */
|
||||
rule_number user_number;
|
||||
rule_number code;
|
||||
|
||||
/* The index in RULES. Usually the rule number in the source,
|
||||
except if some rules are useless. */
|
||||
@@ -209,8 +217,35 @@ typedef struct
|
||||
extern rule *rules;
|
||||
extern rule_number nrules;
|
||||
|
||||
/* Fallback in case we can't print "•". */
|
||||
static inline long
|
||||
print_dot_fallback (unsigned int code _GL_UNUSED,
|
||||
const char *msg _GL_UNUSED,
|
||||
void *callback_arg)
|
||||
{
|
||||
FILE *out = (FILE *) callback_arg;
|
||||
putc ('.', out);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Print "•", the symbol used to represent a point in an item (aka, a
|
||||
dotted rule). */
|
||||
static inline void
|
||||
print_dot (FILE *out)
|
||||
{
|
||||
unicode_to_mb (0x2022, fwrite_success_callback, print_dot_fallback, out);
|
||||
}
|
||||
|
||||
/* Get the rule associated to this item. ITEM points inside RITEM. */
|
||||
rule const *item_rule (item_number const *item);
|
||||
static inline rule const *
|
||||
item_rule (item_number const *item)
|
||||
{
|
||||
item_number const *sp = item;
|
||||
while (!item_number_is_rule_number (*sp))
|
||||
++sp;
|
||||
rule_number r = item_number_as_rule_number (*sp);
|
||||
return &rules[r];
|
||||
}
|
||||
|
||||
/* Pretty-print this ITEM (as in the report). ITEM points inside
|
||||
RITEM. PREVIOUS_RULE is used to see if the lhs is common, in which
|
||||
@@ -262,7 +297,7 @@ extern symbol **symbols;
|
||||
by the user's yylex routine, it yields the internal token number
|
||||
used by the parser and throughout bison. */
|
||||
extern symbol_number *token_translations;
|
||||
extern int max_user_token_number;
|
||||
extern int max_code;
|
||||
|
||||
|
||||
|
||||
|
||||
+12
-10
@@ -72,18 +72,20 @@ output_edge (int source, int destination, char const *label,
|
||||
{
|
||||
fprintf (fout, " %d -> %d [style=%s", source, destination, style);
|
||||
if (label)
|
||||
fprintf (fout, " label=%s", quote (label));
|
||||
{
|
||||
fputs (" label=\"", fout);
|
||||
for (const char *cp = label; *cp; ++cp)
|
||||
switch (*cp)
|
||||
{
|
||||
case '"': fputs ("\\\"", fout); break;
|
||||
case '\\': fputs ("\\\\", fout); break;
|
||||
default: fputc (*cp, fout); break;
|
||||
}
|
||||
fputc ('"', fout);
|
||||
}
|
||||
fputs ("]\n", fout);
|
||||
}
|
||||
|
||||
char const *
|
||||
escape (char const *name)
|
||||
{
|
||||
char *q = quote (name);
|
||||
q[strlen (q) - 1] = '\0';
|
||||
return q + 1;
|
||||
}
|
||||
|
||||
static void
|
||||
no_reduce_bitset_init (state const *s, bitset *no_reduce_set)
|
||||
{
|
||||
@@ -149,7 +151,7 @@ print_token (struct obstack *out, bool first, char const *tok)
|
||||
{
|
||||
if (! first)
|
||||
obstack_sgrow (out, ", ");
|
||||
obstack_sgrow (out, escape (tok));
|
||||
obstack_backslash (out, tok);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,10 +63,4 @@ void output_red (state const *s, reductions const *reds, FILE *fout);
|
||||
*/
|
||||
void finish_graph (FILE *fout);
|
||||
|
||||
/** Escape a lookahead token.
|
||||
*
|
||||
* \param name the token.
|
||||
*/
|
||||
char const *escape (char const *name);
|
||||
|
||||
#endif /* ! GRAPHVIZ_H_ */
|
||||
|
||||
+23
-33
@@ -18,10 +18,11 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <config.h>
|
||||
#include "system.h"
|
||||
|
||||
#include "ielr.h"
|
||||
|
||||
#include "system.h"
|
||||
|
||||
#include <bitset.h>
|
||||
#include <timevar.h>
|
||||
|
||||
@@ -230,7 +231,7 @@ ielr_compute_follow_kernel_items (bitset ritem_sees_lookahead_set,
|
||||
for (goto_number i = 0; i < ngotos; ++i)
|
||||
{
|
||||
size_t nitems = states[from_state[i]]->nitems;
|
||||
item_number *items = states[from_state[i]]->items;
|
||||
item_index *items = states[from_state[i]]->items;
|
||||
for (size_t j = 0; j < nitems; ++j)
|
||||
/* If this item has this goto and if all subsequent symbols in this
|
||||
RHS (if any) are nullable nonterminals, then record this item as
|
||||
@@ -318,7 +319,7 @@ static state ***
|
||||
ielr_compute_predecessors (void)
|
||||
{
|
||||
int *predecessor_counts = xnmalloc (nstates, sizeof *predecessor_counts);
|
||||
state ***result = xnmalloc (nstates, sizeof *result);
|
||||
state ***res = xnmalloc (nstates, sizeof *res);
|
||||
for (state_number i = 0; i < nstates; ++i)
|
||||
predecessor_counts[i] = 0;
|
||||
for (state_number i = 0; i < nstates; ++i)
|
||||
@@ -326,18 +327,18 @@ ielr_compute_predecessors (void)
|
||||
++predecessor_counts[states[i]->transitions->states[j]->number];
|
||||
for (state_number i = 0; i < nstates; ++i)
|
||||
{
|
||||
result[i] = xnmalloc (predecessor_counts[i]+1, sizeof *result[i]);
|
||||
result[i][predecessor_counts[i]] = NULL;
|
||||
res[i] = xnmalloc (predecessor_counts[i]+1, sizeof *res[i]);
|
||||
res[i][predecessor_counts[i]] = NULL;
|
||||
predecessor_counts[i] = 0;
|
||||
}
|
||||
for (state_number i = 0; i < nstates; ++i)
|
||||
for (int j = 0; j < states[i]->transitions->num; ++j)
|
||||
{
|
||||
state_number k = states[i]->transitions->states[j]->number;
|
||||
result[k][predecessor_counts[k]++] = states[i];
|
||||
res[k][predecessor_counts[k]++] = states[i];
|
||||
}
|
||||
free (predecessor_counts);
|
||||
return result;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -417,14 +418,7 @@ ielr_item_has_lookahead (state *s, symbol_number lhs, size_t item,
|
||||
/* If the LHS symbol of this item isn't known (because this is a
|
||||
top-level invocation), go get it. */
|
||||
if (!lhs)
|
||||
{
|
||||
int i;
|
||||
for (i = s->items[item];
|
||||
!item_number_is_rule_number (ritem[i]);
|
||||
++i)
|
||||
continue;
|
||||
lhs = rules[item_number_as_rule_number (ritem[i])].lhs->number;
|
||||
}
|
||||
lhs = item_rule (&ritem[s->items[item]])->lhs->number;
|
||||
/* If this kernel item is next to the beginning of the RHS, then
|
||||
check all predecessors' goto follows for the LHS. */
|
||||
if (item_number_is_rule_number (ritem[s->items[item] - 2]))
|
||||
@@ -632,17 +626,10 @@ ielr_compute_lookaheads (bitsetv follow_kernel_items, bitsetv always_follows,
|
||||
&& !bitset_empty_p (lookahead_filter[t_item]))
|
||||
{
|
||||
if (item_number_is_rule_number (ritem[t->items[t_item] - 2]))
|
||||
{
|
||||
int rule_item;
|
||||
for (rule_item = t->items[t_item];
|
||||
!item_number_is_rule_number (ritem[rule_item]);
|
||||
++rule_item)
|
||||
;
|
||||
ielr_compute_goto_follow_set (
|
||||
follow_kernel_items, always_follows, s,
|
||||
rules[item_number_as_rule_number (ritem[rule_item])].lhs,
|
||||
lookaheads[t_item]);
|
||||
}
|
||||
ielr_compute_goto_follow_set (
|
||||
follow_kernel_items, always_follows, s,
|
||||
item_rule (&ritem[t->items[t_item]])->lhs,
|
||||
lookaheads[t_item]);
|
||||
else if (s->lookaheads)
|
||||
{
|
||||
/* We don't have to start the s item search at the beginning
|
||||
@@ -709,15 +696,17 @@ ielr_compute_state (bitsetv follow_kernel_items, bitsetv always_follows,
|
||||
/* Determine whether there's an isocore of t with which these lookaheads can
|
||||
be merged. */
|
||||
{
|
||||
AnnotationIndex ai;
|
||||
AnnotationList *a;
|
||||
if (annotation_lists)
|
||||
for (ai = 0, a = annotation_lists[lr0_isocore->state->number];
|
||||
{
|
||||
AnnotationIndex ai;
|
||||
AnnotationList *a;
|
||||
for (ai = 0, a = annotation_lists[lr0_isocore->state->number];
|
||||
a;
|
||||
++ai, a = a->next)
|
||||
work1[ai] =
|
||||
AnnotationList__computeDominantContribution (
|
||||
a, lr0_isocore->state->nitems, lookaheads, false);
|
||||
}
|
||||
for (this_isocorep = &t->state_list;
|
||||
this_isocorep == &t->state_list || *this_isocorep != t->state_list;
|
||||
this_isocorep = &(*this_isocorep)->nextIsocore)
|
||||
@@ -726,6 +715,8 @@ ielr_compute_state (bitsetv follow_kernel_items, bitsetv always_follows,
|
||||
break;
|
||||
if (annotation_lists)
|
||||
{
|
||||
AnnotationIndex ai;
|
||||
AnnotationList *a;
|
||||
for (ai = 0, a = annotation_lists[lr0_isocore->state->number];
|
||||
a;
|
||||
++ai, a = a->next)
|
||||
@@ -789,15 +780,14 @@ ielr_compute_state (bitsetv follow_kernel_items, bitsetv always_follows,
|
||||
actually new. */
|
||||
if (has_lookaheads)
|
||||
{
|
||||
size_t i;
|
||||
if (!(*this_isocorep)->lookaheads)
|
||||
{
|
||||
(*this_isocorep)->lookaheads =
|
||||
xnmalloc (t->nitems, sizeof (*this_isocorep)->lookaheads);
|
||||
for (i = 0; i < t->nitems; ++i)
|
||||
for (size_t i = 0; i < t->nitems; ++i)
|
||||
(*this_isocorep)->lookaheads[i] = NULL;
|
||||
}
|
||||
for (i = 0; i < t->nitems; ++i)
|
||||
for (size_t i = 0; i < t->nitems; ++i)
|
||||
if (!bitset_empty_p (lookaheads[i]))
|
||||
{
|
||||
if (!(*this_isocorep)->lookaheads[i])
|
||||
@@ -1030,7 +1020,7 @@ ielr_split_states (bitsetv follow_kernel_items, bitsetv always_follows,
|
||||
if (!node->state->consistent)
|
||||
{
|
||||
size_t i = 0;
|
||||
item_number *itemset = node->state->items;
|
||||
item_index *itemset = node->state->items;
|
||||
for (size_t r = 0; r < node->state->reductions->num; ++r)
|
||||
{
|
||||
rule *this_rule = node->state->reductions->rules[r];
|
||||
|
||||
+4
-4
@@ -99,7 +99,7 @@ void
|
||||
set_goto_map (void)
|
||||
{
|
||||
/* Count the number of gotos (ngotos) per nterm (goto_map). */
|
||||
goto_map = xcalloc (nvars + 1, sizeof *goto_map);
|
||||
goto_map = xcalloc (nnterms + 1, sizeof *goto_map);
|
||||
ngotos = 0;
|
||||
for (state_number s = 0; s < nstates; ++s)
|
||||
{
|
||||
@@ -113,7 +113,7 @@ set_goto_map (void)
|
||||
}
|
||||
}
|
||||
|
||||
goto_number *temp_map = xnmalloc (nvars + 1, sizeof *temp_map);
|
||||
goto_number *temp_map = xnmalloc (nnterms + 1, sizeof *temp_map);
|
||||
{
|
||||
goto_number k = 0;
|
||||
for (symbol_number i = ntokens; i < nsyms; ++i)
|
||||
@@ -583,7 +583,7 @@ lalr_update_state_numbers (state_number old_to_new[], state_number nstates_old)
|
||||
{
|
||||
goto_number ngotos_reachable = 0;
|
||||
symbol_number nonterminal = 0;
|
||||
aver (nsyms == nvars + ntokens);
|
||||
aver (nsyms == nnterms + ntokens);
|
||||
|
||||
for (goto_number i = 0; i < ngotos; ++i)
|
||||
{
|
||||
@@ -601,7 +601,7 @@ lalr_update_state_numbers (state_number old_to_new[], state_number nstates_old)
|
||||
++ngotos_reachable;
|
||||
}
|
||||
}
|
||||
while (nonterminal <= nvars)
|
||||
while (nonterminal <= nnterms)
|
||||
{
|
||||
aver (ngotos == goto_map[nonterminal]);
|
||||
goto_map[nonterminal++] = ngotos_reachable;
|
||||
|
||||
+16
-1
@@ -40,6 +40,10 @@ src_bison_SOURCES = \
|
||||
src/complain.h \
|
||||
src/conflicts.c \
|
||||
src/conflicts.h \
|
||||
src/counterexample.c \
|
||||
src/counterexample.h \
|
||||
src/derivation.c \
|
||||
src/derivation.h \
|
||||
src/derives.c \
|
||||
src/derives.h \
|
||||
src/files.c \
|
||||
@@ -61,6 +65,8 @@ src_bison_SOURCES = \
|
||||
src/location.h \
|
||||
src/lr0.c \
|
||||
src/lr0.h \
|
||||
src/lssi.c \
|
||||
src/lssi.h \
|
||||
src/main.c \
|
||||
src/muscle-tab.c \
|
||||
src/muscle-tab.h \
|
||||
@@ -71,6 +77,8 @@ src_bison_SOURCES = \
|
||||
src/output.c \
|
||||
src/output.h \
|
||||
src/parse-gram.y \
|
||||
src/parse-simulation.c \
|
||||
src/parse-simulation.h \
|
||||
src/print-graph.c \
|
||||
src/print-graph.h \
|
||||
src/print-xml.c \
|
||||
@@ -91,6 +99,8 @@ src_bison_SOURCES = \
|
||||
src/scan-skel.h \
|
||||
src/state.c \
|
||||
src/state.h \
|
||||
src/state-item.c \
|
||||
src/state-item.h \
|
||||
src/symlist.c \
|
||||
src/symlist.h \
|
||||
src/symtab.c \
|
||||
@@ -123,10 +133,15 @@ src_bison_LDADD = \
|
||||
$(ISNANL_LIBM) \
|
||||
$(LDEXPL_LIBM) \
|
||||
$(LDEXP_LIBM) \
|
||||
$(LIBINTL) \
|
||||
$(LIBTHREAD) \
|
||||
$(LIB_CLOCK_GETTIME) \
|
||||
$(LIB_GETHRXTIME) \
|
||||
$(LIB_HARD_LOCALE) \
|
||||
$(LIB_MBRTOWC) \
|
||||
$(LIB_SETLOCALE_NULL) \
|
||||
$(LIBICONV) \
|
||||
$(LIBINTL) \
|
||||
$(LIBREADLINE) \
|
||||
$(LIBTEXTSTYLE)
|
||||
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ static state_list *last_state = NULL;
|
||||
|
||||
/* Print CORE for debugging. */
|
||||
static void
|
||||
core_print (size_t core_size, item_number *core, FILE *out)
|
||||
core_print (size_t core_size, item_index *core, FILE *out)
|
||||
{
|
||||
for (int i = 0; i < core_size; ++i)
|
||||
{
|
||||
@@ -65,7 +65,7 @@ core_print (size_t core_size, item_number *core, FILE *out)
|
||||
`-----------------------------------------------------------------*/
|
||||
|
||||
static state *
|
||||
state_list_append (symbol_number sym, size_t core_size, item_number *core)
|
||||
state_list_append (symbol_number sym, size_t core_size, item_index *core)
|
||||
{
|
||||
state_list *node = xmalloc (sizeof *node);
|
||||
state *res = state_new (sym, core_size, core);
|
||||
@@ -86,7 +86,7 @@ state_list_append (symbol_number sym, size_t core_size, item_number *core)
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Symbols that can be "shifted" (including non terminals) from the
|
||||
/* Symbols that can be "shifted" (including nonterminals) from the
|
||||
current state. */
|
||||
bitset shift_symbol;
|
||||
|
||||
@@ -98,14 +98,14 @@ static rule **redset;
|
||||
static state **shiftset;
|
||||
|
||||
|
||||
/* KERNEL_BASE[symbol-number] -> list of item numbers (offsets inside
|
||||
/* KERNEL_BASE[symbol-number] -> list of item indices (offsets inside
|
||||
RITEM) of length KERNEL_SIZE[symbol-number]. */
|
||||
static item_number **kernel_base;
|
||||
static item_index **kernel_base;
|
||||
static int *kernel_size;
|
||||
|
||||
/* A single dimension array that serves as storage for
|
||||
KERNEL_BASE. */
|
||||
static item_number *kernel_items;
|
||||
static item_index *kernel_items;
|
||||
|
||||
|
||||
static void
|
||||
@@ -257,7 +257,7 @@ new_itemsets (state *s)
|
||||
`--------------------------------------------------------------*/
|
||||
|
||||
static state *
|
||||
get_state (symbol_number sym, size_t core_size, item_number *core)
|
||||
get_state (symbol_number sym, size_t core_size, item_index *core)
|
||||
{
|
||||
if (trace_flag & trace_automaton)
|
||||
{
|
||||
@@ -394,7 +394,7 @@ generate_states (void)
|
||||
|
||||
/* Create the initial state. The 0 at the lhs is the index of the
|
||||
item of this initial rule. */
|
||||
item_number initial_core = 0;
|
||||
item_index initial_core = 0;
|
||||
state_list_append (0, 1, &initial_core);
|
||||
|
||||
/* States are queued when they are created; process them all. */
|
||||
|
||||
+370
@@ -0,0 +1,370 @@
|
||||
/* Lookahead sensitive state item searches for counterexample generation
|
||||
|
||||
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Compiler Compiler.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "lssi.h"
|
||||
|
||||
#include <gl_linked_list.h>
|
||||
#include <gl_xlist.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "getargs.h"
|
||||
#include "nullable.h"
|
||||
|
||||
// Lookahead sensitive state item.
|
||||
typedef struct lssi
|
||||
{
|
||||
state_item_number si;
|
||||
struct lssi *parent;
|
||||
// this is the precise lookahead set (follow_L from the CupEx paper)
|
||||
bitset lookahead;
|
||||
bool free_lookahead;
|
||||
} lssi;
|
||||
|
||||
static lssi *
|
||||
new_lssi (state_item_number si, lssi *p, bitset l, bool free_l)
|
||||
{
|
||||
lssi *res = xmalloc (sizeof *res);
|
||||
res->si = si;
|
||||
res->parent = p;
|
||||
res->lookahead = l;
|
||||
res->free_lookahead = free_l;
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
lssi_free (lssi *sn)
|
||||
{
|
||||
if (sn == NULL)
|
||||
return;
|
||||
if (sn->free_lookahead)
|
||||
bitset_free (sn->lookahead);
|
||||
free (sn);
|
||||
}
|
||||
|
||||
static size_t
|
||||
lssi_hasher (lssi *sn, size_t max)
|
||||
{
|
||||
size_t hash = sn->si;
|
||||
bitset_iterator biter;
|
||||
symbol_number syn;
|
||||
BITSET_FOR_EACH (biter, sn->lookahead, syn, 0)
|
||||
hash += syn;
|
||||
return hash % max;
|
||||
}
|
||||
|
||||
static bool
|
||||
lssi_comparator (lssi *s1, lssi *s2)
|
||||
{
|
||||
if (s1->si == s2->si)
|
||||
{
|
||||
if (s1->lookahead == s2->lookahead)
|
||||
return true;
|
||||
return bitset_equal_p (s1->lookahead, s2->lookahead);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
append_lssi (lssi *sn, Hash_table *visited, gl_list_t queue)
|
||||
{
|
||||
if (hash_lookup (visited, sn))
|
||||
{
|
||||
sn->free_lookahead = false;
|
||||
lssi_free (sn);
|
||||
return false;
|
||||
}
|
||||
hash_xinsert (visited, sn);
|
||||
gl_list_add_last (queue, sn);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
lssi_print (lssi *l)
|
||||
{
|
||||
print_state_item (state_items + l->si, stdout);
|
||||
if (l->lookahead)
|
||||
{
|
||||
printf ("FOLLOWL = { ");
|
||||
bitset_iterator biter;
|
||||
symbol_number sin;
|
||||
BITSET_FOR_EACH (biter, l->lookahead, sin, 0)
|
||||
printf ("%s, \n", symbols[sin]->tag);
|
||||
puts ("}");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Compute the set of state-items that can reach the given conflict item via
|
||||
* a combination of transitions or production steps.
|
||||
*/
|
||||
static bitset
|
||||
eligible_state_items (state_item *target)
|
||||
{
|
||||
bitset result = bitset_create (nstate_items, BITSET_FIXED);
|
||||
gl_list_t queue =
|
||||
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1,
|
||||
(const void **) &target);
|
||||
while (gl_list_size (queue) > 0)
|
||||
{
|
||||
state_item *si = (state_item *) gl_list_get_at (queue, 0);
|
||||
gl_list_remove_at (queue, 0);
|
||||
if (bitset_test (result, si - state_items))
|
||||
continue;
|
||||
bitset_set (result, si - state_items);
|
||||
// search all reverse edges.
|
||||
bitset rsi = si->revs;
|
||||
bitset_iterator biter;
|
||||
state_item_number sin;
|
||||
BITSET_FOR_EACH (biter, rsi, sin, 0)
|
||||
gl_list_add_last (queue, &state_items[sin]);
|
||||
}
|
||||
gl_list_free (queue);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the shortest lookahead-sensitive path from the start state to
|
||||
* this conflict. If optimized is true, only consider parser states
|
||||
* that can reach the conflict state.
|
||||
*/
|
||||
gl_list_t
|
||||
shortest_path_from_start (state_item_number target, symbol_number next_sym)
|
||||
{
|
||||
bitset eligible = eligible_state_items (&state_items[target]);
|
||||
Hash_table *visited = hash_initialize (32,
|
||||
NULL,
|
||||
(Hash_hasher) lssi_hasher,
|
||||
(Hash_comparator) lssi_comparator,
|
||||
(Hash_data_freer) lssi_free);
|
||||
bitset il = bitset_create (nsyms, BITSET_FIXED);
|
||||
bitset_set (il, 0);
|
||||
lssi *init = new_lssi (0, NULL, il, true);
|
||||
gl_list_t queue = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL,
|
||||
NULL, true);
|
||||
append_lssi (init, visited, queue);
|
||||
// breadth-first search
|
||||
bool finished = false;
|
||||
lssi *n;
|
||||
while (gl_list_size (queue) > 0)
|
||||
{
|
||||
n = (lssi *) gl_list_get_at (queue, 0);
|
||||
gl_list_remove_at (queue, 0);
|
||||
state_item_number last = n->si;
|
||||
if (target == last && bitset_test (n->lookahead, next_sym))
|
||||
{
|
||||
finished = true;
|
||||
break;
|
||||
}
|
||||
state_item *si = state_items + last;
|
||||
// Transitions don't change follow_L
|
||||
if (si->trans >= 0)
|
||||
{
|
||||
if (bitset_test (eligible, si->trans))
|
||||
{
|
||||
lssi *next = new_lssi (si->trans, n, n->lookahead, false);
|
||||
append_lssi (next, visited, queue);
|
||||
}
|
||||
}
|
||||
// For production steps, follow_L is based on the symbol after the
|
||||
// nonterminal being produced.
|
||||
// if no such symbol exists, follow_L is unchanged
|
||||
// if the symbol is a terminal, follow_L only contains that terminal
|
||||
// if the symbol is not nullable, follow_L is its FIRSTS set
|
||||
// if the symbol is nullable, follow_L is its FIRSTS set unioned with
|
||||
// this logic applied to the next symbol in the rule
|
||||
if (si->prods)
|
||||
{
|
||||
// Compute follow_L as above
|
||||
bitset lookahead = bitset_create (nsyms, BITSET_FIXED);
|
||||
item_number *pos = si->item + 1;
|
||||
for (; !item_number_is_rule_number (*pos); ++pos)
|
||||
{
|
||||
item_number it = *pos;
|
||||
if (ISTOKEN (it))
|
||||
{
|
||||
bitset_set (lookahead, it);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
bitset_union (lookahead, lookahead, FIRSTS (it));
|
||||
if (!nullable[it - ntokens])
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (item_number_is_rule_number (*pos))
|
||||
bitset_union (lookahead, n->lookahead, lookahead);
|
||||
|
||||
bool lookahead_used = false;
|
||||
// Try all possible production steps within this parser state.
|
||||
bitset_iterator biter;
|
||||
state_item_number nextSI;
|
||||
BITSET_FOR_EACH (biter, si->prods, nextSI, 0)
|
||||
{
|
||||
if (!bitset_test (eligible, nextSI))
|
||||
continue;
|
||||
lssi *next = new_lssi (nextSI, n, lookahead,
|
||||
!lookahead_used);
|
||||
lookahead_used = append_lssi (next, visited, queue)
|
||||
|| lookahead_used;
|
||||
}
|
||||
if (!lookahead_used)
|
||||
bitset_free (lookahead);
|
||||
}
|
||||
}
|
||||
|
||||
bitset_free (eligible);
|
||||
if (!finished)
|
||||
{
|
||||
gl_list_free (queue);
|
||||
fputs ("Cannot find shortest path to conflict state.", stderr);
|
||||
abort ();
|
||||
}
|
||||
gl_list_t res =
|
||||
gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
|
||||
for (lssi *sn = n; sn != NULL; sn = sn->parent)
|
||||
gl_list_add_first (res, state_items + sn->si);
|
||||
|
||||
hash_free (visited);
|
||||
gl_list_free (queue);
|
||||
|
||||
if (trace_flag & trace_cex)
|
||||
{
|
||||
puts ("REDUCE ITEM PATH:");
|
||||
gl_list_iterator_t it = gl_list_iterator (res);
|
||||
const void *sip;
|
||||
while (gl_list_iterator_next (&it, &sip, NULL))
|
||||
print_state_item ((state_item *) sip, stdout, "");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given terminal is in the given symbol set or can begin
|
||||
* a nonterminal in the given symbol set.
|
||||
*/
|
||||
bool
|
||||
intersect_symbol (symbol_number sym, bitset syms)
|
||||
{
|
||||
if (!syms)
|
||||
return true;
|
||||
bitset_iterator biter;
|
||||
symbol_number sn;
|
||||
BITSET_FOR_EACH (biter, syms, sn, 0)
|
||||
{
|
||||
if (sym == sn)
|
||||
return true;
|
||||
if (ISVAR (sn) && bitset_test (FIRSTS (sn), sym))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if any symbol in ts is in syms
|
||||
* or can begin a nonterminal syms.
|
||||
*/
|
||||
bool
|
||||
intersect (bitset ts, bitset syms)
|
||||
{
|
||||
if (!syms || !ts)
|
||||
return true;
|
||||
bitset_iterator biter;
|
||||
symbol_number sn;
|
||||
BITSET_FOR_EACH (biter, syms, sn, 0)
|
||||
{
|
||||
if (bitset_test (ts, sn))
|
||||
return true;
|
||||
if (ISVAR (sn) && !bitset_disjoint_p (ts, FIRSTS (sn)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compute a list of state_items that have a production to n with respect
|
||||
* to its lookahead
|
||||
*/
|
||||
gl_list_t
|
||||
lssi_reverse_production (const state_item *si, bitset lookahead)
|
||||
{
|
||||
gl_list_t result =
|
||||
gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
|
||||
if (SI_TRANSITION (si))
|
||||
return result;
|
||||
// A production step was made to the current lalr_item.
|
||||
// Check that the next symbol in the parent lalr_item is
|
||||
// compatible with the lookahead.
|
||||
bitset_iterator biter;
|
||||
state_item_number sin;
|
||||
BITSET_FOR_EACH (biter, si->revs, sin, 0)
|
||||
{
|
||||
state_item *prevsi = state_items + sin;
|
||||
if (!production_allowed (prevsi, si))
|
||||
continue;
|
||||
bitset prev_lookahead = prevsi->lookahead;
|
||||
if (item_number_is_rule_number (*(prevsi->item)))
|
||||
{
|
||||
// reduce item
|
||||
// Check that some lookaheads can be preserved.
|
||||
if (!intersect (prev_lookahead, lookahead))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// shift item
|
||||
if (lookahead)
|
||||
{
|
||||
// Check that lookahead is compatible with the first
|
||||
// possible symbols in the rest of the production.
|
||||
// Alternatively, if the rest of the production is
|
||||
// nullable, the lookahead must be compatible with
|
||||
// the lookahead of the corresponding item.
|
||||
bool applicable = false;
|
||||
bool nlable = true;
|
||||
for (item_number *pos = prevsi->item + 1;
|
||||
!applicable && nlable && item_number_is_symbol_number (*pos);
|
||||
++pos)
|
||||
{
|
||||
symbol_number next_sym = item_number_as_symbol_number (*pos);
|
||||
if (ISTOKEN (next_sym))
|
||||
{
|
||||
applicable = intersect_symbol (next_sym, lookahead);
|
||||
nlable = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
applicable = intersect (FIRSTS (next_sym), lookahead);
|
||||
if (!applicable)
|
||||
nlable = nullable[next_sym - ntokens];
|
||||
}
|
||||
}
|
||||
if (!applicable && !nlable)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
gl_list_add_last (result, prevsi);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/* Lookahead sensitive state item searches for counterexample generation
|
||||
|
||||
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Compiler Compiler.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef LSSI_H
|
||||
# define LSSI_H
|
||||
|
||||
# include "state-item.h"
|
||||
|
||||
/*
|
||||
All state-item graph nodes should also include a precise follow set (follow_L).
|
||||
However, ignoring follow_L saves a lot of memory and is a pretty good approximation.
|
||||
These functions exist to enforce restrictions caused by follow_L sets.
|
||||
*/
|
||||
|
||||
/*
|
||||
* find shortest lookahead-sensitive path of state-items to target such that
|
||||
* next_sym is in the follow_L set of target in that position.
|
||||
*/
|
||||
gl_list_t shortest_path_from_start (state_item_number target,
|
||||
symbol_number next_sym);
|
||||
|
||||
/**
|
||||
* Determine if the given terminal is in the given symbol set or can begin
|
||||
* a nonterminal in the given symbol set.
|
||||
*/
|
||||
bool intersect_symbol (symbol_number sym, bitset syms);
|
||||
|
||||
/**
|
||||
* Determine if any symbol in ts is in syms
|
||||
* or can begin with a nonterminal in syms.
|
||||
*/
|
||||
bool intersect (bitset ts, bitset syms);
|
||||
|
||||
/**
|
||||
* Compute a set of sequences of state-items that can make production steps
|
||||
* to this state-item such that the resulting possible lookahead symbols are
|
||||
* as given.
|
||||
*/
|
||||
gl_list_t lssi_reverse_production (const state_item *si, bitset lookahead);
|
||||
|
||||
#endif /* LSSI_H */
|
||||
+11
-2
@@ -33,6 +33,7 @@
|
||||
|
||||
#include "complain.h"
|
||||
#include "conflicts.h"
|
||||
#include "counterexample.h"
|
||||
#include "derives.h"
|
||||
#include "files.h"
|
||||
#include "fixits.h"
|
||||
@@ -44,6 +45,7 @@
|
||||
#include "muscle-tab.h"
|
||||
#include "nullable.h"
|
||||
#include "output.h"
|
||||
#include "parse-gram.h"
|
||||
#include "print-graph.h"
|
||||
#include "print-xml.h"
|
||||
#include "print.h"
|
||||
@@ -144,6 +146,9 @@ main (int argc, char *argv[])
|
||||
conflicts_update_state_numbers (old_to_new, nstates_old);
|
||||
free (old_to_new);
|
||||
}
|
||||
if (report_flag & report_cex
|
||||
|| warning_is_enabled (Wcounterexamples))
|
||||
counterexample_init ();
|
||||
conflicts_print ();
|
||||
timevar_pop (tv_conflicts);
|
||||
|
||||
@@ -217,11 +222,15 @@ main (int argc, char *argv[])
|
||||
reduce_free ();
|
||||
conflicts_free ();
|
||||
grammar_free ();
|
||||
counterexample_free ();
|
||||
output_file_names_free ();
|
||||
|
||||
/* The scanner memory cannot be released right after parsing, as it
|
||||
contains things such as user actions, prologue, epilogue etc. */
|
||||
/* The scanner and parser memory cannot be released right after
|
||||
parsing, as it contains things such as user actions, prologue,
|
||||
epilogue etc. */
|
||||
gram_scanner_free ();
|
||||
parser_free ();
|
||||
|
||||
muscle_free ();
|
||||
code_scanner_free ();
|
||||
skel_scanner_free ();
|
||||
|
||||
+4
-4
@@ -107,8 +107,7 @@ muscle_entry_new (char const *key)
|
||||
res->key = key;
|
||||
res->value = NULL;
|
||||
res->storage = NULL;
|
||||
if (!hash_insert (muscle_table, res))
|
||||
xalloc_die ();
|
||||
hash_xinsert (muscle_table, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -142,8 +141,7 @@ muscle_free (void)
|
||||
}
|
||||
|
||||
/* Look for the muscle named KEY. Return NULL if does not exist. */
|
||||
static
|
||||
muscle_entry *
|
||||
static muscle_entry *
|
||||
muscle_lookup (char const *key)
|
||||
{
|
||||
muscle_entry probe;
|
||||
@@ -449,6 +447,7 @@ muscle_percent_variable_update (char const *variable,
|
||||
{ "api.push_pull", "api.push-pull", muscle_keyword },
|
||||
{ "api.tokens.prefix", "api.token.prefix", muscle_code },
|
||||
{ "extends", "api.parser.extends", muscle_keyword },
|
||||
{ "filename_type", "api.filename.type", muscle_code },
|
||||
{ "final", "api.parser.final", muscle_keyword },
|
||||
{ "implements", "api.parser.implements", muscle_keyword },
|
||||
{ "lex_symbol", "api.token.constructor", -1 },
|
||||
@@ -457,6 +456,7 @@ muscle_percent_variable_update (char const *variable,
|
||||
{ "lr.keep-unreachable-states", "lr.keep-unreachable-state", muscle_keyword },
|
||||
{ "lr.keep_unreachable_states", "lr.keep-unreachable-state", muscle_keyword },
|
||||
{ "namespace", "api.namespace", muscle_code },
|
||||
{ "package", "api.package", muscle_code },
|
||||
{ "parser_class_name", "api.parser.class", muscle_code },
|
||||
{ "public", "api.parser.public", muscle_keyword },
|
||||
{ "strictfp", "api.parser.strictfp", muscle_keyword },
|
||||
|
||||
+45
-52
@@ -36,7 +36,7 @@
|
||||
typedef struct rule_list
|
||||
{
|
||||
struct rule_list *next;
|
||||
rule *value;
|
||||
const rule *value;
|
||||
} rule_list;
|
||||
|
||||
bool *nullable = NULL;
|
||||
@@ -44,9 +44,8 @@ bool *nullable = NULL;
|
||||
static void
|
||||
nullable_print (FILE *out)
|
||||
{
|
||||
int i;
|
||||
fputs ("NULLABLE\n", out);
|
||||
for (i = ntokens; i < nsyms; i++)
|
||||
for (int i = ntokens; i < nsyms; i++)
|
||||
fprintf (out, " %s: %s\n", symbols[i]->tag,
|
||||
nullable[i - ntokens] ? "yes" : "no");
|
||||
fputs ("\n\n", out);
|
||||
@@ -55,68 +54,62 @@ nullable_print (FILE *out)
|
||||
void
|
||||
nullable_compute (void)
|
||||
{
|
||||
rule_number ruleno;
|
||||
symbol_number *s1;
|
||||
symbol_number *s2;
|
||||
rule_list *p;
|
||||
nullable = xcalloc (nnterms, sizeof *nullable);
|
||||
|
||||
symbol_number *squeue = xnmalloc (nvars, sizeof *squeue);
|
||||
size_t *rcount = xcalloc (nrules, sizeof *rcount);
|
||||
/* RITEM contains all the rules, including useless productions.
|
||||
Hence we must allocate room for useless nonterminals too. */
|
||||
rule_list **rsets = xcalloc (nvars, sizeof *rsets);
|
||||
rule_list **rsets = xcalloc (nnterms, sizeof *rsets);
|
||||
/* This is said to be more elements than we actually use.
|
||||
Supposedly NRITEMS - NRULES is enough. But why take the risk? */
|
||||
rule_list *relts = xnmalloc (nritems + nvars + 1, sizeof *relts);
|
||||
rule_list *relts = xnmalloc (nritems + nnterms + 1, sizeof *relts);
|
||||
|
||||
nullable = xcalloc (nvars, sizeof *nullable);
|
||||
symbol_number *squeue = xnmalloc (nnterms, sizeof *squeue);
|
||||
symbol_number *s2 = squeue;
|
||||
{
|
||||
rule_list *p = relts;
|
||||
for (rule_number ruleno = 0; ruleno < nrules; ++ruleno)
|
||||
if (rules[ruleno].useful)
|
||||
{
|
||||
const rule *r = &rules[ruleno];
|
||||
if (r->rhs[0] >= 0)
|
||||
{
|
||||
/* This rule has a non empty RHS. */
|
||||
bool any_tokens = false;
|
||||
for (item_number *rp = r->rhs; *rp >= 0; ++rp)
|
||||
if (ISTOKEN (*rp))
|
||||
any_tokens = true;
|
||||
|
||||
s1 = s2 = squeue;
|
||||
p = relts;
|
||||
|
||||
for (ruleno = 0; ruleno < nrules; ++ruleno)
|
||||
if (rules[ruleno].useful)
|
||||
{
|
||||
rule *rules_ruleno = &rules[ruleno];
|
||||
if (rules_ruleno->rhs[0] >= 0)
|
||||
{
|
||||
/* This rule has a non empty RHS. */
|
||||
item_number *rp = NULL;
|
||||
bool any_tokens = false;
|
||||
for (rp = rules_ruleno->rhs; *rp >= 0; ++rp)
|
||||
if (ISTOKEN (*rp))
|
||||
any_tokens = true;
|
||||
|
||||
/* This rule has only nonterminals: schedule it for the second
|
||||
pass. */
|
||||
if (!any_tokens)
|
||||
for (rp = rules_ruleno->rhs; *rp >= 0; ++rp)
|
||||
/* This rule has only nonterminals: schedule it for the second
|
||||
pass. */
|
||||
if (!any_tokens)
|
||||
for (item_number *rp = r->rhs; *rp >= 0; ++rp)
|
||||
{
|
||||
rcount[ruleno]++;
|
||||
p->next = rsets[*rp - ntokens];
|
||||
p->value = r;
|
||||
rsets[*rp - ntokens] = p;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This rule has an empty RHS. */
|
||||
if (r->useful
|
||||
&& ! nullable[r->lhs->number - ntokens])
|
||||
{
|
||||
rcount[ruleno]++;
|
||||
p->next = rsets[*rp - ntokens];
|
||||
p->value = rules_ruleno;
|
||||
rsets[*rp - ntokens] = p;
|
||||
p++;
|
||||
nullable[r->lhs->number - ntokens] = true;
|
||||
*s2++ = r->lhs->number;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This rule has an empty RHS. */
|
||||
aver (item_number_as_rule_number (rules_ruleno->rhs[0])
|
||||
== ruleno);
|
||||
if (rules_ruleno->useful
|
||||
&& ! nullable[rules_ruleno->lhs->number - ntokens])
|
||||
{
|
||||
nullable[rules_ruleno->lhs->number - ntokens] = true;
|
||||
*s2++ = rules_ruleno->lhs->number;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
symbol_number *s1 = squeue;
|
||||
while (s1 < s2)
|
||||
for (p = rsets[*s1++ - ntokens]; p; p = p->next)
|
||||
for (rule_list *p = rsets[*s1++ - ntokens]; p; p = p->next)
|
||||
{
|
||||
rule *r = p->value;
|
||||
const rule *r = p->value;
|
||||
if (--rcount[r->number] == 0)
|
||||
if (r->useful && ! nullable[r->lhs->number - ntokens])
|
||||
{
|
||||
|
||||
+57
-28
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <filename.h> /* IS_PATH_WITH_DIR */
|
||||
#include <get-errno.h>
|
||||
#include <mbswidth.h>
|
||||
#include <path-join.h>
|
||||
#include <quotearg.h>
|
||||
#include <spawn-pipe.h>
|
||||
@@ -107,10 +108,8 @@ GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_state_number_table, state_number)
|
||||
`----------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
quoted_output (FILE *out, char const *cp)
|
||||
output_escaped (FILE *out, const char *cp)
|
||||
{
|
||||
fprintf (out, "[[");
|
||||
|
||||
for (; *cp; cp++)
|
||||
switch (*cp)
|
||||
{
|
||||
@@ -120,7 +119,13 @@ quoted_output (FILE *out, char const *cp)
|
||||
case ']': fputs ("@}", out); break;
|
||||
default: fputc (*cp, out); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
output_quoted (FILE *out, char const *cp)
|
||||
{
|
||||
fprintf (out, "[[");
|
||||
output_escaped (out, cp);
|
||||
fprintf (out, "]]");
|
||||
}
|
||||
|
||||
@@ -132,7 +137,7 @@ quoted_output (FILE *out, char const *cp)
|
||||
static void
|
||||
string_output (FILE *out, char const *string)
|
||||
{
|
||||
quoted_output (out, quotearg_style (c_quoting_style, string));
|
||||
output_quoted (out, quotearg_style (c_quoting_style, string));
|
||||
}
|
||||
|
||||
|
||||
@@ -193,9 +198,9 @@ static const char *
|
||||
symbol_tag (const symbol *sym)
|
||||
{
|
||||
const bool eof_is_user_defined
|
||||
= !endtoken->alias || STRNEQ (endtoken->alias->tag, "$end");
|
||||
= !eoftoken->alias || STRNEQ (eoftoken->alias->tag, "$end");
|
||||
|
||||
if (!eof_is_user_defined && sym->content == endtoken->content)
|
||||
if (!eof_is_user_defined && sym->content == eoftoken->content)
|
||||
return "\"end of file\"";
|
||||
else if (sym->content == undeftoken->content)
|
||||
return "\"invalid token\"";
|
||||
@@ -232,7 +237,7 @@ prepare_symbol_names (char const *muscle_name)
|
||||
/* Width of the next token, including the two quotes, the
|
||||
comma and the space. */
|
||||
int width
|
||||
= strlen (cp) + 2
|
||||
= mbswidth (cp, 0) + 2
|
||||
+ (translatable ? strlen ("N_()") : 0);
|
||||
|
||||
if (col + width > 75)
|
||||
@@ -272,14 +277,14 @@ static void
|
||||
prepare_symbols (void)
|
||||
{
|
||||
MUSCLE_INSERT_INT ("tokens_number", ntokens);
|
||||
MUSCLE_INSERT_INT ("nterms_number", nvars);
|
||||
MUSCLE_INSERT_INT ("nterms_number", nnterms);
|
||||
MUSCLE_INSERT_INT ("symbols_number", nsyms);
|
||||
MUSCLE_INSERT_INT ("user_token_number_max", max_user_token_number);
|
||||
MUSCLE_INSERT_INT ("code_max", max_code);
|
||||
|
||||
muscle_insert_symbol_number_table ("translate",
|
||||
token_translations,
|
||||
token_translations[0],
|
||||
1, max_user_token_number + 1);
|
||||
1, max_code + 1);
|
||||
|
||||
/* tname -- token names. */
|
||||
prepare_symbol_names ("tname");
|
||||
@@ -309,7 +314,7 @@ prepare_symbols (void)
|
||||
{
|
||||
int *values = xnmalloc (ntokens, sizeof *values);
|
||||
for (int i = 0; i < ntokens; ++i)
|
||||
values[i] = symbols[i]->content->user_token_number;
|
||||
values[i] = symbols[i]->content->code;
|
||||
muscle_insert_int_table ("toknum", values,
|
||||
values[0], 1, ntokens);
|
||||
free (values);
|
||||
@@ -474,6 +479,21 @@ symbol_numbers_output (FILE *out)
|
||||
| Output the user reduction actions to OUT. |
|
||||
`-------------------------------------------*/
|
||||
|
||||
static void
|
||||
rule_output (const rule *r, FILE *out)
|
||||
{
|
||||
output_escaped (out, r->lhs->symbol->tag);
|
||||
fputc (':', out);
|
||||
if (0 <= *r->rhs)
|
||||
for (item_number *rhsp = r->rhs; 0 <= *rhsp; ++rhsp)
|
||||
{
|
||||
fputc (' ', out);
|
||||
output_escaped (out, symbols[*rhsp]->tag);
|
||||
}
|
||||
else
|
||||
fputs (" %empty", out);
|
||||
}
|
||||
|
||||
static void
|
||||
user_actions_output (FILE *out)
|
||||
{
|
||||
@@ -492,9 +512,11 @@ user_actions_output (FILE *out)
|
||||
string_output (out, rules[r].action_loc.start.file);
|
||||
fprintf (out, ")dnl\n");
|
||||
}
|
||||
fprintf (out, "[%*s%s]])\n\n",
|
||||
fprintf (out, "[%*s%s]],\n[[",
|
||||
rules[r].action_loc.start.column - 1, "",
|
||||
rules[r].action);
|
||||
rule_output (&rules[r], out);
|
||||
fprintf (out, "]])\n\n");
|
||||
}
|
||||
fputs ("])\n\n", out);
|
||||
}
|
||||
@@ -565,8 +587,8 @@ prepare_symbol_definitions (void)
|
||||
SET_KEY ("tag");
|
||||
MUSCLE_INSERT_STRING (key, symbol_tag (sym));
|
||||
|
||||
SET_KEY ("user_number");
|
||||
MUSCLE_INSERT_INT (key, sym->content->user_token_number);
|
||||
SET_KEY ("code");
|
||||
MUSCLE_INSERT_INT (key, sym->content->code);
|
||||
|
||||
SET_KEY ("is_token");
|
||||
MUSCLE_INSERT_INT (key, i < ntokens);
|
||||
@@ -682,11 +704,12 @@ static void
|
||||
output_skeleton (void)
|
||||
{
|
||||
/* Compute the names of the package data dir and skeleton files. */
|
||||
char const *m4 = (m4 = getenv ("M4")) ? m4 : M4;
|
||||
char const *m4 = m4path ();
|
||||
char const *datadir = pkgdatadir ();
|
||||
char *skeldir = xpath_join (datadir, "skeletons");
|
||||
char *m4sugar = xpath_join (datadir, "m4sugar/m4sugar.m4");
|
||||
char *m4bison = xpath_join (skeldir, "bison.m4");
|
||||
char *traceon = xpath_join (skeldir, "traceon.m4");
|
||||
char *skel = (IS_PATH_WITH_DIR (skeleton)
|
||||
? xstrdup (skeleton)
|
||||
: xpath_join (skeldir, skeleton));
|
||||
@@ -698,21 +721,10 @@ output_skeleton (void)
|
||||
|
||||
/* 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];
|
||||
pid_t pid;
|
||||
{
|
||||
char const *argv[10];
|
||||
char const *argv[11];
|
||||
int i = 0;
|
||||
argv[i++] = m4;
|
||||
|
||||
@@ -730,15 +742,29 @@ output_skeleton (void)
|
||||
|
||||
argv[i++] = "-I";
|
||||
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++] = m4sugar;
|
||||
argv[i++] = "-";
|
||||
argv[i++] = m4bison;
|
||||
if (trace_flag & trace_m4)
|
||||
argv[i++] = traceon;
|
||||
argv[i++] = skel;
|
||||
argv[i++] = NULL;
|
||||
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. */
|
||||
pid = create_pipe_bidi ("m4", m4, (char **)(void*)argv, false, true,
|
||||
true, filter_fd);
|
||||
@@ -747,6 +773,7 @@ output_skeleton (void)
|
||||
free (skeldir);
|
||||
free (m4sugar);
|
||||
free (m4bison);
|
||||
free (traceon);
|
||||
free (skel);
|
||||
|
||||
if (trace_flag & trace_muscles)
|
||||
@@ -800,8 +827,10 @@ prepare (void)
|
||||
|
||||
#define DEFINE(Name) MUSCLE_INSERT_STRING (#Name, Name ? Name : "")
|
||||
DEFINE (dir_prefix);
|
||||
DEFINE (mapped_dir_prefix);
|
||||
DEFINE (parser_file_name);
|
||||
DEFINE (spec_header_file);
|
||||
DEFINE (spec_mapped_header_file);
|
||||
DEFINE (spec_file_prefix);
|
||||
DEFINE (spec_graph_file);
|
||||
DEFINE (spec_name_prefix);
|
||||
|
||||
+343
-237
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user