mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-08-08 10:15:14 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6675d36e25 | ||
|
|
d0bec3175f | ||
|
|
79e68b6c4d | ||
|
|
5cb74cacd8 | ||
|
|
9c8e6e05b6 | ||
|
|
431774d1f6 | ||
|
|
7d5474e979 | ||
|
|
6b78e50cef | ||
|
|
28769d608e | ||
|
|
a22588bcb9 | ||
|
|
b8c5e5609f | ||
|
|
b81229e1f9 | ||
|
|
815a76f558 | ||
|
|
ea138cd1f1 | ||
|
|
9922f1f877 | ||
|
|
1438b79e80 | ||
|
|
01f3e2969b | ||
|
|
744da03955 | ||
|
|
b28d67b6b0 | ||
|
|
cf890692f1 | ||
|
|
6932023f4d | ||
|
|
fff17fe8fe | ||
|
|
5544615a59 | ||
|
|
346ba14f15 | ||
|
|
4d18195ebc | ||
|
|
dd3e7b3895 | ||
|
|
64a3b6546a | ||
|
|
bad07a7f66 | ||
|
|
88bd814bf1 | ||
|
|
4f9ae5de07 | ||
|
|
78f72a4516 | ||
|
|
c04693d651 | ||
|
|
12191911ba | ||
|
|
d7f27477f4 | ||
|
|
5bad15d7ea | ||
|
|
cd099edf2d | ||
|
|
1e12219775 | ||
|
|
d8c2af56c1 | ||
|
|
cc11bb037c | ||
|
|
121dd98508 | ||
|
|
2eddbd0ac4 | ||
|
|
ee86ea8839 | ||
|
|
a2ad33dca6 | ||
|
|
5b2b7b1ffb | ||
|
|
dc72b3566d | ||
|
|
c47e1174d4 | ||
|
|
093eeb27e9 | ||
|
|
dab23c4a21 | ||
|
|
38a169bec1 | ||
|
|
dc77d6500f | ||
|
|
8262c7dc22 | ||
|
|
44f28d10ee | ||
|
|
44ad466a32 | ||
|
|
a839f4c461 | ||
|
|
9a51c6a128 | ||
|
|
2608b0cf12 | ||
|
|
aa766d1560 | ||
|
|
a7ed13b25f | ||
|
|
2d90916067 | ||
|
|
91e5a23ff2 | ||
|
|
d4ae66c371 | ||
|
|
70fb574717 | ||
|
|
0820f16ca8 | ||
|
|
49f1e5f428 | ||
|
|
238692ad77 | ||
|
|
5f95583da7 | ||
|
|
964fb2aa6f | ||
|
|
7c0d36b760 | ||
|
|
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 | ||
|
|
22c3839168 | ||
|
|
4619b32dc0 | ||
|
|
ad921890c1 | ||
|
|
14ce500508 | ||
|
|
acba58ac59 | ||
|
|
9c21da3363 | ||
|
|
febf6115a0 | ||
|
|
11b5bac7bf | ||
|
|
b61bf2f0e8 | ||
|
|
19f45df02b | ||
|
|
2ab4058de0 | ||
|
|
f2277c3fec | ||
|
|
fb49a10e2c | ||
|
|
f049a57eec |
+1
-1
@@ -1 +1 @@
|
||||
3.6.1
|
||||
3.6.93
|
||||
|
||||
+16
-12
@@ -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
|
||||
@@ -135,7 +136,7 @@ jobs:
|
||||
packages:
|
||||
- intel-oneapi-icc
|
||||
|
||||
- name: "ARM64: GCC 10 -O3 part 1"
|
||||
- name: "ARM64: GCC 10 -O2 part 1"
|
||||
stage: check
|
||||
os: linux
|
||||
arch: arm64
|
||||
@@ -144,24 +145,27 @@ jobs:
|
||||
env:
|
||||
- CC=gcc-10
|
||||
- CXX=g++-10
|
||||
- CONFIGUREFLAGS='CPPFLAGS=-DNDEBUG CFLAGS=-O3 CXXFLAGS=-O3'
|
||||
- CONFIGUREFLAGS='CPPFLAGS=-DNDEBUG CFLAGS=-O2 CXXFLAGS=-O2'
|
||||
- PART=1
|
||||
|
||||
# GCC10 on PPC seems to be buggy.
|
||||
# E.g., https://travis-ci.org/github/akimd/bison/jobs/687812428.
|
||||
- name: "PPC64le: GCC 9 part 1"
|
||||
- name: "PPC64le: GCC 10 -O2 part 1"
|
||||
stage: check
|
||||
os: linux
|
||||
arch: ppc64le
|
||||
dist: bionic
|
||||
addons: *gcc10
|
||||
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 10 part 1"
|
||||
- name: "s390x: GCC 10 -O2 part 1"
|
||||
stage: check
|
||||
os: linux
|
||||
arch: s390x
|
||||
@@ -170,7 +174,7 @@ jobs:
|
||||
env:
|
||||
- CC=gcc-10
|
||||
- CXX=g++-10
|
||||
- CONFIGUREFLAGS='CFLAGS=-O3 CXXFLAGS=-O3'
|
||||
- CONFIGUREFLAGS='CFLAGS=-O2 CXXFLAGS=-O2'
|
||||
- PART=1
|
||||
|
||||
## ----- ##
|
||||
|
||||
@@ -131,3 +131,11 @@ gen-ChangeLog:
|
||||
# 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,5 +1,262 @@
|
||||
GNU Bison NEWS
|
||||
|
||||
* Noteworthy changes in release 3.7 (2020-07-23) [stable]
|
||||
|
||||
** 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 `-Wcounterexamples`/`-Wcex`, bison will now output
|
||||
counterexamples for conflicts.
|
||||
|
||||
**** Unifying Counterexamples
|
||||
|
||||
Unifying counterexamples are strings which can be parsed in two ways due
|
||||
to the conflict. For example on a grammar that contains the usual
|
||||
"dangling else" ambiguity:
|
||||
|
||||
$ bison else.y
|
||||
else.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
|
||||
else.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
|
||||
|
||||
$ bison else.y -Wcex
|
||||
else.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
|
||||
else.y: warning: shift/reduce conflict on token "else" [-Wcounterexamples]
|
||||
Example: "if" exp "then" "if" exp "then" exp • "else" exp
|
||||
Shift derivation
|
||||
exp
|
||||
↳ "if" exp "then" exp
|
||||
↳ "if" exp "then" exp • "else" exp
|
||||
Example: "if" exp "then" "if" exp "then" exp • "else" exp
|
||||
Reduce derivation
|
||||
exp
|
||||
↳ "if" exp "then" exp "else" exp
|
||||
↳ "if" exp "then" exp •
|
||||
|
||||
When text styling is enabled, colors are used in the examples and the
|
||||
derivations to highlight the structure of both analyses. In this case,
|
||||
|
||||
"if" exp "then" [ "if" exp "then" exp • ] "else" exp
|
||||
|
||||
vs.
|
||||
|
||||
"if" exp "then" [ "if" exp "then" exp • "else" exp ]
|
||||
|
||||
|
||||
The counterexamples are "focused", in two different ways. First, they do
|
||||
not clutter the output with all the derivations from the start symbol,
|
||||
rather they start on the "conflicted nonterminal". They go straight to the
|
||||
point. Second, they don't "expand" nonterminal symbols uselessly.
|
||||
|
||||
**** Nonunifying Counterexamples
|
||||
|
||||
In the case of the dangling else, Bison found an example that can be
|
||||
parsed in two ways (therefore proving that the grammar is ambiguous).
|
||||
When it cannot find such an example, it instead generates two examples
|
||||
that are the same up until the dot:
|
||||
|
||||
$ bison foo.y
|
||||
foo.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
|
||||
foo.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
|
||||
foo.y:4.4-7: warning: rule useless in parser due to conflicts [-Wother]
|
||||
4 | a: expr
|
||||
| ^~~~
|
||||
|
||||
$ bison -Wcex foo.y
|
||||
foo.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
|
||||
foo.y: warning: shift/reduce conflict on token ID [-Wcounterexamples]
|
||||
First example: expr • ID ',' ID $end
|
||||
Shift derivation
|
||||
$accept
|
||||
↳ s $end
|
||||
↳ a ID
|
||||
↳ expr
|
||||
↳ expr • ID ','
|
||||
Second example: expr • ID $end
|
||||
Reduce derivation
|
||||
$accept
|
||||
↳ s $end
|
||||
↳ a ID
|
||||
↳ expr •
|
||||
foo.y:4.4-7: warning: rule useless in parser due to conflicts [-Wother]
|
||||
4 | a: expr
|
||||
| ^~~~
|
||||
|
||||
In these cases, the parser usually doesn't have enough lookahead to
|
||||
differentiate the two given examples.
|
||||
|
||||
**** Reports
|
||||
|
||||
Counterexamples are also included in the report when given
|
||||
`--report=counterexamples`/`-rcex` (or `--report=all`), with more
|
||||
technical details:
|
||||
|
||||
State 7
|
||||
|
||||
1 exp: "if" exp "then" exp • [$end, "then", "else"]
|
||||
2 | "if" exp "then" exp • "else" exp
|
||||
|
||||
"else" shift, and go to state 8
|
||||
|
||||
"else" [reduce using rule 1 (exp)]
|
||||
$default reduce using rule 1 (exp)
|
||||
|
||||
shift/reduce conflict on token "else":
|
||||
1 exp: "if" exp "then" exp •
|
||||
2 exp: "if" exp "then" exp • "else" exp
|
||||
Example: "if" exp "then" "if" exp "then" exp • "else" exp
|
||||
Shift derivation
|
||||
exp
|
||||
↳ "if" exp "then" exp
|
||||
↳ "if" exp "then" exp • "else" exp
|
||||
Example: "if" exp "then" "if" exp "then" exp • "else" exp
|
||||
Reduce derivation
|
||||
exp
|
||||
↳ "if" exp "then" exp "else" exp
|
||||
↳ "if" exp "then" exp •
|
||||
|
||||
*** File prefix mapping
|
||||
|
||||
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
|
||||
|
||||
*** Diagnostics
|
||||
|
||||
When text styling is enabled and the terminal supports it, the warnings
|
||||
now include hyperlinks to the documentation.
|
||||
|
||||
*** 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.
|
||||
|
||||
** Documentation
|
||||
|
||||
*** Examples
|
||||
|
||||
The bistromathic demonstrates %param and how to quote sources in the error
|
||||
messages:
|
||||
|
||||
> 123 456
|
||||
1.5-7: syntax error: expected end of file or + or - or * or / or ^ before number
|
||||
1 | 123 456
|
||||
| ^~~
|
||||
|
||||
** Bug fixes
|
||||
|
||||
*** 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
|
||||
@@ -12,6 +269,7 @@ GNU Bison NEWS
|
||||
|
||||
bison used to emit "nested" comments, which is invalid C.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.6.1 (2020-05-10) [stable]
|
||||
|
||||
** Bug fixes
|
||||
@@ -26,6 +284,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
|
||||
@@ -248,6 +507,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!
|
||||
@@ -268,6 +528,7 @@ GNU Bison NEWS
|
||||
|
||||
Fix api.token.raw support in Java.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.5.3 (2020-03-08) [stable]
|
||||
|
||||
** Bug fixes
|
||||
@@ -278,6 +539,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
|
||||
@@ -287,6 +549,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
|
||||
@@ -295,6 +558,7 @@ GNU Bison NEWS
|
||||
|
||||
Fix compiler warnings.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.5 (2019-12-11) [stable]
|
||||
|
||||
** Backward incompatible changes
|
||||
@@ -502,6 +766,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
|
||||
@@ -519,12 +784,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
|
||||
@@ -665,6 +932,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
|
||||
@@ -672,6 +940,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
|
||||
@@ -679,6 +948,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
|
||||
@@ -821,11 +1091,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
|
||||
@@ -940,7 +1210,7 @@ GNU Bison NEWS
|
||||
|
||||
** Bug fixes
|
||||
|
||||
*** Incorrect number of reduce-reduce conflicts
|
||||
*** Incorrect number of reduce/reduce conflicts
|
||||
|
||||
On a grammar such as
|
||||
|
||||
@@ -994,6 +1264,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
|
||||
@@ -1002,6 +1273,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
|
||||
@@ -1009,12 +1281,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
|
||||
@@ -1022,6 +1296,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
|
||||
@@ -1188,6 +1463,7 @@ GNU Bison NEWS
|
||||
|
||||
Portability/warning issues with Flex.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.1 (2018-08-27) [stable]
|
||||
|
||||
** Backward incompatible changes
|
||||
@@ -1328,6 +1604,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
|
||||
@@ -1358,6 +1635,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
|
||||
@@ -1370,6 +1648,7 @@ GNU Bison NEWS
|
||||
|
||||
Several portability issues in tests were fixed.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.0.3 (2015-01-15) [stable]
|
||||
|
||||
** Bug fixes
|
||||
@@ -1426,6 +1705,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
|
||||
@@ -1450,6 +1730,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
|
||||
@@ -1481,6 +1762,7 @@ GNU Bison NEWS
|
||||
|
||||
Bugs and portability issues.
|
||||
|
||||
|
||||
* Noteworthy changes in release 3.0 (2013-07-25) [stable]
|
||||
|
||||
** WARNING: Future backward-incompatibilities!
|
||||
@@ -1851,7 +2133,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.
|
||||
@@ -2077,6 +2359,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
|
||||
@@ -2087,6 +2370,7 @@ GNU Bison NEWS
|
||||
|
||||
*** Fix some compiler warnings (lalr1.cc)
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.7 (2012-12-12) [stable]
|
||||
|
||||
** Bug fixes
|
||||
@@ -2211,6 +2495,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.
|
||||
@@ -2230,10 +2515,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
|
||||
@@ -2278,6 +2565,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
|
||||
@@ -2294,6 +2582,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.
|
||||
@@ -2332,6 +2621,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
|
||||
@@ -2465,6 +2755,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:
|
||||
@@ -2562,6 +2853,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:
|
||||
@@ -2917,6 +3209,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
|
||||
@@ -2937,6 +3230,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
|
||||
@@ -3031,6 +3325,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
|
||||
@@ -3056,6 +3351,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.
|
||||
@@ -3071,6 +3367,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
|
||||
@@ -3257,6 +3554,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
|
||||
@@ -3371,6 +3669,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",
|
||||
@@ -3379,6 +3678,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
|
||||
@@ -3461,6 +3761,7 @@ GNU Bison NEWS
|
||||
|
||||
** DJGPP support added.
|
||||
|
||||
|
||||
* Noteworthy changes in release 2.1 (2005-09-16)
|
||||
|
||||
** The C++ lalr1.cc skeleton supports %lex-param.
|
||||
@@ -3487,6 +3788,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
|
||||
@@ -3550,6 +3852,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
|
||||
@@ -3670,6 +3973,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.
|
||||
@@ -3701,6 +4005,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
|
||||
@@ -3845,6 +4150,7 @@ GNU Bison NEWS
|
||||
|
||||
** GNU M4 is now required when using Bison.
|
||||
|
||||
|
||||
* Noteworthy changes in release 1.35 (2002-03-25)
|
||||
|
||||
** C Skeleton
|
||||
@@ -3860,6 +4166,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
|
||||
@@ -3880,6 +4187,7 @@ GNU Bison NEWS
|
||||
|
||||
** Fix test suite portability problems.
|
||||
|
||||
|
||||
* Noteworthy changes in release 1.33 (2002-02-07)
|
||||
|
||||
** Fix C++ issues
|
||||
@@ -3889,6 +4197,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
|
||||
@@ -3897,6 +4206,7 @@ GNU Bison NEWS
|
||||
|
||||
** Italian, Dutch translations
|
||||
|
||||
|
||||
* Noteworthy changes in release 1.31 (2002-01-14)
|
||||
|
||||
** Many Bug Fixes
|
||||
@@ -3984,6 +4294,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
|
||||
@@ -3995,6 +4306,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
|
||||
@@ -4030,6 +4342,7 @@ GNU Bison NEWS
|
||||
** @$
|
||||
Automatic location tracking.
|
||||
|
||||
|
||||
* Noteworthy changes in release 1.28 (1999-07-06)
|
||||
|
||||
** Should compile better now with K&R compilers.
|
||||
@@ -4040,11 +4353,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.
|
||||
@@ -4062,6 +4377,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
|
||||
@@ -4087,6 +4403,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
|
||||
@@ -4096,72 +4413,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 Wcex Nonunifying rcex
|
||||
|
||||
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
|
||||
|
||||
-->
|
||||
|
||||
+233
-154
@@ -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,201 @@ 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
|
||||
- "lookahead", not "look-ahead".
|
||||
- "midrule", not "mid-rule".
|
||||
- "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 +382,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
|
||||
@@ -393,7 +444,7 @@ added the `[-Wother]` part to all the warnings). Part of the update can be
|
||||
done with a crude tool: `build-aux/update-test`.
|
||||
|
||||
Once you ran the test suite, and therefore have many `testsuite.log` files,
|
||||
run, from the source tree:
|
||||
run `make update-tests`. Or, by hand, from the *source* tree:
|
||||
|
||||
$ ./build-aux/update-test $build/tests/testsuite.dir/*/testsuite.log
|
||||
|
||||
@@ -409,6 +460,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 +564,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 +601,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,15 +1,41 @@
|
||||
* 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
|
||||
|
||||
** Questions
|
||||
*** Java
|
||||
- Should i18n be part of the Lexer? Currently it's a static method of
|
||||
@@ -39,23 +65,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 +75,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
|
||||
@@ -148,6 +157,9 @@ Les catégories d'avertissements incluent :
|
||||
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.,
|
||||
@@ -414,16 +426,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.
|
||||
@@ -514,13 +516,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:
|
||||
|
||||
@@ -597,15 +592,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.
|
||||
|
||||
+5
-3
@@ -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,14 +38,15 @@ gnulib_modules='
|
||||
obstack-printf
|
||||
perror progname
|
||||
quote quotearg
|
||||
rbtreehash-list
|
||||
readline
|
||||
readme-release
|
||||
realloc-posix
|
||||
relocatable-prog relocatable-script
|
||||
rename
|
||||
spawn-pipe stdbool stpcpy strdup-posix strerror strverscmp
|
||||
spawn-pipe stdbool stpcpy stpncpy 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
|
||||
|
||||
+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.
|
||||
|
||||
+24
-16
@@ -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).
|
||||
- `id`: string (e.g., `exp`, `NUM`, or `TOK_NUM` with api.token.prefix)
|
||||
If `has_id`, the name of the token kind (prefixed by api.token.prefix if
|
||||
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 (e.g., `YYSYMBOL_exp`, `YYSYMBOL_NUM`)
|
||||
The base of the symbol kind, i.e., the enumerator of this symbol (token or
|
||||
nonterminal) which is mapped 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,32 @@
|
||||
/* "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-8 { color: #013220; } /* Dark green. */
|
||||
.cex-9 { color: #e75480; } /* Dark pink. */
|
||||
.cex-10 { color: cyan; }
|
||||
.cex-11 { color: orange; }
|
||||
|
||||
/* 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,12 @@ m4_define([b4_yytranslate_define],
|
||||
{
|
||||
]b4_translate[
|
||||
};
|
||||
const int user_token_number_max_ = ]b4_user_token_number_max[;
|
||||
// Last valid token kind.
|
||||
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,6 +17,7 @@
|
||||
# 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.
|
||||
@@ -27,9 +28,10 @@
|
||||
#
|
||||
# Prefix all the output lines with PREFIX.
|
||||
m4_define([_b4_comment],
|
||||
[$2[]m4_bpatsubsts(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;])
|
||||
|
||||
|
||||
+10
-7
@@ -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
|
||||
@@ -331,8 +333,8 @@ static YYLTYPE yyloc_default][]b4_yyloc_default;])[
|
||||
accessed by $0, $-1, etc., in any rule. */
|
||||
#define YYMAXLEFT ]b4_max_left_semantic_context[
|
||||
|
||||
/* YYMAXUTOK -- Last valid token number (for yychar). */
|
||||
#define YYMAXUTOK ]b4_user_token_number_max[
|
||||
/* YYMAXUTOK -- Last valid token kind. */
|
||||
#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);
|
||||
}
|
||||
}
|
||||
|
||||
+18
-16
@@ -428,9 +428,10 @@ b4_locations_if([, ref ]b4_location_type[ yylocationp])[)
|
||||
*/
|
||||
public bool parse ()
|
||||
{
|
||||
/// Lookahead and lookahead in internal form.
|
||||
// Lookahead token kind.
|
||||
int yychar = TokenKind.YYEMPTY;
|
||||
SymbolKind yytoken = SymbolKind.]b4_symbol(-2, kind)[;
|
||||
// Lookahead symbol kind.
|
||||
SymbolKind yytoken = ]b4_symbol(-2, kind)[;
|
||||
|
||||
/* State. */
|
||||
int yyn = 0;
|
||||
@@ -509,14 +510,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 +588,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 +639,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 +727,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 +746,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 +842,18 @@ m4_popdef([b4_at_dollar])])dnl
|
||||
]b4_translate[
|
||||
@};
|
||||
|
||||
immutable int user_token_number_max_ = ]b4_user_token_number_max[;
|
||||
// Last valid token kind.
|
||||
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[;
|
||||
|
||||
+29
-27
@@ -53,8 +53,9 @@ b4_use_push_for_pull_if([
|
||||
# allows them to be defined either in parse() when doing pull parsing,
|
||||
# or as class instance variable when doing push parsing.
|
||||
m4_define([b4_define_state],[[
|
||||
/* Lookahead and lookahead in internal form. */
|
||||
/* Lookahead token kind. */
|
||||
int yychar = YYEMPTY_;
|
||||
/* Lookahead symbol kind. */
|
||||
SymbolKind yytoken = null;
|
||||
|
||||
/* State. */
|
||||
@@ -79,7 +80,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 +603,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 +614,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 +629,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 +745,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 +780,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 +934,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 +982,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,27 +1072,28 @@ 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)])[);
|
||||
}]])[
|
||||
|
||||
/* YYTRANSLATE_(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
|
||||
as returned by yylex, with out-of-bounds checking. */
|
||||
private static final SymbolKind yytranslate_ (int t)
|
||||
private static final SymbolKind yytranslate_(int t)
|
||||
]b4_api_token_raw_if(dnl
|
||||
[[ {
|
||||
return SymbolKind.get (t);
|
||||
return SymbolKind.get(t);
|
||||
}
|
||||
]],
|
||||
[[ {
|
||||
int user_token_number_max_ = ]b4_user_token_number_max[;
|
||||
// Last valid token kind.
|
||||
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...)
|
||||
|
||||
+97
-95
@@ -48,6 +48,10 @@ m4_define([b4_pure_if],
|
||||
## api.push-pull. ##
|
||||
## --------------- ##
|
||||
|
||||
# b4_pull_if, b4_push_if
|
||||
# ----------------------
|
||||
# Whether the pull/push APIs are needed. Both can be enabled.
|
||||
|
||||
b4_percent_define_default([[api.push-pull]], [[pull]])
|
||||
b4_percent_define_check_values([[[[api.push-pull]],
|
||||
[[pull]], [[push]], [[both]]]])
|
||||
@@ -155,7 +159,7 @@ m4_define([b4_rhs_location],
|
||||
# Declare the variables that are global, or local to YYPARSE if
|
||||
# pure-parser.
|
||||
m4_define([b4_declare_scanner_communication_variables], [[
|
||||
/* The lookahead symbol. */
|
||||
/* Lookahead token kind. */
|
||||
int yychar;
|
||||
|
||||
]b4_pure_if([[
|
||||
@@ -176,68 +180,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 +296,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 +318,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 +575,8 @@ union yyalloc
|
||||
/* YYNSTATES -- Number of states. */
|
||||
#define YYNSTATES ]b4_states_number[
|
||||
|
||||
#define YYMAXUTOK ]b4_user_token_number_max[
|
||||
/* YYMAXUTOK -- Last valid token kind. */
|
||||
#define YYMAXUTOK ]b4_code_max[
|
||||
|
||||
|
||||
/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
|
||||
@@ -829,7 +813,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 +1429,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 +1488,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 +1510,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,14 +1542,14 @@ 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;]])[
|
||||
int yyn;
|
||||
/* The return value of yyparse. */
|
||||
int yyresult;
|
||||
/* Lookahead token as an internal (translated) token number. */
|
||||
/* Lookahead symbol kind. */
|
||||
yysymbol_kind_t yytoken = ]b4_symbol(-2, kind)[;
|
||||
/* The variables used to return semantic value and location from the
|
||||
action routines. */
|
||||
@@ -1572,14 +1569,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 +2050,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 +2075,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>
|
||||
|
||||
+18
-10
@@ -52,7 +52,7 @@
|
||||
<xsl:if test="nonterminal[@usefulness='useless-in-grammar']">
|
||||
<xsl:text>Nonterminals useless in grammar </xsl:text>
|
||||
<xsl:for-each select="nonterminal[@usefulness='useless-in-grammar']">
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:value-of select="@name"/>
|
||||
<xsl:text> </xsl:text>
|
||||
</xsl:for-each>
|
||||
@@ -65,7 +65,7 @@
|
||||
<xsl:text>Terminals unused in grammar </xsl:text>
|
||||
<xsl:for-each select="terminal[@usefulness='unused-in-grammar']">
|
||||
<xsl:sort select="@symbol-number" data-type="number"/>
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:value-of select="@name"/>
|
||||
<xsl:text> </xsl:text>
|
||||
</xsl:for-each>
|
||||
@@ -136,6 +136,7 @@
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="terminal">
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:value-of select="@name"/>
|
||||
<xsl:call-template name="line-wrap">
|
||||
<xsl:with-param name="first-line-length">
|
||||
@@ -148,6 +149,9 @@
|
||||
</xsl:with-param>
|
||||
<xsl:with-param name="line-length" select="66" />
|
||||
<xsl:with-param name="text">
|
||||
<xsl:if test="string-length(@type) != 0">
|
||||
<xsl:value-of select="concat(' <', @type, '>')"/>
|
||||
</xsl:if>
|
||||
<xsl:value-of select="concat(' (', @token-number, ')')"/>
|
||||
<xsl:for-each select="key('bison:ruleByRhs', @name)">
|
||||
<xsl:value-of select="concat(' ', @number)"/>
|
||||
@@ -157,14 +161,18 @@
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="nonterminal">
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:value-of select="@name"/>
|
||||
<xsl:if test="string-length(@type) != 0">
|
||||
<xsl:value-of select="concat(' <', @type, '>')"/>
|
||||
</xsl:if>
|
||||
<xsl:value-of select="concat(' (', @symbol-number, ')')"/>
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:variable name="output">
|
||||
<xsl:call-template name="line-wrap">
|
||||
<xsl:with-param name="line-length" select="66" />
|
||||
<xsl:with-param name="text">
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:if test="key('bison:ruleByLhs', @name)">
|
||||
<xsl:text>on@left:</xsl:text>
|
||||
<xsl:for-each select="key('bison:ruleByLhs', @name)">
|
||||
@@ -173,7 +181,7 @@
|
||||
</xsl:if>
|
||||
<xsl:if test="key('bison:ruleByRhs', @name)">
|
||||
<xsl:if test="key('bison:ruleByLhs', @name)">
|
||||
<xsl:text>, </xsl:text>
|
||||
<xsl:text> </xsl:text>
|
||||
</xsl:if>
|
||||
<xsl:text>on@right:</xsl:text>
|
||||
<xsl:for-each select="key('bison:ruleByRhs', @name)">
|
||||
@@ -300,7 +308,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 +319,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,12 +355,12 @@
|
||||
|
||||
<!-- RHS -->
|
||||
<xsl:for-each select="rhs/*">
|
||||
<xsl:if test="position() = $point + 1">
|
||||
<xsl:text> .</xsl:text>
|
||||
<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:text> .</xsl:text>
|
||||
<xsl:if test="position() = last() and position() = $dot">
|
||||
<xsl:text> •</xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
<xsl:if test="$lookaheads">
|
||||
|
||||
+79
-55
@@ -75,7 +75,7 @@
|
||||
ol.lower-alpha {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
.point {
|
||||
.dot {
|
||||
color: #cc0000;
|
||||
}
|
||||
#footer {
|
||||
@@ -227,6 +227,7 @@
|
||||
<xsl:text> </xsl:text>
|
||||
<p class="pre">
|
||||
<xsl:call-template name="style-rule-set">
|
||||
<xsl:with-param name="anchor" select="'true'" />
|
||||
<xsl:with-param
|
||||
name="rule-set" select="rules/rule[@usefulness!='useless-in-grammar']"
|
||||
/>
|
||||
@@ -238,9 +239,11 @@
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="style-rule-set">
|
||||
<xsl:param name="anchor"/>
|
||||
<xsl:param name="rule-set"/>
|
||||
<xsl:for-each select="$rule-set">
|
||||
<xsl:apply-templates select=".">
|
||||
<xsl:with-param name="anchor" select="$anchor"/>
|
||||
<xsl:with-param name="pad" select="'3'"/>
|
||||
<xsl:with-param name="prev-lhs">
|
||||
<xsl:if test="position()>1">
|
||||
@@ -306,9 +309,10 @@
|
||||
<xsl:text> Terminals, with rules where they appear</xsl:text>
|
||||
</h3>
|
||||
<xsl:text> </xsl:text>
|
||||
<p class="pre">
|
||||
<ul>
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:apply-templates select="terminal"/>
|
||||
</p>
|
||||
</ul>
|
||||
<xsl:text> </xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
@@ -318,41 +322,64 @@
|
||||
<xsl:text> Nonterminals, with rules where they appear</xsl:text>
|
||||
</h3>
|
||||
<xsl:text> </xsl:text>
|
||||
<p class="pre">
|
||||
<ul>
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:apply-templates
|
||||
select="nonterminal[@usefulness!='useless-in-grammar']"
|
||||
/>
|
||||
</p>
|
||||
</ul>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="terminal">
|
||||
<b><xsl:value-of select="@name"/></b>
|
||||
<xsl:value-of select="concat(' (', @token-number, ')')"/>
|
||||
<xsl:for-each select="key('bison:ruleByRhs', @name)">
|
||||
<xsl:apply-templates select="." mode="number-link"/>
|
||||
</xsl:for-each>
|
||||
<xsl:text> </xsl:text>
|
||||
<li>
|
||||
<b><xsl:value-of select="@name"/></b>
|
||||
<xsl:if test="string-length(@type) != 0">
|
||||
<xsl:value-of select="concat(' <', @type, '>')"/>
|
||||
</xsl:if>
|
||||
<xsl:value-of select="concat(' (', @token-number, ')')"/>
|
||||
<xsl:for-each select="key('bison:ruleByRhs', @name)">
|
||||
<xsl:apply-templates select="." mode="number-link"/>
|
||||
</xsl:for-each>
|
||||
</li>
|
||||
<xsl:text> </xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="nonterminal">
|
||||
<b><xsl:value-of select="@name"/></b>
|
||||
<xsl:value-of select="concat(' (', @symbol-number, ')')"/>
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:if test="key('bison:ruleByLhs', @name)">
|
||||
<xsl:text>on left:</xsl:text>
|
||||
<xsl:for-each select="key('bison:ruleByLhs', @name)">
|
||||
<xsl:apply-templates select="." mode="number-link"/>
|
||||
</xsl:for-each>
|
||||
</xsl:if>
|
||||
<xsl:if test="key('bison:ruleByRhs', @name)">
|
||||
<xsl:if test="key('bison:ruleByLhs', @name)">
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:text> </xsl:text>
|
||||
<li>
|
||||
<b><xsl:value-of select="@name"/></b>
|
||||
<xsl:if test="string-length(@type) != 0">
|
||||
<xsl:value-of select="concat(' <', @type, '>')"/>
|
||||
</xsl:if>
|
||||
<xsl:text>on right:</xsl:text>
|
||||
<xsl:for-each select="key('bison:ruleByRhs', @name)">
|
||||
<xsl:apply-templates select="." mode="number-link"/>
|
||||
</xsl:for-each>
|
||||
</xsl:if>
|
||||
<xsl:value-of select="concat(' (', @symbol-number, ')')"/>
|
||||
<xsl:text> </xsl:text>
|
||||
<ul>
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:if test="key('bison:ruleByLhs', @name)">
|
||||
<xsl:text> </xsl:text>
|
||||
<li>
|
||||
<xsl:text>on left:</xsl:text>
|
||||
<xsl:for-each select="key('bison:ruleByLhs', @name)">
|
||||
<xsl:apply-templates select="." mode="number-link"/>
|
||||
</xsl:for-each>
|
||||
</li>
|
||||
<xsl:text> </xsl:text>
|
||||
</xsl:if>
|
||||
<xsl:if test="key('bison:ruleByRhs', @name)">
|
||||
<xsl:text> </xsl:text>
|
||||
<li>
|
||||
<xsl:text>on right:</xsl:text>
|
||||
<xsl:for-each select="key('bison:ruleByRhs', @name)">
|
||||
<xsl:apply-templates select="." mode="number-link"/>
|
||||
</xsl:for-each>
|
||||
</li>
|
||||
<xsl:text> </xsl:text>
|
||||
</xsl:if>
|
||||
<xsl:text> </xsl:text>
|
||||
</ul>
|
||||
<xsl:text> </xsl:text>
|
||||
</li>
|
||||
<xsl:text> </xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
@@ -385,7 +412,7 @@
|
||||
<xsl:value-of select="concat('state_', @number)"/>
|
||||
</xsl:attribute>
|
||||
</a>
|
||||
<xsl:text>state </xsl:text>
|
||||
<xsl:text>State </xsl:text>
|
||||
<xsl:value-of select="@number"/>
|
||||
</h3>
|
||||
<xsl:text> </xsl:text>
|
||||
@@ -457,35 +484,44 @@
|
||||
<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>
|
||||
</xsl:apply-templates>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
anchor = 'true': define as an <a> anchor.
|
||||
itemset = 'true': show the items.
|
||||
-->
|
||||
<xsl:template match="rule">
|
||||
<xsl:param name="anchor"/>
|
||||
<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()])">
|
||||
<xsl:text> </xsl:text>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:if test="$itemset != 'true'">
|
||||
<a>
|
||||
<xsl:attribute name="name">
|
||||
<xsl:value-of select="concat('rule_', @number)"/>
|
||||
</xsl:attribute>
|
||||
</a>
|
||||
</xsl:if>
|
||||
<xsl:text> </xsl:text>
|
||||
|
||||
<xsl:choose>
|
||||
<xsl:when test="$itemset = 'true'">
|
||||
<xsl:when test="$anchor = 'true'">
|
||||
<a>
|
||||
<xsl:attribute name="name">
|
||||
<xsl:value-of select="concat('rule_', @number)"/>
|
||||
</xsl:attribute>
|
||||
<xsl:call-template name="lpad">
|
||||
<xsl:with-param name="str" select="string(@number)"/>
|
||||
<xsl:with-param name="pad" select="number($pad)"/>
|
||||
</xsl:call-template>
|
||||
</a>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<a>
|
||||
<xsl:attribute name="href">
|
||||
<xsl:value-of select="concat('#rule_', @number)"/>
|
||||
@@ -495,25 +531,13 @@
|
||||
<xsl:with-param name="pad" select="number($pad)"/>
|
||||
</xsl:call-template>
|
||||
</a>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:call-template name="lpad">
|
||||
<xsl:with-param name="str" select="string(@number)"/>
|
||||
<xsl:with-param name="pad" select="number($pad)"/>
|
||||
</xsl:call-template>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<xsl:text> </xsl:text>
|
||||
|
||||
<!-- LHS -->
|
||||
<xsl:choose>
|
||||
<xsl:when test="$itemset != 'true' and $prev-lhs = lhs[text()]">
|
||||
<xsl:call-template name="lpad">
|
||||
<xsl:with-param name="str" select="'|'"/>
|
||||
<xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 2"/>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
<xsl:when test="$itemset = 'true' and $prev-lhs = lhs[text()]">
|
||||
<xsl:when test="$prev-lhs = lhs[text()]">
|
||||
<xsl:call-template name="lpad">
|
||||
<xsl:with-param name="str" select="'|'"/>
|
||||
<xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 2"/>
|
||||
@@ -529,14 +553,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
|
||||
|
||||
+1059
-300
File diff suppressed because it is too large
Load Diff
+23
@@ -0,0 +1,23 @@
|
||||
%union
|
||||
{
|
||||
int ival;
|
||||
const char *sval;
|
||||
}
|
||||
|
||||
%token <ival> NUM
|
||||
%nterm <ival> exp
|
||||
%token <sval> STR
|
||||
%nterm <sval> useless
|
||||
|
||||
%left '+' '-'
|
||||
%left '*'
|
||||
|
||||
%%
|
||||
exp:
|
||||
exp '+' exp
|
||||
| exp '-' exp
|
||||
| exp '*' exp
|
||||
| exp '/' exp
|
||||
| NUM
|
||||
;
|
||||
useless: STR;
|
||||
@@ -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]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
%%
|
||||
stmt:
|
||||
expr
|
||||
| if_stmt
|
||||
;
|
||||
|
||||
if_stmt:
|
||||
"if" expr "then" stmt
|
||||
| "if" expr "then" stmt "else" stmt
|
||||
;
|
||||
|
||||
expr:
|
||||
"identifier"
|
||||
@@ -0,0 +1,10 @@
|
||||
%%
|
||||
sequence:
|
||||
%empty
|
||||
| maybeword
|
||||
| sequence "word"
|
||||
;
|
||||
maybeword:
|
||||
%empty
|
||||
| "word"
|
||||
;
|
||||
-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
|
||||
|
||||
+10
-1
@@ -53,7 +53,9 @@ push-parser model.
|
||||
This example demonstrates best practices when using Bison.
|
||||
- Its hand-written scanner tracks locations.
|
||||
- Its interface is pure.
|
||||
- It uses the `error` token to get error recovery.
|
||||
- It uses %params to pass user information to the parser and scanner.
|
||||
- Its scanner uses the `error` token to signal lexical errors and enter
|
||||
error recovery.
|
||||
- Its interface is "incremental", well suited for interaction: it uses the
|
||||
push-parser API to feed the parser with the incoming tokens.
|
||||
- It features an interactive command line with completion based on the
|
||||
@@ -62,6 +64,13 @@ This example demonstrates best practices when using Bison.
|
||||
messages.
|
||||
- It uses a custom syntax error with location, lookahead correction and
|
||||
token internationalization.
|
||||
- Error messages quote the source with squiggles that underline the error:
|
||||
```
|
||||
> 123 456
|
||||
1.5-7: syntax error: expected end of file or + or - or * or / or ^ before number
|
||||
1 | 123 456
|
||||
| ^~~
|
||||
```
|
||||
- It supports debug traces with semantic values.
|
||||
- It uses named references instead of the traditional $1, $2, etc.
|
||||
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
This example demonstrates best practices when using Bison.
|
||||
- Its hand-written scanner tracks locations.
|
||||
- Its interface is pure.
|
||||
- It uses the `error` token to get error recovery.
|
||||
- It uses %params to pass user information to the parser and scanner.
|
||||
- Its scanner uses the `error` token to signal lexical errors and enter
|
||||
error recovery.
|
||||
- Its interface is "incremental", well suited for interaction: it uses the
|
||||
push-parser API to feed the parser with the incoming tokens.
|
||||
- It features an interactive command line with completion based on the
|
||||
@@ -11,6 +13,13 @@ This example demonstrates best practices when using Bison.
|
||||
messages.
|
||||
- It uses a custom syntax error with location, lookahead correction and
|
||||
token internationalization.
|
||||
- Error messages quote the source with squiggles that underline the error:
|
||||
```
|
||||
> 123 456
|
||||
1.5-7: syntax error: expected end of file or + or - or * or / or ^ before number
|
||||
1 | 123 456
|
||||
| ^~~
|
||||
```
|
||||
- It supports debug traces with semantic values.
|
||||
- It uses named references instead of the traditional $1, $2, etc.
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -101,14 +101,28 @@ cat >input <<EOF
|
||||
EOF
|
||||
run 0 '> *
|
||||
> ''
|
||||
err: 1.1: syntax error: expected end of file or - or ( or exit or number or function etc., before *'
|
||||
err: 1.1: syntax error: expected end of file or - or ( or exit or number or function etc., before *
|
||||
err: 1 | *
|
||||
err: | ^'
|
||||
|
||||
# Underline long errors.
|
||||
cat >input <<EOF
|
||||
123 123456
|
||||
EOF
|
||||
run 0 '> 123 123456
|
||||
> ''
|
||||
err: 1.5-10: syntax error: expected end of file or + or - or * or / or ^ before number
|
||||
err: 1 | 123 123456
|
||||
err: | ^~~~~~'
|
||||
|
||||
cat >input <<EOF
|
||||
1 + 2 * * 3
|
||||
EOF
|
||||
run 0 '> 1 + 2 * * 3
|
||||
> ''
|
||||
err: 1.9: syntax error: expected - or ( or number or function or variable before *'
|
||||
err: 1.9: syntax error: expected - or ( or number or function or variable before *
|
||||
err: 1 | 1 + 2 * * 3
|
||||
err: | ^'
|
||||
|
||||
cat >input <<EOF
|
||||
1 / 0
|
||||
@@ -132,8 +146,14 @@ run 0 '> ((1 ++ 2) ** 3)
|
||||
1332
|
||||
> ''
|
||||
err: 1.6: syntax error: expected - or ( or number or function or variable before +
|
||||
err: 1 | ((1 ++ 2) ** 3)
|
||||
err: | ^
|
||||
err: 2.5: syntax error: expected - or ( or number or function or variable before +
|
||||
err: 2.16: syntax error: expected - or ( or number or function or variable before *'
|
||||
err: 2 | (1 ++ 2) + (3 ** 4)
|
||||
err: | ^
|
||||
err: 2.16: syntax error: expected - or ( or number or function or variable before *
|
||||
err: 2 | (1 ++ 2) + (3 ** 4)
|
||||
err: | ^'
|
||||
|
||||
# The rule "( error )" should work even if there are no tokens between "(" and ")".
|
||||
cat >input <<EOF
|
||||
@@ -142,7 +162,9 @@ EOF
|
||||
run 0 '> ()
|
||||
666
|
||||
> ''
|
||||
err: 1.2: syntax error: expected - or ( or number or function or variable before )'
|
||||
err: 1.2: syntax error: expected - or ( or number or function or variable before )
|
||||
err: 1 | ()
|
||||
err: | ^'
|
||||
|
||||
|
||||
cat >input <<EOF
|
||||
@@ -189,6 +211,8 @@ err: LAC: checking lookahead function: S5
|
||||
err: LAC: checking lookahead variable: S6
|
||||
err: LAC: checking lookahead NEG: Err
|
||||
err: 1.2: syntax error: expected - or ( or number or function or variable before +
|
||||
err: 1 | (+_)
|
||||
err: | ^
|
||||
err: LAC: initial context discarded due to error recovery
|
||||
err: Shifting token error (1.2: )
|
||||
err: Entering state 10
|
||||
@@ -269,8 +293,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
|
||||
@@ -286,7 +310,9 @@ run 0 '> (1+
|
||||
( - atan cos exp ln number sin sqrt
|
||||
> (1+
|
||||
> ''
|
||||
err: 1.4: syntax error: expected - or ( or number or function or variable before end of file'
|
||||
err: 1.4: syntax error: expected - or ( or number or function or variable before end of file
|
||||
err: 1 | (1+
|
||||
err: | ^'
|
||||
|
||||
# Check the completion of a word.
|
||||
sed -e 's/\\t/ /g' >input <<EOF
|
||||
@@ -294,7 +320,9 @@ sed -e 's/\\t/ /g' >input <<EOF
|
||||
EOF
|
||||
run 0 '> (atan ( ''
|
||||
> ''
|
||||
err: 1.9: syntax error: expected - or ( or number or function or variable before end of file'
|
||||
err: 1.9: syntax error: expected - or ( or number or function or variable before end of file
|
||||
err: 1 | (atan ( ''
|
||||
err: | ^'
|
||||
|
||||
# Check the completion at the very beginning.
|
||||
sed -e 's/\\t/ /g' >input <<EOF
|
||||
@@ -306,3 +334,28 @@ 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.3: syntax error: expected - or ( or number or function or variable before +
|
||||
err: 1 | 1++ ''
|
||||
err: | ^
|
||||
'
|
||||
|
||||
# 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.4: syntax error: expected - or ( or number or function or variable before +
|
||||
err: 1 | (1++2) + 3 + ''
|
||||
err: | ^
|
||||
err: 1.15: syntax error: expected - or ( or number or function or variable before end of file
|
||||
err: 1 | (1++2) + 3 + ''
|
||||
err: | ^
|
||||
'
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+112
-34
@@ -1,7 +1,26 @@
|
||||
%require "3.6"
|
||||
/* Parser and scanner for bistromathic. -*- C -*-
|
||||
|
||||
Copyright (C) 2019-2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Compiler Compiler.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
%require "3.7"
|
||||
|
||||
// Emitted on top of the implementation file.
|
||||
%code top {
|
||||
#include <assert.h>
|
||||
#include <ctype.h> // isdigit
|
||||
#include <locale.h> // LC_ALL
|
||||
#include <math.h> // cos, sin, etc.
|
||||
@@ -25,6 +44,7 @@
|
||||
#endif
|
||||
}
|
||||
|
||||
// Emitted in the header file, before the definition of YYSTYPE.
|
||||
%code requires {
|
||||
// Function type.
|
||||
typedef double (func_t) (double);
|
||||
@@ -45,19 +65,34 @@
|
||||
|
||||
symrec *putsym (char const *name, int sym_type);
|
||||
symrec *getsym (char const *name);
|
||||
|
||||
// Exchanging information with the parser.
|
||||
typedef struct
|
||||
{
|
||||
// Whether to not emit error messages.
|
||||
int silent;
|
||||
// The current input line.
|
||||
const char *line;
|
||||
} user_context;
|
||||
}
|
||||
|
||||
// Emitted in the header file, after the definition of YYSTYPE.
|
||||
%code provides {
|
||||
# ifndef __attribute__
|
||||
# ifndef __GNUC__
|
||||
# define __attribute__(Spec) /* empty */
|
||||
# endif
|
||||
# endif
|
||||
int yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc);
|
||||
void yyerror (YYLTYPE *loc, char const *format, ...)
|
||||
__attribute__ ((__format__ (__printf__, 2, 3)));
|
||||
|
||||
yytoken_kind_t
|
||||
yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc,
|
||||
const user_context *uctx);
|
||||
void yyerror (YYLTYPE *loc, const user_context *uctx,
|
||||
char const *format, ...)
|
||||
__attribute__ ((__format__ (__printf__, 3, 4)));
|
||||
}
|
||||
|
||||
// Emitted in the implementation file.
|
||||
%code {
|
||||
#if defined ENABLE_NLS && ENABLE_NLS
|
||||
# define _(Msgid) gettext (Msgid)
|
||||
@@ -69,6 +104,9 @@
|
||||
int done = 0;
|
||||
}
|
||||
|
||||
// Include the header in the implementation rather than duplicating it.
|
||||
%define api.header.include {"parse.h"}
|
||||
|
||||
// Don't share global variables between the scanner and the parser.
|
||||
%define api.pure full
|
||||
|
||||
@@ -91,6 +129,9 @@
|
||||
// Generate the parser description file (calc.output).
|
||||
%verbose
|
||||
|
||||
// User information exchanged with the parser and scanner.
|
||||
%param {const user_context *uctx}
|
||||
|
||||
// Generate YYSTYPE from the types assigned to symbols.
|
||||
%define api.value.type union
|
||||
%token
|
||||
@@ -146,7 +187,7 @@ exp:
|
||||
{
|
||||
if ($r == 0)
|
||||
{
|
||||
yyerror (&@$, "error: division by zero");
|
||||
yyerror (&@$, uctx, "error: division by zero");
|
||||
YYERROR;
|
||||
}
|
||||
else
|
||||
@@ -218,7 +259,7 @@ getsym (char const *name)
|
||||
}
|
||||
|
||||
// How many symbols are registered.
|
||||
int
|
||||
static int
|
||||
symbol_count (void)
|
||||
{
|
||||
int res = 0;
|
||||
@@ -232,8 +273,9 @@ symbol_count (void)
|
||||
| Scanner. |
|
||||
`----------*/
|
||||
|
||||
int
|
||||
yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc)
|
||||
yytoken_kind_t
|
||||
yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc,
|
||||
const user_context *uctx)
|
||||
{
|
||||
int c;
|
||||
|
||||
@@ -268,7 +310,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 +327,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)
|
||||
@@ -301,7 +345,7 @@ yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc)
|
||||
|
||||
// Stray characters.
|
||||
default:
|
||||
yyerror (yylloc, "syntax error: invalid character: %c", c);
|
||||
yyerror (yylloc, uctx, "syntax error: invalid character: %c", c);
|
||||
return TOK_YYerror;
|
||||
}
|
||||
}
|
||||
@@ -312,7 +356,7 @@ yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc)
|
||||
`---------*/
|
||||
|
||||
|
||||
const char *
|
||||
static const char *
|
||||
error_format_string (int argc)
|
||||
{
|
||||
switch (argc)
|
||||
@@ -339,8 +383,11 @@ error_format_string (int argc)
|
||||
|
||||
|
||||
int
|
||||
yyreport_syntax_error (const yypcontext_t *ctx)
|
||||
yyreport_syntax_error (const yypcontext_t *ctx, const user_context *uctx)
|
||||
{
|
||||
if (uctx->silent)
|
||||
return 0;
|
||||
|
||||
enum { ARGS_MAX = 6 };
|
||||
yysymbol_kind_t arg[ARGS_MAX];
|
||||
int argsize = yypcontext_expected_tokens (ctx, arg, ARGS_MAX);
|
||||
@@ -351,11 +398,12 @@ yyreport_syntax_error (const yypcontext_t *ctx)
|
||||
argsize = ARGS_MAX;
|
||||
const char *format = error_format_string (1 + argsize + too_many_expected_tokens);
|
||||
|
||||
const YYLTYPE *loc = yypcontext_location (ctx);
|
||||
while (*format)
|
||||
// %@: location.
|
||||
if (format[0] == '%' && format[1] == '@')
|
||||
{
|
||||
YY_LOCATION_PRINT (stderr, *yypcontext_location (ctx));
|
||||
YY_LOCATION_PRINT (stderr, *loc);
|
||||
format += 2;
|
||||
}
|
||||
// %u: unexpected token.
|
||||
@@ -380,13 +428,25 @@ yyreport_syntax_error (const yypcontext_t *ctx)
|
||||
++format;
|
||||
}
|
||||
fputc ('\n', stderr);
|
||||
|
||||
// Quote the source line.
|
||||
{
|
||||
fprintf (stderr, "%5d | %s\n", loc->first_line, uctx->line);
|
||||
fprintf (stderr, "%5s | %*s", "", loc->first_column, "^");
|
||||
for (int i = loc->last_column - loc->first_column - 1; 0 < i; --i)
|
||||
putc ('~', stderr);
|
||||
putc ('\n', stderr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Called by yyparse on error.
|
||||
void yyerror (YYLTYPE *loc, char const *format, ...)
|
||||
void yyerror (YYLTYPE *loc, const user_context *uctx, char const *format, ...)
|
||||
{
|
||||
if (uctx->silent)
|
||||
return;
|
||||
|
||||
YY_LOCATION_PRINT (stderr, *loc);
|
||||
fputs (": ", stderr);
|
||||
va_list args;
|
||||
@@ -407,7 +467,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,13 +479,16 @@ 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)
|
||||
{
|
||||
user_context uctx = {0, line};
|
||||
yypstate *ps = yypstate_new ();
|
||||
int status = 0;
|
||||
do {
|
||||
YYSTYPE lval;
|
||||
status = yypush_parse (ps, yylex (&line, &lval, lloc), &lval, lloc);
|
||||
yytoken_kind_t token = yylex (&line, &lval, lloc, &uctx);
|
||||
status = yypush_parse (ps, token, &lval, lloc, &uctx);
|
||||
} while (status == YYPUSH_MORE);
|
||||
yypstate_delete (ps);
|
||||
lloc->last_line++;
|
||||
@@ -433,27 +497,36 @@ 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)
|
||||
{
|
||||
YYDPRINTF ((stderr, "expected_tokens (\"%s\")", input));
|
||||
user_context uctx = {1, input};
|
||||
|
||||
// Parse the current state of the line.
|
||||
yypstate *ps = yypstate_new ();
|
||||
int status = 0;
|
||||
YYLTYPE lloc = { 1, 1, 1, 1 };
|
||||
do {
|
||||
YYLTYPE lloc;
|
||||
YYSTYPE lval;
|
||||
int token = yylex (&input, &lval, &lloc);
|
||||
yytoken_kind_t token = yylex (&input, &lval, &lloc, &uctx);
|
||||
// Don't let the parse know when we reach the end of input.
|
||||
if (!token)
|
||||
if (token == TOK_YYEOF)
|
||||
break;
|
||||
status = yypush_parse (ps, token, &lval, &lloc);
|
||||
status = yypush_parse (ps, token, &lval, &lloc, &uctx);
|
||||
} 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 +536,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 +546,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 +586,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 +612,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 +632,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)
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
/* Parser for lexcalc. -*- C -*-
|
||||
|
||||
Copyright (C) 2018-2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Compiler Compiler.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
// Prologue (directives).
|
||||
%expect 0
|
||||
|
||||
@@ -19,6 +38,9 @@
|
||||
#include <stdlib.h> // getenv.
|
||||
}
|
||||
|
||||
// Include the header in the implementation rather than duplicating it.
|
||||
%define api.header.include {"parse.h"}
|
||||
|
||||
// Don't share global variables between the scanner and the parser.
|
||||
%define api.pure full
|
||||
|
||||
|
||||
@@ -1,10 +1,29 @@
|
||||
/* Prologue (directives). -*- C -*- */
|
||||
/* Scanner for lexcalc. -*- C -*-
|
||||
|
||||
Copyright (C) 2018-2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Compiler Compiler.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Prologue (directives). */
|
||||
|
||||
/* Disable Flex features we don't need, to avoid warnings. */
|
||||
%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 +31,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,26 @@
|
||||
/* Parser and scanner for pushcalc. -*- C -*-
|
||||
|
||||
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Compiler Compiler.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
%code top {
|
||||
#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 +100,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)
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
/* Parser for reccalc. -*- C -*-
|
||||
|
||||
Copyright (C) 2019-2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Compiler Compiler.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
// Prologue (directives).
|
||||
%expect 0
|
||||
|
||||
@@ -46,14 +65,29 @@
|
||||
result parse (void);
|
||||
}
|
||||
|
||||
// Include the header in the implementation rather than duplicating it.
|
||||
%define api.header.include {"parse.h"}
|
||||
|
||||
// Don't share global variables between the scanner and the parser.
|
||||
%define api.pure full
|
||||
|
||||
// To avoid name clashes (e.g., with C's EOF) prefix token definitions
|
||||
// with TOK_ (e.g., TOK_EOF).
|
||||
%define api.token.prefix {TOK_}
|
||||
|
||||
// Generate YYSTYPE from the types assigned to symbols.
|
||||
%define api.value.type union
|
||||
%define parse.error verbose
|
||||
|
||||
// Error messages with "unexpected XXX, expected XXX...".
|
||||
%define parse.error detailed
|
||||
|
||||
// Enable run-time traces (yydebug).
|
||||
%define parse.trace
|
||||
|
||||
// Generate the parser description file (parse.output).
|
||||
%verbose
|
||||
|
||||
// Scanner and error count are exchanged between main, yyparse and yylex.
|
||||
// Scanner and error count are exchanged between main, yyparse and yylex.
|
||||
%param {yyscan_t scanner}{result *res}
|
||||
|
||||
%token
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
/* Scanner for reccalc. -*- C -*-
|
||||
|
||||
Copyright (C) 2019-2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Compiler Compiler.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Prologue (directives). -*- C -*- */
|
||||
|
||||
/* Disable Flex features we don't need, to avoid warnings. */
|
||||
@@ -32,9 +51,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
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
/* Parser and scanner for calc in D. -*- D -*-
|
||||
|
||||
Copyright (C) 2018-2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Compiler Compiler.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
%language "D"
|
||||
|
||||
%define api.parser.class {Calc}
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
/* Parser and scanner for calc in Java. -*- Java -*-
|
||||
|
||||
Copyright (C) 2018-2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Compiler Compiler.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
%language "Java"
|
||||
|
||||
%define api.parser.class {Calc}
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
/* Simple parser and scanner in Java. -*- Java -*-
|
||||
|
||||
Copyright (C) 2018-2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Compiler Compiler.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
%language "Java"
|
||||
|
||||
%define api.parser.class {Calc}
|
||||
|
||||
@@ -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: ffbb0ced8b...ac34618e85
@@ -18,7 +18,9 @@
|
||||
/asnprintf.c
|
||||
/asprintf.c
|
||||
/assure.h
|
||||
/attribute.h
|
||||
/basename-lgpl.c
|
||||
/basename-lgpl.h
|
||||
/basename.c
|
||||
/binary-io.c
|
||||
/binary-io.h
|
||||
@@ -117,10 +119,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 +151,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
|
||||
@@ -273,6 +313,7 @@
|
||||
/stdlib.h
|
||||
/stdlib.in.h
|
||||
/stpcpy.c
|
||||
/stpncpy.c
|
||||
/strchrnul.c
|
||||
/strchrnul.valgrind
|
||||
/strdup.c
|
||||
@@ -305,11 +346,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 +364,7 @@
|
||||
/unlink.c
|
||||
/unlocked-io.h
|
||||
/unsetenv.c
|
||||
/unused-parameter.h
|
||||
/vasnprintf.c
|
||||
/vasnprintf.h
|
||||
/vasprintf.c
|
||||
|
||||
+7
-2
@@ -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
|
||||
@@ -13,7 +13,6 @@
|
||||
/codeset.m4
|
||||
/config-h.m4
|
||||
/configmake.m4
|
||||
/dirname.m4
|
||||
/double-slash-root.m4
|
||||
/dup2.m4
|
||||
/eealloc.m4
|
||||
@@ -25,6 +24,7 @@
|
||||
/exponentl.m4
|
||||
/extensions.m4
|
||||
/extern-inline.m4
|
||||
/extern-inline.m4~
|
||||
/fatal-signal.m4
|
||||
/fcntl-o.m4
|
||||
/fcntl.m4
|
||||
@@ -57,7 +57,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
|
||||
@@ -172,6 +175,7 @@
|
||||
/stdio_h.m4
|
||||
/stdlib_h.m4
|
||||
/stpcpy.m4
|
||||
/stpncpy.m4
|
||||
/strchrnul.m4
|
||||
/strdup.m4
|
||||
/strerror.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
|
||||
|
||||
+165
-180
@@ -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)
|
||||
{
|
||||
@@ -172,10 +169,10 @@ AnnotationList__compute_conflicted_tokens (bitset shift_tokens,
|
||||
bitset_copy (tokens, shift_tokens);
|
||||
for (int i = 0; i < reds->num; ++i)
|
||||
{
|
||||
bitset_and (conflicted_tokens_rule, tokens, reds->lookahead_tokens[i]);
|
||||
bitset_and (conflicted_tokens_rule, tokens, reds->lookaheads[i]);
|
||||
bitset_or (conflicted_tokens,
|
||||
conflicted_tokens, conflicted_tokens_rule);
|
||||
bitset_or (tokens, tokens, reds->lookahead_tokens[i]);
|
||||
bitset_or (tokens, tokens, reds->lookaheads[i]);
|
||||
/* Check that rules are sorted on rule number or the next step in
|
||||
AnnotationList__compute_from_inadequacies will misbehave. */
|
||||
aver (i == 0 || reds->rules[i-1] < reds->rules[i]);
|
||||
@@ -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:
|
||||
@@ -409,7 +401,7 @@ AnnotationList__compute_from_inadequacies (
|
||||
struct obstack *annotations_obstackp,
|
||||
InadequacyListNodeCount *inadequacy_list_node_count)
|
||||
{
|
||||
/* Return an empty list if s->lookahead_tokens = NULL. */
|
||||
/* Return an empty list if s->lookaheads = NULL. */
|
||||
if (s->consistent)
|
||||
return;
|
||||
|
||||
@@ -425,16 +417,12 @@ 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. */
|
||||
{
|
||||
for (int rule_i = 0; rule_i < s->reductions->num; ++rule_i)
|
||||
if (bitset_test (s->reductions->lookahead_tokens[rule_i],
|
||||
if (bitset_test (s->reductions->lookaheads[rule_i],
|
||||
conflicted_token))
|
||||
++contribution_count;
|
||||
if (bitset_test (shift_tokens, conflicted_token))
|
||||
@@ -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. */
|
||||
{
|
||||
@@ -452,7 +445,7 @@ AnnotationList__compute_from_inadequacies (
|
||||
for (int rule_i = 0; rule_i < s->reductions->num; ++rule_i)
|
||||
{
|
||||
rule *the_rule = s->reductions->rules[rule_i];
|
||||
if (bitset_test (s->reductions->lookahead_tokens[rule_i],
|
||||
if (bitset_test (s->reductions->lookaheads[rule_i],
|
||||
conflicted_token))
|
||||
{
|
||||
bitset_set (actions, rule_i);
|
||||
@@ -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_ */
|
||||
|
||||
+68
-19
@@ -35,6 +35,13 @@
|
||||
#include "getargs.h"
|
||||
#include "quote.h"
|
||||
|
||||
// The URL of the manual page about diagnostics. Use the per-node
|
||||
// manual, to avoid downloading repeatedly the whole manual over the
|
||||
// Internet.
|
||||
static const char *diagnostics_url
|
||||
= "https://www.gnu.org/software/bison/manual/html_node/Diagnostics.html";
|
||||
|
||||
|
||||
err_status complaint_status = status_none;
|
||||
|
||||
bool warnings_are_errors = false;
|
||||
@@ -96,6 +103,20 @@ end_use_class (const char *s, FILE *out)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
begin_hyperlink (FILE *out, const char *ref)
|
||||
{
|
||||
if (out == stderr)
|
||||
styled_ostream_set_hyperlink (errstream, ref, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
end_hyperlink (FILE *out)
|
||||
{
|
||||
if (out == stderr)
|
||||
styled_ostream_set_hyperlink (errstream, NULL, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
flush (FILE *out)
|
||||
{
|
||||
@@ -104,6 +125,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 +152,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 +160,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 +169,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 +326,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");
|
||||
@@ -410,9 +448,20 @@ warnings_print_categories (warnings warn_flags, FILE *out)
|
||||
const char* style = severity_style (s);
|
||||
fputs (" [", out);
|
||||
begin_use_class (style, out);
|
||||
fprintf (out, "-W%s%s",
|
||||
s == severity_error ? "error=" : "",
|
||||
argmatch_warning_argument (&w));
|
||||
// E.g., "counterexamples".
|
||||
const char *warning = argmatch_warning_argument (&w);
|
||||
char ref[200];
|
||||
snprintf (ref, sizeof ref,
|
||||
"%s#W%s", diagnostics_url, warning);
|
||||
begin_hyperlink (out, ref);
|
||||
ostream_printf (errstream,
|
||||
"-W%s%s",
|
||||
s == severity_error ? "error=" : "",
|
||||
warning);
|
||||
end_hyperlink (out);
|
||||
// Because we mix stdio with ostream I/O, we need to flush
|
||||
// here for sake of color == debug.
|
||||
flush (out);
|
||||
end_use_class (style, out);
|
||||
fputc (']', out);
|
||||
/* Display only the first match, the second is "-Wall". */
|
||||
|
||||
+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. */
|
||||
|
||||
+87
-48
@@ -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,19 +245,19 @@ 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). |
|
||||
`--------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
flush_reduce (bitset lookahead_tokens, int token)
|
||||
flush_reduce (bitset lookaheads, int token)
|
||||
{
|
||||
bitset_reset (lookahead_tokens, token);
|
||||
bitset_reset (lookaheads, 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. |
|
||||
@@ -268,14 +275,14 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
|
||||
/* Find the rule to reduce by to get precedence of reduction. */
|
||||
rule *redrule = reds->rules[ruleno];
|
||||
int redprec = redrule->prec->prec;
|
||||
bitset lookahead_tokens = reds->lookahead_tokens[ruleno];
|
||||
bitset lookaheads = reds->lookaheads[ruleno];
|
||||
|
||||
for (symbol_number i = 0; i < ntokens; ++i)
|
||||
if (bitset_test (lookahead_tokens, i)
|
||||
if (bitset_test (lookaheads, i)
|
||||
&& 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)
|
||||
@@ -288,7 +295,7 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
|
||||
{
|
||||
register_precedence (i, redrule->prec->number);
|
||||
log_resolution (redrule, i, shift_resolution);
|
||||
flush_reduce (lookahead_tokens, i);
|
||||
flush_reduce (lookaheads, i);
|
||||
}
|
||||
else
|
||||
/* Matching precedence levels.
|
||||
@@ -309,7 +316,7 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
|
||||
case right_assoc:
|
||||
register_assoc (i, redrule->prec->number);
|
||||
log_resolution (redrule, i, right_resolution);
|
||||
flush_reduce (lookahead_tokens, i);
|
||||
flush_reduce (lookaheads, i);
|
||||
break;
|
||||
|
||||
case left_assoc:
|
||||
@@ -322,7 +329,7 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
|
||||
register_assoc (i, redrule->prec->number);
|
||||
log_resolution (redrule, i, nonassoc_resolution);
|
||||
flush_shift (s, i);
|
||||
flush_reduce (lookahead_tokens, i);
|
||||
flush_reduce (lookaheads, i);
|
||||
/* Record an explicit error for this token. */
|
||||
errors[(*nerrs)++] = symbols[i];
|
||||
break;
|
||||
@@ -357,11 +364,12 @@ 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
|
||||
&& !bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set))
|
||||
if (reds->rules[i]->prec
|
||||
&& reds->rules[i]->prec->prec
|
||||
&& !bitset_disjoint_p (reds->lookaheads[i], lookahead_set))
|
||||
resolve_sr_conflict (s, i, errors, &nerrs);
|
||||
|
||||
if (nerrs)
|
||||
@@ -377,13 +385,13 @@ set_conflicts (state *s, symbol **errors)
|
||||
/* Loop over all rules which require lookahead in this state. Check
|
||||
for conflicts not resolved above.
|
||||
|
||||
reds->lookahead_tokens can be NULL if the LR type is LR(0). */
|
||||
if (reds->lookahead_tokens)
|
||||
reds->lookaheads can be NULL if the LR type is LR(0). */
|
||||
if (reds->lookaheads)
|
||||
for (int i = 0; i < reds->num; ++i)
|
||||
{
|
||||
if (!bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set))
|
||||
if (!bitset_disjoint_p (reds->lookaheads[i], lookahead_set))
|
||||
conflicts[s->number] = true;
|
||||
bitset_or (lookahead_set, lookahead_set, reds->lookahead_tokens[i]);
|
||||
bitset_or (lookahead_set, lookahead_set, reds->lookaheads[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,7 +460,7 @@ count_state_sr_conflicts (const state *s)
|
||||
}
|
||||
|
||||
for (int i = 0; i < reds->num; ++i)
|
||||
bitset_or (lookahead_set, lookahead_set, reds->lookahead_tokens[i]);
|
||||
bitset_or (lookahead_set, lookahead_set, reds->lookaheads[i]);
|
||||
|
||||
bitset_and (lookahead_set, lookahead_set, shift_set);
|
||||
|
||||
@@ -491,7 +499,7 @@ count_state_rr_conflicts (const state *s)
|
||||
{
|
||||
int count = 0;
|
||||
for (int j = 0; j < reds->num; ++j)
|
||||
count += bitset_test (reds->lookahead_tokens[j], i);
|
||||
count += bitset_test (reds->lookaheads[j], i);
|
||||
if (2 <= count)
|
||||
res += count-1;
|
||||
}
|
||||
@@ -526,7 +534,7 @@ count_rule_state_sr_conflicts (rule *r, state *s)
|
||||
for (int i = 0; i < reds->num; ++i)
|
||||
if (reds->rules[i] == r)
|
||||
{
|
||||
bitset lookaheads = reds->lookahead_tokens[i];
|
||||
bitset lookaheads = reds->lookaheads[i];
|
||||
int j;
|
||||
FOR_EACH_SHIFT (trans, j)
|
||||
res += bitset_test (lookaheads, TRANSITION_SYMBOL (trans, j));
|
||||
@@ -568,8 +576,8 @@ count_rule_state_rr_conflicts (rule *r, state *s)
|
||||
if (reds->rules[j] != r)
|
||||
{
|
||||
bitset_and (lookaheads,
|
||||
reds->lookahead_tokens[i],
|
||||
reds->lookahead_tokens[j]);
|
||||
reds->lookaheads[i],
|
||||
reds->lookaheads[j]);
|
||||
res += bitset_count (lookaheads);
|
||||
}
|
||||
bitset_free (lookaheads);
|
||||
@@ -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,10 @@ conflicts_print (void)
|
||||
expected_rr_conflicts = -1;
|
||||
}
|
||||
|
||||
/* Screams for factoring, but almost useless because of the
|
||||
different strings to translate. */
|
||||
// The warning flags used to emit a diagnostic, if we did.
|
||||
warnings unexpected_conflicts_warning = Wnone;
|
||||
/* The following two blocks scream for factoring, but i18n support
|
||||
would make it ugly. */
|
||||
{
|
||||
int total = count_sr_conflicts ();
|
||||
/* If %expect is not used, but %expect-rr is, then expect 0 sr. */
|
||||
@@ -682,16 +700,23 @@ 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);
|
||||
if (total)
|
||||
unexpected_conflicts_warning = complaint;
|
||||
}
|
||||
}
|
||||
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);
|
||||
unexpected_conflicts_warning = Wconflicts_sr;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
@@ -704,17 +729,31 @@ 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);
|
||||
if (total)
|
||||
unexpected_conflicts_warning = complaint;
|
||||
}
|
||||
}
|
||||
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);
|
||||
unexpected_conflicts_warning = Wconflicts_rr;
|
||||
}
|
||||
}
|
||||
|
||||
if (warning_is_enabled (Wcounterexamples))
|
||||
report_counterexamples ();
|
||||
else if (unexpected_conflicts_warning != Wnone)
|
||||
subcomplain (NULL, unexpected_conflicts_warning,
|
||||
_("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,36 @@
|
||||
/* 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.h"
|
||||
|
||||
// Init/deinit this module.
|
||||
void counterexample_init (void);
|
||||
void counterexample_free (void);
|
||||
|
||||
// Print the counterexamples for the conflicts of state S.
|
||||
//
|
||||
// Used both for the warnings on the terminal (OUT = stderr, PREFIX =
|
||||
// ""), and for the reports (OUT != stderr, PREFIX != "").
|
||||
void
|
||||
counterexample_report_state (const state *s, FILE *out, const char *prefix);
|
||||
|
||||
#endif /* COUNTEREXAMPLE_H */
|
||||
@@ -0,0 +1,444 @@
|
||||
/* 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 "glyphs.h"
|
||||
|
||||
#include <c-ctype.h>
|
||||
#include <gl_linked_list.h>
|
||||
#include <mbswidth.h>
|
||||
|
||||
#include "system.h"
|
||||
#include "complain.h"
|
||||
|
||||
struct derivation
|
||||
{
|
||||
symbol_number sym;
|
||||
derivation_list children;
|
||||
int reference_count;
|
||||
// Color assigned for styling. Guarantees that the derivation is
|
||||
// always displayed with the same color, independently of the order
|
||||
// in which the derivations are traversed.
|
||||
int color;
|
||||
};
|
||||
|
||||
static derivation d_dot = { -1, NULL, -1, -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;
|
||||
deriv->color = -1;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
max (int a, int b)
|
||||
{
|
||||
return a < b ? b : a;
|
||||
}
|
||||
|
||||
// Longest distance from root to leaf.
|
||||
static int
|
||||
derivation_depth (const derivation *deriv)
|
||||
{
|
||||
if (deriv->children)
|
||||
{
|
||||
// Children's depth cannot be 0, even if there are no children
|
||||
// (the case of a derivation with an empty RHS).
|
||||
int res = 1;
|
||||
derivation *child;
|
||||
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
|
||||
derivation_list_next (&it, &child);
|
||||
)
|
||||
res = max (res, derivation_depth (child));
|
||||
return res + 1;
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
all_spaces (const char *s)
|
||||
{
|
||||
while (c_isspace (*s))
|
||||
s++;
|
||||
return *s == '\0';
|
||||
}
|
||||
|
||||
// Printing the derivation as trees without trailing spaces is
|
||||
// painful: we cannot simply pad one "column" before moving to the
|
||||
// next:
|
||||
//
|
||||
// exp
|
||||
// ↳ x1 e1 foo1 x1
|
||||
// ↳ x2 ↳ ε ↳ foo2 ↳ x2
|
||||
// ↳ x3 ↳ foo3 ↳ x3
|
||||
// ↳ "X" • ↳ x1 foo4 ↳ "X"
|
||||
// ↳ x2 ↳ "quuux"
|
||||
// ↳ x3
|
||||
// ↳ "X"
|
||||
//
|
||||
// It's hard for a column to know that it's "last" to decide whether
|
||||
// to output the right-padding or not. So when we need to pad on the
|
||||
// right to complete a column, we don't output the spaces, we
|
||||
// accumulate the width of padding in *PADDING.
|
||||
//
|
||||
// Each time we actually print something (non space), we flush that
|
||||
// padding. When we _don't_ print something, its width is added to
|
||||
// the current padding.
|
||||
//
|
||||
// This function implements this.
|
||||
//
|
||||
// When COND is true, put S on OUT, preceded by *PADDING white spaces.
|
||||
// Otherwise add the width to *PADDING. Return the width of S.
|
||||
static int
|
||||
fputs_if (bool cond, FILE *out, int *padding, const char *s)
|
||||
{
|
||||
int res = mbswidth (s, 0);
|
||||
if (cond && !all_spaces (s))
|
||||
{
|
||||
fprintf (out, "%*s%s", *padding, "", s);
|
||||
*padding = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*padding += res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// The width taken to report this derivation recursively down to its
|
||||
// leaves.
|
||||
static int
|
||||
derivation_width (const derivation *deriv)
|
||||
{
|
||||
if (deriv->children)
|
||||
{
|
||||
const symbol *sym = symbols[deriv->sym];
|
||||
int self_width = mbswidth (sym->tag, 0);
|
||||
|
||||
// Arrow and space.
|
||||
int children_width = down_arrow_width;
|
||||
if (gl_list_size (deriv->children) == 0)
|
||||
// Empty rhs.
|
||||
children_width += empty_width;
|
||||
else
|
||||
{
|
||||
derivation *child;
|
||||
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
|
||||
derivation_list_next (&it, &child);
|
||||
)
|
||||
children_width
|
||||
+= derivation_separator_width + derivation_width (child);
|
||||
// No separator at the beginning.
|
||||
children_width -= derivation_separator_width;
|
||||
}
|
||||
return max (self_width, children_width);
|
||||
}
|
||||
else if (deriv == &d_dot)
|
||||
{
|
||||
return dot_width;
|
||||
}
|
||||
else // leaf.
|
||||
{
|
||||
const symbol *sym = symbols[deriv->sym];
|
||||
return mbswidth (sym->tag, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Print DERIV for DEPTH.
|
||||
//
|
||||
// The tree is printed from top to bottom with DEPTH ranging from 0 to
|
||||
// the total depth of the tree. DERIV should only printed when we
|
||||
// reach its depth, i.e., then DEPTH is 0.
|
||||
//
|
||||
// When DEPTH is 1 and we're on a subderivation, then we print the RHS
|
||||
// of the derivation (in DEPTH 0 we printed its LHS).
|
||||
//
|
||||
// Return the "logical printed" width. We might have not have reached
|
||||
// that width, in which case the missing spaces are in *PADDING.
|
||||
static int
|
||||
derivation_print_tree_impl (const derivation *deriv, FILE *out,
|
||||
int depth, int *padding)
|
||||
{
|
||||
const int width = derivation_width (deriv);
|
||||
|
||||
int res = 0;
|
||||
if (deriv->children)
|
||||
{
|
||||
const symbol *sym = symbols[deriv->sym];
|
||||
char style[20];
|
||||
snprintf (style, 20, "cex-%d", deriv->color);
|
||||
|
||||
if (depth == 0 || depth == 1)
|
||||
{
|
||||
begin_use_class (style, out);
|
||||
begin_use_class ("cex-step", out);
|
||||
}
|
||||
if (depth == 0)
|
||||
{
|
||||
res += fputs_if (true, out, padding, sym->tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
res += fputs_if (depth == 1, out, padding, down_arrow);
|
||||
if (gl_list_size (deriv->children) == 0)
|
||||
// Empty rhs.
|
||||
res += fputs_if (depth == 1, out, padding, empty);
|
||||
else
|
||||
{
|
||||
bool first = true;
|
||||
derivation *child;
|
||||
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
|
||||
derivation_list_next (&it, &child);
|
||||
)
|
||||
{
|
||||
if (!first)
|
||||
res += fputs_if (depth == 1, out, padding, derivation_separator);
|
||||
res += derivation_print_tree_impl (child, out, depth - 1, padding);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (depth == 0 || depth == 1)
|
||||
{
|
||||
end_use_class ("cex-step", out);
|
||||
end_use_class (style, out);
|
||||
}
|
||||
*padding += width - res;
|
||||
res = width;
|
||||
}
|
||||
else if (deriv == &d_dot)
|
||||
{
|
||||
if (depth == 0)
|
||||
begin_use_class ("cex-dot", out);
|
||||
res += fputs_if (depth == 0, out, padding, dot);
|
||||
if (depth == 0)
|
||||
end_use_class ("cex-dot", out);
|
||||
}
|
||||
else // leaf.
|
||||
{
|
||||
const symbol *sym = symbols[deriv->sym];
|
||||
if (depth == 0)
|
||||
begin_use_class ("cex-leaf", out);
|
||||
res += fputs_if (depth == 0, out, padding, sym->tag);
|
||||
if (depth == 0)
|
||||
end_use_class ("cex-leaf", out);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
derivation_print_tree (const derivation *deriv, FILE *out, const char *prefix)
|
||||
{
|
||||
fputc ('\n', out);
|
||||
for (int depth = 0, max_depth = derivation_depth (deriv);
|
||||
depth < max_depth; ++depth)
|
||||
{
|
||||
int padding = 0;
|
||||
fprintf (out, " %s", prefix);
|
||||
derivation_print_tree_impl (deriv, out, depth, &padding);
|
||||
fputc ('\n', out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Print DERIV, colored according to COUNTER.
|
||||
Return false if nothing is printed. */
|
||||
static bool
|
||||
derivation_print_flat_impl (derivation *deriv, FILE *out,
|
||||
bool leaves_only,
|
||||
int *counter, const char *prefix)
|
||||
{
|
||||
if (deriv->children)
|
||||
{
|
||||
const symbol *sym = symbols[deriv->sym];
|
||||
deriv->color = *counter;
|
||||
++*counter;
|
||||
char style[20];
|
||||
snprintf (style, 20, "cex-%d", deriv->color);
|
||||
begin_use_class (style, out);
|
||||
|
||||
if (!leaves_only)
|
||||
{
|
||||
fputs (prefix, out);
|
||||
begin_use_class ("cex-step", out);
|
||||
fprintf (out, "%s %s [ ", sym->tag, arrow);
|
||||
end_use_class ("cex-step", out);
|
||||
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_flat_impl (child, out,
|
||||
leaves_only, counter, prefix))
|
||||
{
|
||||
prefix = " ";
|
||||
res = true;
|
||||
}
|
||||
else if (!leaves_only)
|
||||
prefix = " ";
|
||||
}
|
||||
if (!leaves_only)
|
||||
{
|
||||
begin_use_class ("cex-step", out);
|
||||
if (res)
|
||||
fputs (" ]", out);
|
||||
else
|
||||
fputs ("]", out);
|
||||
end_use_class ("cex-step", out);
|
||||
}
|
||||
end_use_class (style, out);
|
||||
return res;
|
||||
}
|
||||
else if (deriv == &d_dot)
|
||||
{
|
||||
fputs (prefix, out);
|
||||
begin_use_class ("cex-dot", out);
|
||||
fputs (dot, out);
|
||||
end_use_class ("cex-dot", out);
|
||||
}
|
||||
else // leaf.
|
||||
{
|
||||
fputs (prefix, out);
|
||||
const symbol *sym = symbols[deriv->sym];
|
||||
begin_use_class ("cex-leaf", out);
|
||||
fprintf (out, "%s", sym->tag);
|
||||
end_use_class ("cex-leaf", out);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
derivation_print_flat (const derivation *deriv, FILE *out, const char *prefix)
|
||||
{
|
||||
int counter = 0;
|
||||
fputs (prefix, out);
|
||||
derivation_print_flat_impl ((derivation *)deriv, out, false, &counter, "");
|
||||
fputc ('\n', out);
|
||||
}
|
||||
|
||||
void
|
||||
derivation_print_leaves (const derivation *deriv, FILE *out)
|
||||
{
|
||||
int counter = 0;
|
||||
derivation_print_flat_impl ((derivation *)deriv, out, true, &counter, "");
|
||||
fputc ('\n', out);
|
||||
}
|
||||
|
||||
void
|
||||
derivation_print (const derivation *deriv, FILE *out, const char *prefix)
|
||||
{
|
||||
if (getenv ("YYFLAT"))
|
||||
derivation_print_flat (deriv, out, prefix);
|
||||
else
|
||||
derivation_print_tree (deriv, out, prefix);
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/* 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);
|
||||
}
|
||||
|
||||
// Number of symbols.
|
||||
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);
|
||||
void derivation_free (derivation *deriv);
|
||||
void derivation_retain (derivation *deriv);
|
||||
|
||||
// A derivation denoting the position of the dot.
|
||||
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_lookaheads },
|
||||
{ "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;
|
||||
}
|
||||
|
||||
+9
-6
@@ -77,8 +77,9 @@ enum report
|
||||
report_none = 0,
|
||||
report_states = 1 << 0,
|
||||
report_itemsets = 1 << 1,
|
||||
report_lookahead_tokens = 1 << 2,
|
||||
report_lookaheads = 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. */
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/* Graphical symbols.
|
||||
|
||||
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Compiler Compiler.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "glyphs.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <attribute.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <mbswidth.h>
|
||||
#include <unicodeio.h>
|
||||
|
||||
|
||||
glyph_buffer_t arrow;
|
||||
int arrow_width;
|
||||
|
||||
glyph_buffer_t down_arrow;
|
||||
int down_arrow_width;
|
||||
|
||||
glyph_buffer_t dot;
|
||||
int dot_width;
|
||||
|
||||
glyph_buffer_t empty;
|
||||
int empty_width;
|
||||
|
||||
const char *derivation_separator = " ";
|
||||
int derivation_separator_width = 1;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
glyph_buffer_t *pbuf;
|
||||
const char *fallback;
|
||||
} callback_arg_t;
|
||||
|
||||
|
||||
static long
|
||||
on_success (const char *buf, size_t buflen, void *callback_arg)
|
||||
{
|
||||
callback_arg_t *arg = (callback_arg_t *) callback_arg;
|
||||
assert (buflen + 1 < sizeof *arg->pbuf);
|
||||
*stpncpy (*arg->pbuf, buf, buflen) = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
static long
|
||||
on_failure (unsigned code MAYBE_UNUSED, const char *msg MAYBE_UNUSED,
|
||||
void *callback_arg)
|
||||
{
|
||||
callback_arg_t *arg = (callback_arg_t *) callback_arg;
|
||||
assert (strlen (arg->fallback) + 1 < sizeof *arg->pbuf);
|
||||
strcpy (*arg->pbuf, arg->fallback);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
glyph_set (glyph_buffer_t *glyph, int *width,
|
||||
unsigned code, const char *fallback)
|
||||
{
|
||||
callback_arg_t arg = { glyph, fallback };
|
||||
int res = unicode_to_mb (code, on_success, on_failure, &arg);
|
||||
*width = mbswidth (*glyph, 0);
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
glyphs_init (void)
|
||||
{
|
||||
glyph_set (&arrow, &arrow_width, 0x2192, "->");
|
||||
glyph_set (&dot, &dot_width, 0x2022, ".");
|
||||
glyph_set (&down_arrow, &down_arrow_width, 0x21b3, "`->");
|
||||
glyph_set (&empty, &empty_width, 0x03b5, "%empty");
|
||||
|
||||
strncat (down_arrow, " ", sizeof down_arrow - strlen (down_arrow) - 1);
|
||||
down_arrow_width += 1;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/* Graphical symbols.
|
||||
|
||||
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Compiler Compiler.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef GLYPHS_H
|
||||
# define GLYPHS_H
|
||||
|
||||
/* Initialize the following variables. */
|
||||
void glyphs_init (void);
|
||||
|
||||
/* In gnulib/lib/unicodeio.h unicode_to_mb uses a buffer of 25 bytes.
|
||||
In down_arrow, we append one space. */
|
||||
typedef char glyph_buffer_t[26];
|
||||
|
||||
/* "→", separates the lhs of a rule from its rhs. */
|
||||
extern glyph_buffer_t arrow;
|
||||
extern int arrow_width;
|
||||
|
||||
/* "•", a point in an item (aka, a dotted rule). */
|
||||
extern glyph_buffer_t dot;
|
||||
extern int dot_width;
|
||||
|
||||
/* "↳ ", below an lhs to announce the rhs. */
|
||||
extern glyph_buffer_t down_arrow;
|
||||
extern int down_arrow_width;
|
||||
|
||||
/* "ε", an empty rhs. */
|
||||
extern glyph_buffer_t empty;
|
||||
extern int empty_width;
|
||||
|
||||
/* " ", separate symbols in the rhs of a derivation. */
|
||||
extern const char *derivation_separator;
|
||||
extern int derivation_separator_width;
|
||||
|
||||
#endif /* GLYPHS_H */
|
||||
+24
-24
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "complain.h"
|
||||
#include "getargs.h"
|
||||
#include "glyphs.h"
|
||||
#include "gram.h"
|
||||
#include "print-xml.h"
|
||||
#include "reader.h"
|
||||
@@ -40,25 +41,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 +57,7 @@ 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);
|
||||
fprintf (out, " %s", dot);
|
||||
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");
|
||||
}
|
||||
|
||||
+20
-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,8 @@
|
||||
|
||||
Associativities are recorded similarly in SYMBOLS[I]->assoc. */
|
||||
|
||||
# include "system.h"
|
||||
|
||||
# include "location.h"
|
||||
# include "symtab.h"
|
||||
|
||||
@@ -109,13 +111,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 +179,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. */
|
||||
@@ -210,7 +216,15 @@ extern rule *rules;
|
||||
extern rule_number nrules;
|
||||
|
||||
/* 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 +276,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;
|
||||
|
||||
|
||||
|
||||
|
||||
+14
-12
@@ -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;
|
||||
}
|
||||
|
||||
@@ -182,9 +184,9 @@ output_red (state const *s, reductions const *reds, FILE *fout)
|
||||
bool firste = true;
|
||||
rule_number ruleno = reds->rules[j]->number;
|
||||
|
||||
if (reds->lookahead_tokens)
|
||||
if (reds->lookaheads)
|
||||
for (int i = 0; i < ntokens; i++)
|
||||
if (bitset_test (reds->lookahead_tokens[j], i))
|
||||
if (bitset_test (reds->lookaheads[j], i))
|
||||
{
|
||||
if (bitset_test (no_reduce_set, i))
|
||||
firstd = print_token (&dout, firstd, symbols[i]->tag);
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
+24
-34
@@ -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,12 +1020,12 @@ 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];
|
||||
bitset lookahead_set =
|
||||
node->state->reductions->lookahead_tokens[r];
|
||||
node->state->reductions->lookaheads[r];
|
||||
if (item_number_is_rule_number (*this_rule->rhs))
|
||||
ielr_compute_goto_follow_set (follow_kernel_items,
|
||||
always_follows, node,
|
||||
|
||||
+28
-31
@@ -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)
|
||||
@@ -256,9 +256,9 @@ lookback_find_state (int lookback_index)
|
||||
state *res = NULL;
|
||||
for (int j = 0; j < nstates; ++j)
|
||||
if (states[j]->reductions
|
||||
&& states[j]->reductions->lookahead_tokens)
|
||||
&& states[j]->reductions->lookaheads)
|
||||
{
|
||||
if (states[j]->reductions->lookahead_tokens - LA > lookback_index)
|
||||
if (states[j]->reductions->lookaheads - LA > lookback_index)
|
||||
/* Went too far. */
|
||||
break;
|
||||
else
|
||||
@@ -280,7 +280,7 @@ lookback_print (FILE *out)
|
||||
{
|
||||
fprintf (out, " %3d = ", i);
|
||||
const state *s = lookback_find_state (i);
|
||||
int rnum = i - (s->reductions->lookahead_tokens - LA);
|
||||
int rnum = i - (s->reductions->lookaheads - LA);
|
||||
const rule *r = s->reductions->rules[rnum];
|
||||
fprintf (out, "(%3d, ", s->number);
|
||||
rule_print (r, NULL, out);
|
||||
@@ -305,7 +305,7 @@ static void
|
||||
add_lookback_edge (state *s, rule const *r, goto_number gotono)
|
||||
{
|
||||
int ri = state_reduction_find (s, r);
|
||||
int idx = (s->reductions->lookahead_tokens - LA) + ri;
|
||||
int idx = (s->reductions->lookaheads - LA) + ri;
|
||||
lookback[idx] = goto_list_new (gotono, lookback[idx]);
|
||||
}
|
||||
|
||||
@@ -421,7 +421,7 @@ compute_follows (void)
|
||||
|
||||
|
||||
static void
|
||||
compute_lookahead_tokens (void)
|
||||
compute_lookaheads (void)
|
||||
{
|
||||
if (trace_flag & trace_automaton)
|
||||
lookback_print (stderr);
|
||||
@@ -437,13 +437,12 @@ compute_lookahead_tokens (void)
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------.
|
||||
| Count the number of lookahead tokens required for S |
|
||||
| (N_LOOKAHEAD_TOKENS member). |
|
||||
`----------------------------------------------------*/
|
||||
/*------------------------------------------------------.
|
||||
| Count the number of lookahead tokens required for S. |
|
||||
`------------------------------------------------------*/
|
||||
|
||||
static int
|
||||
state_lookahead_tokens_count (state *s, bool default_reduction_only_for_accept)
|
||||
state_lookaheads_count (state *s, bool default_reduction_only_for_accept)
|
||||
{
|
||||
const reductions *reds = s->reductions;
|
||||
const transitions *trans = s->transitions;
|
||||
@@ -473,9 +472,9 @@ state_lookahead_tokens_count (state *s, bool default_reduction_only_for_accept)
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------.
|
||||
| Compute LA, NLA, and the lookahead_tokens members. |
|
||||
`----------------------------------------------------*/
|
||||
/*----------------------------------------------.
|
||||
| Compute LA, NLA, and the lookaheads members. |
|
||||
`----------------------------------------------*/
|
||||
|
||||
void
|
||||
initialize_LA (void)
|
||||
@@ -491,25 +490,23 @@ initialize_LA (void)
|
||||
/* Compute the total number of reductions requiring a lookahead. */
|
||||
nLA = 0;
|
||||
for (state_number i = 0; i < nstates; ++i)
|
||||
nLA +=
|
||||
state_lookahead_tokens_count (states[i],
|
||||
default_reduction_only_for_accept);
|
||||
nLA += state_lookaheads_count (states[i],
|
||||
default_reduction_only_for_accept);
|
||||
/* Avoid having to special case 0. */
|
||||
if (!nLA)
|
||||
nLA = 1;
|
||||
|
||||
bitsetv pLA = LA = bitsetv_create (nLA, ntokens, BITSET_FIXED);
|
||||
|
||||
/* Initialize the members LOOKAHEAD_TOKENS for each state whose reductions
|
||||
/* Initialize the members LOOKAHEADS for each state whose reductions
|
||||
require lookahead tokens. */
|
||||
for (state_number i = 0; i < nstates; ++i)
|
||||
{
|
||||
int count =
|
||||
state_lookahead_tokens_count (states[i],
|
||||
default_reduction_only_for_accept);
|
||||
int count = state_lookaheads_count (states[i],
|
||||
default_reduction_only_for_accept);
|
||||
if (count)
|
||||
{
|
||||
states[i]->reductions->lookahead_tokens = pLA;
|
||||
states[i]->reductions->lookaheads = pLA;
|
||||
pLA += count;
|
||||
}
|
||||
}
|
||||
@@ -521,7 +518,7 @@ initialize_LA (void)
|
||||
`---------------------------------------------*/
|
||||
|
||||
static void
|
||||
lookahead_tokens_print (FILE *out)
|
||||
lookaheads_print (FILE *out)
|
||||
{
|
||||
fputs ("Lookaheads:\n", out);
|
||||
for (state_number i = 0; i < nstates; ++i)
|
||||
@@ -533,11 +530,11 @@ lookahead_tokens_print (FILE *out)
|
||||
for (int j = 0; j < reds->num; ++j)
|
||||
{
|
||||
fprintf (out, " rule %d:", reds->rules[j]->number);
|
||||
if (reds->lookahead_tokens)
|
||||
if (reds->lookaheads)
|
||||
{
|
||||
bitset_iterator iter;
|
||||
int k;
|
||||
BITSET_FOR_EACH (iter, reds->lookahead_tokens[j], k, 0)
|
||||
BITSET_FOR_EACH (iter, reds->lookaheads[j], k, 0)
|
||||
fprintf (out, " %s", symbols[k]->tag);
|
||||
}
|
||||
fputc ('\n', out);
|
||||
@@ -564,10 +561,10 @@ lalr (void)
|
||||
lookback = xcalloc (nLA, sizeof *lookback);
|
||||
build_relations ();
|
||||
compute_follows ();
|
||||
compute_lookahead_tokens ();
|
||||
compute_lookaheads ();
|
||||
|
||||
if (trace_flag & trace_sets)
|
||||
lookahead_tokens_print (stderr);
|
||||
lookaheads_print (stderr);
|
||||
if (trace_flag & trace_automaton)
|
||||
{
|
||||
begin_use_class ("trace0", stderr);
|
||||
@@ -583,7 +580,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 +598,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;
|
||||
@@ -614,6 +611,6 @@ void
|
||||
lalr_free (void)
|
||||
{
|
||||
for (state_number s = 0; s < nstates; ++s)
|
||||
states[s]->reductions->lookahead_tokens = NULL;
|
||||
states[s]->reductions->lookaheads = NULL;
|
||||
bitsetv_free (LA);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user