mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-08-13 04:35:14 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a11a9308c | ||
|
|
d8cc6b073e | ||
|
|
0264b4bca0 | ||
|
|
8b424b865e | ||
|
|
f4431ea115 | ||
|
|
fe8c36ddca | ||
|
|
21c147b6e5 | ||
|
|
d3c575a6c6 | ||
|
|
d8b49e2b73 | ||
|
|
14c65a35f0 | ||
|
|
c47bb87f9f | ||
|
|
98c35e0025 | ||
|
|
bd6b046ce7 | ||
|
|
7c6e7bd300 | ||
|
|
3cba59dd7f | ||
|
|
a15879c623 | ||
|
|
5d501ee728 | ||
|
|
bc5e4541da | ||
|
|
567d1eaa19 | ||
|
|
c08e0863be | ||
|
|
541943ee04 | ||
|
|
dcdd119f69 | ||
|
|
a0bc06b703 | ||
|
|
5e33dfe59d | ||
|
|
2a4e9a358f | ||
|
|
f7b642cff7 | ||
|
|
3da17724ad | ||
|
|
68e3e442f9 | ||
|
|
e432619d11 | ||
|
|
a1b7fef045 | ||
|
|
067e35a8be | ||
|
|
0522047c96 | ||
|
|
3724b50ef9 | ||
|
|
b801b7b670 | ||
|
|
b7aab2dbad | ||
|
|
89e42ffb4b | ||
|
|
6aae4a7378 | ||
|
|
7d4a4300c2 | ||
|
|
31d4ec28bd | ||
|
|
0a5bfb4fda | ||
|
|
12d0b15679 | ||
|
|
cb7dcb011e | ||
|
|
71579c7219 | ||
|
|
2f8a874215 | ||
|
|
ad6f600bb1 | ||
|
|
de4f41eab7 | ||
|
|
e73f086b0d | ||
|
|
8cf098415e | ||
|
|
977e19840d | ||
|
|
d975c2f76e | ||
|
|
0676801b8c | ||
|
|
82aa96e9b1 | ||
|
|
cb65553449 | ||
|
|
f47a1bd622 | ||
|
|
205d372c68 | ||
|
|
07a1243b40 | ||
|
|
ece343d2c2 | ||
|
|
be95a4fe29 | ||
|
|
6accee7716 | ||
|
|
e63f22703e | ||
|
|
fa390dc311 | ||
|
|
17fdf5eca2 | ||
|
|
72b3c1a673 | ||
|
|
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 |
+1
-1
@@ -1 +1 @@
|
|||||||
3.6.4
|
3.7.3
|
||||||
|
|||||||
+4
-1
@@ -50,6 +50,7 @@ jobs:
|
|||||||
- make -j2 dist-xz
|
- make -j2 dist-xz
|
||||||
# Can help understanding why we get "dirty" tarballs.
|
# Can help understanding why we get "dirty" tarballs.
|
||||||
- git status
|
- git status
|
||||||
|
- git diff
|
||||||
- dist=$(echo bison*.xz)
|
- dist=$(echo bison*.xz)
|
||||||
|
|
||||||
# Unfortunately we cannot deterministically know the name of the tarball without the full
|
# Unfortunately we cannot deterministically know the name of the tarball without the full
|
||||||
@@ -119,6 +120,8 @@ jobs:
|
|||||||
- CXX='clang++-10 -fsanitize=address -stdlib=libc++'
|
- CXX='clang++-10 -fsanitize=address -stdlib=libc++'
|
||||||
- PART=2
|
- PART=2
|
||||||
|
|
||||||
|
# See https://github.com/simd-everywhere/simde/blob/master/.travis.yml
|
||||||
|
# and https://software.intel.com/content/www/us/en/develop/documentation/get-started-with-intel-oneapi-render-linux/top/configure-your-system.html.
|
||||||
- name: "ICC"
|
- name: "ICC"
|
||||||
stage: check
|
stage: check
|
||||||
os: linux
|
os: linux
|
||||||
@@ -127,7 +130,7 @@ jobs:
|
|||||||
- CC=icc
|
- CC=icc
|
||||||
- CXX=icpc
|
- CXX=icpc
|
||||||
install:
|
install:
|
||||||
- source /opt/intel/inteloneapi/compiler/latest/env/vars.sh
|
- source /opt/intel/oneapi/compiler/latest/env/vars.sh
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
|
|||||||
@@ -1,6 +1,84 @@
|
|||||||
GNU Bison NEWS
|
GNU Bison NEWS
|
||||||
|
|
||||||
* Noteworthy changes in release 3.6.90 (2020-07-04) [beta]
|
* Noteworthy changes in release 3.7.4 (2020-11-14) [stable]
|
||||||
|
|
||||||
|
** Bug fixes
|
||||||
|
|
||||||
|
*** Bug fixes in yacc.c
|
||||||
|
|
||||||
|
In Yacc mode, all the tokens are defined twice: once as an enum, and then
|
||||||
|
as a macro. YYEMPTY was missing its macro.
|
||||||
|
|
||||||
|
*** Bug fixes in lalr1.cc
|
||||||
|
|
||||||
|
The lalr1.cc skeleton used to emit internal assertions (using YY_ASSERT)
|
||||||
|
even when the `parse.assert` %define variable is not enabled. It no
|
||||||
|
longer does.
|
||||||
|
|
||||||
|
The private internal macro YY_ASSERT now obeys the `api.prefix` %define
|
||||||
|
variable.
|
||||||
|
|
||||||
|
When there is a very large number of tokens, some assertions could be long
|
||||||
|
enough to hit arbitrary limits in Visual C++. They have been rewritten to
|
||||||
|
work around this limitation.
|
||||||
|
|
||||||
|
** Changes
|
||||||
|
|
||||||
|
The YYBISON macro in generated "regular C parsers" (from the "yacc.c"
|
||||||
|
skeleton) used to be defined to 1. It is now defined to the version of
|
||||||
|
Bison as an integer (e.g., 30704 for version 3.7.4).
|
||||||
|
|
||||||
|
* Noteworthy changes in release 3.7.3 (2020-10-13) [stable]
|
||||||
|
|
||||||
|
** Bug fixes
|
||||||
|
|
||||||
|
Fix concurrent build issues.
|
||||||
|
|
||||||
|
The bison executable is no longer linked uselessly against libreadline.
|
||||||
|
|
||||||
|
Fix incorrect use of yytname in glr.cc.
|
||||||
|
|
||||||
|
* Noteworthy changes in release 3.7.2 (2020-09-05) [stable]
|
||||||
|
|
||||||
|
This release of Bison fixes all known bugs reported for Bison in MITRE's
|
||||||
|
Common Vulnerabilities and Exposures (CVE) system. These vulnerabilities
|
||||||
|
are only about bison-the-program itself, not the generated code.
|
||||||
|
|
||||||
|
Although these bugs are typically irrelevant to how Bison is used, they
|
||||||
|
are worth fixing if only to give users peace of mind.
|
||||||
|
|
||||||
|
There is no known vulnerability in the generated parsers.
|
||||||
|
|
||||||
|
** Bug fixes
|
||||||
|
|
||||||
|
Fix concurrent build issues (introduced in Bison 3.5).
|
||||||
|
|
||||||
|
Push parsers always use YYMALLOC/YYFREE (no direct calls to malloc/free).
|
||||||
|
|
||||||
|
Fix portability issues of the test suite, and of bison itself.
|
||||||
|
|
||||||
|
Some unlikely crashes found by fuzzing have been fixed. This is only
|
||||||
|
about bison itself, not the generated parsers.
|
||||||
|
|
||||||
|
|
||||||
|
* Noteworthy changes in release 3.7.1 (2020-08-02) [stable]
|
||||||
|
|
||||||
|
** Bug fixes
|
||||||
|
|
||||||
|
Crash when a token alias contains a NUL byte.
|
||||||
|
|
||||||
|
Portability issues with libtextstyle.
|
||||||
|
|
||||||
|
Portability issues of Bison itself with MSVC.
|
||||||
|
|
||||||
|
** Changes
|
||||||
|
|
||||||
|
Improvements and fixes in the documentation.
|
||||||
|
|
||||||
|
More precise location about symbol type redefinitions.
|
||||||
|
|
||||||
|
|
||||||
|
* Noteworthy changes in release 3.7 (2020-07-23) [stable]
|
||||||
|
|
||||||
** Deprecated features
|
** Deprecated features
|
||||||
|
|
||||||
@@ -18,28 +96,115 @@ GNU Bison NEWS
|
|||||||
|
|
||||||
Contributed by Vincent Imbimbo.
|
Contributed by Vincent Imbimbo.
|
||||||
|
|
||||||
When given `--report=counterexamples` or `-Wcounterexamples`, bison will
|
When given `-Wcounterexamples`/`-Wcex`, bison will now output
|
||||||
now output counterexamples for conflicts in the grammar. These are
|
counterexamples for conflicts.
|
||||||
strings in the grammar which can be parsed in two ways due to the
|
|
||||||
conflict. For example:
|
|
||||||
|
|
||||||
Example exp '+' exp • '/' exp
|
**** Unifying Counterexamples
|
||||||
First derivation exp ::=[ exp ::=[ exp '+' exp • ] '/' exp ]
|
|
||||||
Second derivation exp ::=[ exp '+' exp ::=[ exp • '/' exp ] ]
|
|
||||||
|
|
||||||
This is a shift/reduce conflict caused by none of the operators having
|
Unifying counterexamples are strings which can be parsed in two ways due
|
||||||
precedence, so the example can be parsed in the two ways shown. When
|
to the conflict. For example on a grammar that contains the usual
|
||||||
bison cannot find an example that can be derived in two ways, it instead
|
"dangling else" ambiguity:
|
||||||
generates two examples that are the same up until the dot:
|
|
||||||
|
|
||||||
First example expr • ID $end
|
$ bison else.y
|
||||||
First derivation $accept ::=[ s ::=[ a ::=[ expr • ] ID ] $end ]
|
else.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
|
||||||
Second example expr • ID ',' ID $end
|
else.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
|
||||||
Second derivation $accept ::=[ s ::=[ a ::=[ expr ::=[ expr • ID ',' ] ] ID ] $end ]
|
|
||||||
|
$ bison else.y -Wcex
|
||||||
|
else.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
|
||||||
|
else.y: warning: shift/reduce conflict on token "else" [-Wcounterexamples]
|
||||||
|
Example: "if" exp "then" "if" exp "then" exp • "else" exp
|
||||||
|
Shift derivation
|
||||||
|
exp
|
||||||
|
↳ "if" exp "then" exp
|
||||||
|
↳ "if" exp "then" exp • "else" exp
|
||||||
|
Example: "if" exp "then" "if" exp "then" exp • "else" exp
|
||||||
|
Reduce derivation
|
||||||
|
exp
|
||||||
|
↳ "if" exp "then" exp "else" exp
|
||||||
|
↳ "if" exp "then" exp •
|
||||||
|
|
||||||
|
When text styling is enabled, colors are used in the examples and the
|
||||||
|
derivations to highlight the structure of both analyses. In this case,
|
||||||
|
|
||||||
|
"if" exp "then" [ "if" exp "then" exp • ] "else" exp
|
||||||
|
|
||||||
|
vs.
|
||||||
|
|
||||||
|
"if" exp "then" [ "if" exp "then" exp • "else" exp ]
|
||||||
|
|
||||||
|
|
||||||
|
The counterexamples are "focused", in two different ways. First, they do
|
||||||
|
not clutter the output with all the derivations from the start symbol,
|
||||||
|
rather they start on the "conflicted nonterminal". They go straight to the
|
||||||
|
point. Second, they don't "expand" nonterminal symbols uselessly.
|
||||||
|
|
||||||
|
**** Nonunifying Counterexamples
|
||||||
|
|
||||||
|
In the case of the dangling else, Bison found an example that can be
|
||||||
|
parsed in two ways (therefore proving that the grammar is ambiguous).
|
||||||
|
When it cannot find such an example, it instead generates two examples
|
||||||
|
that are the same up until the dot:
|
||||||
|
|
||||||
|
$ bison foo.y
|
||||||
|
foo.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
|
||||||
|
foo.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
|
||||||
|
foo.y:4.4-7: warning: rule useless in parser due to conflicts [-Wother]
|
||||||
|
4 | a: expr
|
||||||
|
| ^~~~
|
||||||
|
|
||||||
|
$ bison -Wcex foo.y
|
||||||
|
foo.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
|
||||||
|
foo.y: warning: shift/reduce conflict on token ID [-Wcounterexamples]
|
||||||
|
First example: expr • ID ',' ID $end
|
||||||
|
Shift derivation
|
||||||
|
$accept
|
||||||
|
↳ s $end
|
||||||
|
↳ a ID
|
||||||
|
↳ expr
|
||||||
|
↳ expr • ID ','
|
||||||
|
Second example: expr • ID $end
|
||||||
|
Reduce derivation
|
||||||
|
$accept
|
||||||
|
↳ s $end
|
||||||
|
↳ a ID
|
||||||
|
↳ expr •
|
||||||
|
foo.y:4.4-7: warning: rule useless in parser due to conflicts [-Wother]
|
||||||
|
4 | a: expr
|
||||||
|
| ^~~~
|
||||||
|
|
||||||
In these cases, the parser usually doesn't have enough lookahead to
|
In these cases, the parser usually doesn't have enough lookahead to
|
||||||
differentiate the two given examples.
|
differentiate the two given examples.
|
||||||
|
|
||||||
|
**** Reports
|
||||||
|
|
||||||
|
Counterexamples are also included in the report when given
|
||||||
|
`--report=counterexamples`/`-rcex` (or `--report=all`), with more
|
||||||
|
technical details:
|
||||||
|
|
||||||
|
State 7
|
||||||
|
|
||||||
|
1 exp: "if" exp "then" exp • [$end, "then", "else"]
|
||||||
|
2 | "if" exp "then" exp • "else" exp
|
||||||
|
|
||||||
|
"else" shift, and go to state 8
|
||||||
|
|
||||||
|
"else" [reduce using rule 1 (exp)]
|
||||||
|
$default reduce using rule 1 (exp)
|
||||||
|
|
||||||
|
shift/reduce conflict on token "else":
|
||||||
|
1 exp: "if" exp "then" exp •
|
||||||
|
2 exp: "if" exp "then" exp • "else" exp
|
||||||
|
Example: "if" exp "then" "if" exp "then" exp • "else" exp
|
||||||
|
Shift derivation
|
||||||
|
exp
|
||||||
|
↳ "if" exp "then" exp
|
||||||
|
↳ "if" exp "then" exp • "else" exp
|
||||||
|
Example: "if" exp "then" "if" exp "then" exp • "else" exp
|
||||||
|
Reduce derivation
|
||||||
|
exp
|
||||||
|
↳ "if" exp "then" exp "else" exp
|
||||||
|
↳ "if" exp "then" exp •
|
||||||
|
|
||||||
*** File prefix mapping
|
*** File prefix mapping
|
||||||
|
|
||||||
Contributed by Joshua Watt.
|
Contributed by Joshua Watt.
|
||||||
@@ -52,6 +217,11 @@ GNU Bison NEWS
|
|||||||
|
|
||||||
** Changes
|
** Changes
|
||||||
|
|
||||||
|
*** Diagnostics
|
||||||
|
|
||||||
|
When text styling is enabled and the terminal supports it, the warnings
|
||||||
|
now include hyperlinks to the documentation.
|
||||||
|
|
||||||
*** Relocatable installation
|
*** Relocatable installation
|
||||||
|
|
||||||
When installed to be relocatable (via `configure --enable-relocatable`),
|
When installed to be relocatable (via `configure --enable-relocatable`),
|
||||||
@@ -92,6 +262,18 @@ GNU Bison NEWS
|
|||||||
Now the parser state can be examined when parsing is finished. The parser
|
Now the parser state can be examined when parsing is finished. The parser
|
||||||
state is reset when starting a new parse.
|
state is reset when starting a new parse.
|
||||||
|
|
||||||
|
** Documentation
|
||||||
|
|
||||||
|
*** Examples
|
||||||
|
|
||||||
|
The bistromathic demonstrates %param and how to quote sources in the error
|
||||||
|
messages:
|
||||||
|
|
||||||
|
> 123 456
|
||||||
|
1.5-7: syntax error: expected end of file or + or - or * or / or ^ before number
|
||||||
|
1 | 123 456
|
||||||
|
| ^~~
|
||||||
|
|
||||||
** Bug fixes
|
** Bug fixes
|
||||||
|
|
||||||
*** Include the generated header (yacc.c)
|
*** Include the generated header (yacc.c)
|
||||||
@@ -433,7 +615,8 @@ GNU Bison NEWS
|
|||||||
\005) with incorrect styling. Fixes for similar issues with unexpectedly
|
\005) with incorrect styling. Fixes for similar issues with unexpectedly
|
||||||
short lines (e.g., the file was changed between parsing and diagnosing).
|
short lines (e.g., the file was changed between parsing and diagnosing).
|
||||||
|
|
||||||
Several unlikely crashes found by fuzzing have been fixed.
|
Some unlikely crashes found by fuzzing have been fixed. This is only
|
||||||
|
about bison itself, not the generated parsers.
|
||||||
|
|
||||||
|
|
||||||
* Noteworthy changes in release 3.5.2 (2020-02-13) [stable]
|
* Noteworthy changes in release 3.5.2 (2020-02-13) [stable]
|
||||||
@@ -4357,7 +4540,7 @@ LocalWords: yysymbol yytnamerr yyreport ctx ARGMAX yysyntax stderr LPAREN
|
|||||||
LocalWords: symrec yypcontext TOKENMAX yyexpected YYEMPTY yypstate YYEOF
|
LocalWords: symrec yypcontext TOKENMAX yyexpected YYEMPTY yypstate YYEOF
|
||||||
LocalWords: autocompletion bistromathic submessages Cayuela lexcalc hoc
|
LocalWords: autocompletion bistromathic submessages Cayuela lexcalc hoc
|
||||||
LocalWords: yytoken YYUNDEF YYerror basename Automake's UTF ifdef ffile
|
LocalWords: yytoken YYUNDEF YYerror basename Automake's UTF ifdef ffile
|
||||||
LocalWords: gotos readline Imbimbo Wcounterexamples
|
LocalWords: gotos readline Imbimbo Wcounterexamples Wcex Nonunifying rcex
|
||||||
|
|
||||||
Local Variables:
|
Local Variables:
|
||||||
ispell-dictionary: "american"
|
ispell-dictionary: "american"
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ Bison from the git repo. Roughly, run:
|
|||||||
then proceed with the usual `configure && make` steps.
|
then proceed with the usual `configure && make` steps.
|
||||||
|
|
||||||
## Build from tarball
|
## Build from tarball
|
||||||
See the [INSTALL file](INSTALL] for generic compilation and installation
|
See the [INSTALL file](INSTALL) for generic compilation and installation
|
||||||
instructions.
|
instructions.
|
||||||
|
|
||||||
Bison requires GNU m4 1.4.6 or later. See
|
Bison requires GNU m4 1.4.6 or later. See
|
||||||
@@ -42,9 +42,11 @@ installing it. In that case, do not use `src/bison`: it would use the
|
|||||||
As an experimental feature, diagnostics are now colored, controlled by the
|
As an experimental feature, diagnostics are now colored, controlled by the
|
||||||
`--color` and `--style` options.
|
`--color` and `--style` options.
|
||||||
|
|
||||||
To use them, install the libtextstyle library before configuring Bison. It
|
To use them, install the libtextstyle library, 0.20.5 or newer, before
|
||||||
is available from https://alpha.gnu.org/gnu/gettext/, for instance
|
configuring Bison. It is available from https://alpha.gnu.org/gnu/gettext/,
|
||||||
https://alpha.gnu.org/pub/gnu/gettext/libtextstyle-0.20.5.tar.gz.
|
for instance https://alpha.gnu.org/gnu/gettext/libtextstyle-0.20.5.tar.gz,
|
||||||
|
or as part of Gettext 0.21 or newer, for instance
|
||||||
|
https://ftp.gnu.org/gnu/gettext/gettext-0.21.tar.gz.
|
||||||
|
|
||||||
The option --color supports the following arguments:
|
The option --color supports the following arguments:
|
||||||
- always, yes: Enable colors.
|
- always, yes: Enable colors.
|
||||||
@@ -61,6 +63,13 @@ To customize the styles, create a CSS file, say `bison-bw.css`, similar to
|
|||||||
then invoke bison with `--style=bison-bw.css`, or set the `BISON_STYLE`
|
then invoke bison with `--style=bison-bw.css`, or set the `BISON_STYLE`
|
||||||
environment variable to `bison-bw.css`.
|
environment variable to `bison-bw.css`.
|
||||||
|
|
||||||
|
In some diagnostics, bison uses libtextstyle to emit special escapes to
|
||||||
|
generate clickable hyperlinks. The environment variable
|
||||||
|
`NO_TERM_HYPERLINKS` can be used to suppress them. This may be useful for
|
||||||
|
terminal emulators which produce garbage output when they receive the escape
|
||||||
|
sequence for a hyperlink. Currently (as of 2020), this affects some versions
|
||||||
|
of emacs, guake, konsole, lxterminal, rxvt, yakuake.
|
||||||
|
|
||||||
## Relocatability
|
## Relocatability
|
||||||
If you pass `--enable-relocatable` to `configure`, Bison is relocatable.
|
If you pass `--enable-relocatable` to `configure`, Bison is relocatable.
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -211,6 +211,8 @@ assert/abort), and all the --trace output which is meant for the maintainers
|
|||||||
only.
|
only.
|
||||||
|
|
||||||
## Vocabulary
|
## Vocabulary
|
||||||
|
- "lookahead", not "look-ahead".
|
||||||
|
- "midrule", not "mid-rule".
|
||||||
- "nonterminal", not "variable" or "non-terminal" or "non terminal".
|
- "nonterminal", not "variable" or "non-terminal" or "non terminal".
|
||||||
Abbreviated as "nterm".
|
Abbreviated as "nterm".
|
||||||
- "shift/reduce" and "reduce/reduce", not "shift-reduce" or "shift reduce",
|
- "shift/reduce" and "reduce/reduce", not "shift-reduce" or "shift reduce",
|
||||||
@@ -442,7 +444,7 @@ added the `[-Wother]` part to all the warnings). Part of the update can be
|
|||||||
done with a crude tool: `build-aux/update-test`.
|
done with a crude tool: `build-aux/update-test`.
|
||||||
|
|
||||||
Once you ran the test suite, and therefore have many `testsuite.log` files,
|
Once you ran the test suite, and therefore have many `testsuite.log` files,
|
||||||
run, from the source tree:
|
run `make update-tests`. Or, by hand, from the *source* tree:
|
||||||
|
|
||||||
$ ./build-aux/update-test $build/tests/testsuite.dir/*/testsuite.log
|
$ ./build-aux/update-test $build/tests/testsuite.dir/*/testsuite.log
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,12 @@
|
|||||||
* Bison 3.7
|
* Soon
|
||||||
|
** gnulib
|
||||||
|
Bruno notes:
|
||||||
|
|
||||||
|
> I haven't looked deeply, but it strikes me that gnulib/lib/bitset/array.c
|
||||||
|
> does not make use of the 'ffsl' function, nor or the 'integer_length_l'
|
||||||
|
> function. Maybe because in Bison, all bitsets are so dense that it does
|
||||||
|
> not give a performance advantage?
|
||||||
|
|
||||||
** Cex
|
** Cex
|
||||||
*** Improve gnulib
|
*** Improve gnulib
|
||||||
Don't do this (counterexample.c):
|
Don't do this (counterexample.c):
|
||||||
@@ -36,8 +44,6 @@ Unless we play it dumb (little structure).
|
|||||||
- How about not evaluating incomplete lines when the text is not finished
|
- How about not evaluating incomplete lines when the text is not finished
|
||||||
(as shells do).
|
(as shells do).
|
||||||
|
|
||||||
- Caret diagnostics
|
|
||||||
|
|
||||||
** Questions
|
** Questions
|
||||||
*** Java
|
*** Java
|
||||||
- Should i18n be part of the Lexer? Currently it's a static method of
|
- Should i18n be part of the Lexer? Currently it's a static method of
|
||||||
@@ -50,13 +56,6 @@ Unless we play it dumb (little structure).
|
|||||||
|
|
||||||
- promote YYEOF rather than EOF.
|
- promote YYEOF rather than EOF.
|
||||||
|
|
||||||
*** D
|
|
||||||
- is there a way to attach yysymbol_name to the enum itself? As we did
|
|
||||||
in Java.
|
|
||||||
|
|
||||||
- It would be better to have TokenKind as return value. Can we use
|
|
||||||
reflection to support both output types?
|
|
||||||
|
|
||||||
** YYerror
|
** YYerror
|
||||||
https://git.savannah.gnu.org/gitweb/?p=gettext.git;a=blob;f=gettext-runtime/intl/plural.y;h=a712255af4f2f739c93336d4ff6556d932a426a5;hb=HEAD
|
https://git.savannah.gnu.org/gitweb/?p=gettext.git;a=blob;f=gettext-runtime/intl/plural.y;h=a712255af4f2f739c93336d4ff6556d932a426a5;hb=HEAD
|
||||||
|
|
||||||
@@ -69,7 +68,7 @@ Stop hard-coding "Calc". Adjust local.at (look for FIXME).
|
|||||||
|
|
||||||
** A dev warning for b4_
|
** A dev warning for b4_
|
||||||
Maybe we should check for m4_ and b4_ leaking out of the m4 processing, as
|
Maybe we should check for m4_ and b4_ leaking out of the m4 processing, as
|
||||||
Autoconf does. It would have caught overquotation issues.
|
Autoconf does. It would have caught over-quotation issues.
|
||||||
|
|
||||||
** doc
|
** doc
|
||||||
I feel it's ugly to use the GNU style to declare functions in the doc. It
|
I feel it's ugly to use the GNU style to declare functions in the doc. It
|
||||||
@@ -90,7 +89,7 @@ push parsers on top of pull parser. Which is currently not relevant, since
|
|||||||
push parsers are measurably slower.
|
push parsers are measurably slower.
|
||||||
|
|
||||||
** %define parse.error formatted
|
** %define parse.error formatted
|
||||||
How about pushing bistromathics' yyreport_syntax_error as another standard
|
How about pushing Bistromathic's yyreport_syntax_error as another standard
|
||||||
way to generate the error message, and leave to the user the task of
|
way to generate the error message, and leave to the user the task of
|
||||||
providing the message formats? Currently in bistro, it reads:
|
providing the message formats? Currently in bistro, it reads:
|
||||||
|
|
||||||
@@ -204,18 +203,282 @@ The "automaton" and "set" categories are not so useful. We should probably
|
|||||||
introduce lr(0) and lalr, just the way we have ielr categories. The
|
introduce lr(0) and lalr, just the way we have ielr categories. The
|
||||||
"closure" function is too verbose, it should probably have its own category.
|
"closure" function is too verbose, it should probably have its own category.
|
||||||
|
|
||||||
"set" can still be used for summariring the important sets. That would make
|
"set" can still be used for summarizing the important sets. That would make
|
||||||
tests easy to maintain.
|
tests easy to maintain.
|
||||||
|
|
||||||
*** complain.*
|
*** complain.*
|
||||||
Rename these guys as "diagnostics.*" (or "diagnose.*"), since that's the
|
Rename these guys as "diagnostics.*" (or "diagnose.*"), since that's the
|
||||||
name they have in gcc, clang, etc. Likewise for the complain_* series of
|
name they have in GCC, clang, etc. Likewise for the complain_* series of
|
||||||
functions.
|
functions.
|
||||||
|
|
||||||
*** ritem
|
*** ritem
|
||||||
states/nstates, rules/nrules, ..., ritem/nritems
|
states/nstates, rules/nrules, ..., ritem/nritems
|
||||||
Fix the latter.
|
Fix the latter.
|
||||||
|
|
||||||
|
* D programming language
|
||||||
|
There's a number of features that are missing, here sorted in _suggested_
|
||||||
|
order of implementation.
|
||||||
|
|
||||||
|
When copying code from other skeletons, keep the comments exactly as they
|
||||||
|
are. Keep the same variable names. If you change the wording in one place,
|
||||||
|
do it in the others too. In other words: make sure to keep the
|
||||||
|
maintenance *simple* by avoiding any gratuitous difference.
|
||||||
|
|
||||||
|
** Rename the D example
|
||||||
|
Move the current content of examples/d into examples/d/simple.
|
||||||
|
|
||||||
|
** Create a second example
|
||||||
|
Duplicate examples/d/simple into examples/d/calc.
|
||||||
|
|
||||||
|
** Add location tracking to d/calc
|
||||||
|
Look at the examples in the other languages to see how to do that.
|
||||||
|
|
||||||
|
** yysymbol_name
|
||||||
|
The SymbolKind is an enum. For a given SymbolKind we want to get its string
|
||||||
|
representation. Currently it's a separate table in the parser that does
|
||||||
|
that:
|
||||||
|
|
||||||
|
/* Symbol kinds. */
|
||||||
|
public enum SymbolKind
|
||||||
|
{
|
||||||
|
S_YYEMPTY = -2, /* No symbol. */
|
||||||
|
S_YYEOF = 0, /* "end of file" */
|
||||||
|
S_YYerror = 1, /* error */
|
||||||
|
S_YYUNDEF = 2, /* "invalid token" */
|
||||||
|
S_EQ = 3, /* "=" */
|
||||||
|
...
|
||||||
|
S_input = 14, /* input */
|
||||||
|
S_line = 15, /* line */
|
||||||
|
S_exp = 16, /* exp */
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
|
||||||
|
First, the terminals, then, starting at \a yyntokens_, nonterminals. */
|
||||||
|
private static immutable string[] yytname_ =
|
||||||
|
[
|
||||||
|
"\"end of file\"", "error", "\"invalid token\"", "\"=\"", "\"+\"",
|
||||||
|
"\"-\"", "\"*\"", "\"/\"", "\"(\"", "\")\"", "\"end of line\"",
|
||||||
|
"\"number\"", "UNARY", "$accept", "input", "line", "exp", null
|
||||||
|
];
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
So to get a symbol kind, one runs `yytname_[yykind]`.
|
||||||
|
|
||||||
|
Is there a way to attach this conversion to string to SymbolKind? In Java
|
||||||
|
for instance, we have:
|
||||||
|
|
||||||
|
public enum SymbolKind
|
||||||
|
{
|
||||||
|
S_YYEOF(0), /* "end of file" */
|
||||||
|
S_YYerror(1), /* error */
|
||||||
|
S_YYUNDEF(2), /* "invalid token" */
|
||||||
|
...
|
||||||
|
S_input(16), /* input */
|
||||||
|
S_line(17), /* line */
|
||||||
|
S_exp(18); /* exp */
|
||||||
|
|
||||||
|
private final int yycode_;
|
||||||
|
|
||||||
|
SymbolKind (int n) {
|
||||||
|
this.yycode_ = n;
|
||||||
|
}
|
||||||
|
...
|
||||||
|
/* YYNAMES_[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
|
||||||
|
First, the terminals, then, starting at \a YYNTOKENS_, nonterminals. */
|
||||||
|
private static final String[] yynames_ = yynames_init();
|
||||||
|
private static final String[] yynames_init()
|
||||||
|
{
|
||||||
|
return new String[]
|
||||||
|
{
|
||||||
|
i18n("end of file"), i18n("error"), i18n("invalid token"), "!", "+", "-", "*",
|
||||||
|
"/", "^", "(", ")", "=", i18n("end of line"), i18n("number"), "NEG",
|
||||||
|
"$accept", "input", "line", "exp", null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The user-facing name of this symbol. */
|
||||||
|
public final String getName() {
|
||||||
|
return yynames_[yycode_];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
which allows to write more naturally `yykind.getName()` rather than
|
||||||
|
`yytname_[yykind]`. Is there something comparable in (idiomatic) D?
|
||||||
|
|
||||||
|
** Change the return value of yylex
|
||||||
|
Historically people were allowed to return any int from the scanner (which
|
||||||
|
is convenient and allows `return '+'` from the scanner). Akim tends to see
|
||||||
|
this as an error, we should restrict the return values to TokenKind (not to
|
||||||
|
be confused with SymbolKind).
|
||||||
|
|
||||||
|
In the case of D, without the history, we have the choice to support or not
|
||||||
|
`int`. If we want to _keep_ `int`, is there a way, say via introspection,
|
||||||
|
to support both signatures of yylex? If we don't keep `int`, just move to
|
||||||
|
TokenKind.
|
||||||
|
|
||||||
|
** Documentation
|
||||||
|
Write documentation about D support in doc/bison.texi. Imitate the Java
|
||||||
|
documentation. You should be more succinct IMHO.
|
||||||
|
|
||||||
|
** Complete Symbols
|
||||||
|
The current interface from the scanner to the parser is somewhat clumsy: the
|
||||||
|
token kind is returned by yylex, but the value and location are stored in
|
||||||
|
the scanner. This reflects the fact that the implementation of the parser
|
||||||
|
uses three variables to deal with each parsed symbol: its kind, its value,
|
||||||
|
its location.
|
||||||
|
|
||||||
|
So today the scanner of examples/d/calc.d (no locations) looks like:
|
||||||
|
|
||||||
|
if (input.front.isNumber)
|
||||||
|
{
|
||||||
|
import std.conv : parse;
|
||||||
|
semanticVal_.ival = input.parse!int;
|
||||||
|
return TokenKind.NUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
and the generated parser:
|
||||||
|
|
||||||
|
/* Read a lookahead token. */
|
||||||
|
if (yychar == TokenKind.YYEMPTY)
|
||||||
|
{
|
||||||
|
yychar = yylex ();
|
||||||
|
yylval = yylexer.semanticVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
The parser class should feature a `Symbol` type which binds together kind,
|
||||||
|
value and location, and the scanner should be able to return an instance of
|
||||||
|
that type. Something like
|
||||||
|
|
||||||
|
if (input.front.isNumber)
|
||||||
|
{
|
||||||
|
import std.conv : parse;
|
||||||
|
return parser.Symbol (TokenKind.NUM, input.parse!int);
|
||||||
|
}
|
||||||
|
|
||||||
|
** Token Constructors
|
||||||
|
In the previous example it is possible to mix incorrectly kinds and values,
|
||||||
|
and for instance:
|
||||||
|
|
||||||
|
return parser.Symbol (TokenKind.NUM, "Hello, World!\n");
|
||||||
|
|
||||||
|
attaches a string value to NUM kind (wrong, of course). When
|
||||||
|
api.token.constructor is set, in C++, Bison generated "token constructors":
|
||||||
|
parser.make_NUM. parser.make_PLUS, parser.make_STRING, etc. The previous
|
||||||
|
example becomes
|
||||||
|
|
||||||
|
return parser.make_NUM ("Hello, World!\n");
|
||||||
|
|
||||||
|
which would easily be caught by the type checker.
|
||||||
|
|
||||||
|
** Lookahead Correction
|
||||||
|
Add support for LAC to the D skeleton. It should not be too hard: look how
|
||||||
|
this is done in lalr1.cc, and mock it.
|
||||||
|
|
||||||
|
** Push Parser
|
||||||
|
Add support for push parser. Do not start a nice skeleton, just enhance the
|
||||||
|
current one to support push parsers. This is going to be a tougher nut to
|
||||||
|
crack.
|
||||||
|
|
||||||
|
First, you need to understand well how the push parser is expected to work.
|
||||||
|
To this end:
|
||||||
|
- read the doc
|
||||||
|
- look at examples/c/pushcalc
|
||||||
|
- create an example of a Java push parser.
|
||||||
|
- have a look at the generated parser in Java, which has the advantage of
|
||||||
|
being already based on a parser object, instead of just a function.
|
||||||
|
|
||||||
|
The C case is harder to read, but it may help too. Keep in mind that
|
||||||
|
because there's no object to maintain state, the C push parser uses some
|
||||||
|
struct (yypstate) to preserve this state. We don't need this in D, the
|
||||||
|
parser object will suffice.
|
||||||
|
|
||||||
|
I think working directly on the skeleton to add push-parser support is not
|
||||||
|
the simplest path. I suggest that you (1) transform a generated parser into
|
||||||
|
a push parser by hand, and then (2) transform lalr1.d to generate such a
|
||||||
|
parser.
|
||||||
|
|
||||||
|
Use `git commit` frequently to make sure you keep track of your progress.
|
||||||
|
|
||||||
|
*** (1.a) Prepare pull parser by hand
|
||||||
|
Copy again one of the D examples into say examples/d/pushcalc. Also
|
||||||
|
check-in the generated parser to facilitate experimentation.
|
||||||
|
|
||||||
|
- find local variables of yyparse should become members of the parser object
|
||||||
|
(so that we preserve state from one call to the next).
|
||||||
|
|
||||||
|
- do it in your generated D parser. We don't need an equivalent for
|
||||||
|
yypstate, because we already have it: that the parser object itself.
|
||||||
|
|
||||||
|
- have your *pull*-parser (i.e., the good old yy::parser::parse()) work
|
||||||
|
properly this way. Write and run tests. That's one of the reasons I
|
||||||
|
suggest using examples/d/calc as a starting point: it already has tests,
|
||||||
|
you can/should add more.
|
||||||
|
|
||||||
|
At this point you have a pull-parser which you prepared to turn into a
|
||||||
|
push-parser.
|
||||||
|
|
||||||
|
*** (1.b) Turn pull parser into push parser by hand
|
||||||
|
|
||||||
|
- look again at how push parsers are implemented in Java/C to see what needs
|
||||||
|
to change in yyparse so that the control is inverted: parse() will
|
||||||
|
be *given* the tokens, instead of having to call yylex itself. When I say
|
||||||
|
"look at C", I think your best option are (i) yacc.c (look for b4_push_if)
|
||||||
|
and (ii) examples/c/pushcalc.
|
||||||
|
|
||||||
|
- rename parse() as push_parse(Symbol yyla) (or push_parse(TokenKind, Value,
|
||||||
|
Location)) that takes the symbol as argument. That's the push parser we
|
||||||
|
are looking for.
|
||||||
|
|
||||||
|
- define a new parse() function which has the same signature as the usual
|
||||||
|
pull-parser, that repeatedly calls the push_parse function. Something
|
||||||
|
like this:
|
||||||
|
|
||||||
|
int parse ()
|
||||||
|
{
|
||||||
|
int status = 0;
|
||||||
|
do {
|
||||||
|
status = this->push_parse (yylex());
|
||||||
|
} while (status == YYPUSH_MORE);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
- show me that parser, so that we can validate the approach.
|
||||||
|
|
||||||
|
*** (2) Port that into the skeleton
|
||||||
|
- once we agree on the API of the push parser, implement it into lalr1.d.
|
||||||
|
You will probaby need help on this regard, but imitation, again, should
|
||||||
|
help.
|
||||||
|
|
||||||
|
- have example/d/pushcalc work properly and pass tests
|
||||||
|
|
||||||
|
- add tests in the "real" test suite. Do that in tests/calc.at. I can
|
||||||
|
help.
|
||||||
|
|
||||||
|
- document
|
||||||
|
|
||||||
|
** GLR Parser
|
||||||
|
This is very ambitious. That's the final boss. There are currently no
|
||||||
|
"clean" implementation to get inspiration from.
|
||||||
|
|
||||||
|
glr.c is very clean but:
|
||||||
|
- is low-level C
|
||||||
|
- is a different skeleton from yacc.c
|
||||||
|
|
||||||
|
glr.cc is (currently) an ugly hack: a C++ shell around glr.c. Valentin
|
||||||
|
Tolmer is currently rewriting glr.cc to be clean C++, but he is not
|
||||||
|
finished. There will be a lot a common code between lalr1.cc and glr.cc, so
|
||||||
|
eventually I would like them to be fused into a single skeleton, supporting
|
||||||
|
both deterministic and generalized parsing.
|
||||||
|
|
||||||
|
It would be great for D to also support this.
|
||||||
|
|
||||||
|
The basic ideas of GLR are explained here:
|
||||||
|
|
||||||
|
https://www.codeproject.com/Articles/5259825/GLR-Parsing-in-Csharp-How-to-Use-The-Most-Powerful
|
||||||
|
|
||||||
* Better error messages
|
* Better error messages
|
||||||
The users are not provided with enough tools to forge their error messages.
|
The users are not provided with enough tools to forge their error messages.
|
||||||
See for instance "Is there an option to change the message produced by
|
See for instance "Is there an option to change the message produced by
|
||||||
@@ -233,7 +496,7 @@ and older C++ compilers. Currently the code defaults to defining it to
|
|||||||
define it to the same type as the C ptrdiff_t type.
|
define it to the same type as the C ptrdiff_t type.
|
||||||
|
|
||||||
* Completion
|
* Completion
|
||||||
Several features are not available in all the backends.
|
Several features are not available in all the back-ends.
|
||||||
|
|
||||||
- lac: D, Java (easy)
|
- lac: D, Java (easy)
|
||||||
- push parsers: glr.c, glr.cc, lalr1.cc (not very difficult)
|
- push parsers: glr.c, glr.cc, lalr1.cc (not very difficult)
|
||||||
@@ -303,7 +566,7 @@ opposite side we have some use of \l, which is graphviz-specific, in what
|
|||||||
should be generic code.
|
should be generic code.
|
||||||
|
|
||||||
Little effort seems to have been given to factoring these files and their
|
Little effort seems to have been given to factoring these files and their
|
||||||
rint{,-xml} counterpart. We would very much like to re-use the pretty format
|
print{,-xml} counterpart. We would very much like to re-use the pretty format
|
||||||
of states from .output for the graphs, etc.
|
of states from .output for the graphs, etc.
|
||||||
|
|
||||||
Since graphviz dies on medium-to-big grammars, maybe consider an other tool?
|
Since graphviz dies on medium-to-big grammars, maybe consider an other tool?
|
||||||
@@ -581,14 +844,39 @@ to bison. If you're interested, I'll work on a patch.
|
|||||||
Equip the parser with a means to create the (visual) parse tree.
|
Equip the parser with a means to create the (visual) parse tree.
|
||||||
|
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
# LocalWords: Cex gnulib gl Bistromathic TokenKinds yylex enum YYEOF EOF
|
||||||
|
# LocalWords: YYerror gettext af hb YYERRCODE undef calc FIXME dev yyerror
|
||||||
|
# LocalWords: Autoconf YYUNDEFTOK lexemes parsers Bistromathic's yyreport
|
||||||
|
# LocalWords: const argc yacc yyclearin lookahead destructor Rici incluent
|
||||||
|
# LocalWords: yydestruct yydiscardin catégories d'avertissements sr activé
|
||||||
|
# LocalWords: conflits défaut rr l'alias chaîne n'est attaché un symbole
|
||||||
|
# LocalWords: obsolète règle vide midrule valeurs de intermédiaire ou avec
|
||||||
|
# LocalWords: définies inutilisées priorité associativité inutiles POSIX
|
||||||
|
# LocalWords: incompatibilités tous les autres avertissements sauf dans rp
|
||||||
|
# LocalWords: désactiver CATEGORIE traiter comme des erreurs glr Akim bool
|
||||||
|
# LocalWords: Demaille arith lalr goto struct pathlen nullable ntokens lr
|
||||||
|
# LocalWords: nterm bitsetv ielr ritem nstates nrules nritems yysymbol EQ
|
||||||
|
# LocalWords: SymbolKind YYEMPTY YYUNDEF YYTNAME NUM yyntokens yytname sed
|
||||||
|
# LocalWords: nonterminals yykind yycode YYNAMES yynames init getName conv
|
||||||
|
# LocalWords: TokenKind semanticVal ival yychar yylval yylexer Tolmer hoc
|
||||||
|
# LocalWords: Sobisch YYPTRDIFF ptrdiff Autotest YYPRINT toknum yytoknum
|
||||||
|
# LocalWords: sym Wother stderr FP fixits xgettext fdiagnostics Graphviz
|
||||||
|
# LocalWords: graphviz VCG bitset xml bw maint yytoken YYABORT deps
|
||||||
|
# LocalWords: YYACCEPT yytranslate nonnegative destructors yyerrlab repo
|
||||||
|
# LocalWords: backends stmt expr yy Mardle baz qux Vadim Maslow CPP cpp
|
||||||
|
# LocalWords: yydebug gcc UCHAR EBCDIC gung PDP NUL Pre Florian Krohm utf
|
||||||
|
# LocalWords: YYACT YYLLOC YYLSP yyval yyvsp yylen yyloc yylsp endif
|
||||||
|
# LocalWords: ispell american
|
||||||
|
|
||||||
Local Variables:
|
Local Variables:
|
||||||
mode: outline
|
mode: outline
|
||||||
coding: utf-8
|
coding: utf-8
|
||||||
fill-column: 76
|
fill-column: 76
|
||||||
|
ispell-dictionary: "american"
|
||||||
End:
|
End:
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
Copyright (C) 2001-2004, 2006, 2008-2015, 2018-2020 Free Software
|
Copyright (C) 2001-2004, 2006, 2008-2015, 2018-2020 Free Software
|
||||||
Foundation, Inc.
|
Foundation, Inc.
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -44,7 +44,9 @@ gnulib_modules='
|
|||||||
realloc-posix
|
realloc-posix
|
||||||
relocatable-prog relocatable-script
|
relocatable-prog relocatable-script
|
||||||
rename
|
rename
|
||||||
spawn-pipe stdbool stpcpy strdup-posix strerror strverscmp
|
spawn-pipe stdbool stpcpy stpncpy strdup-posix strerror strverscmp
|
||||||
|
sys_ioctl
|
||||||
|
termios
|
||||||
timevar
|
timevar
|
||||||
unicodeio unistd unistd-safer unlink unlocked-io
|
unicodeio unistd unistd-safer unlink unlocked-io
|
||||||
update-copyright unsetenv verify
|
update-copyright unsetenv verify
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ _sed_rm_comments_q = $(subst ','\'',$(_sed_remove_comments))
|
|||||||
|
|
||||||
_space_before_paren_exempt =? \\n\\$$
|
_space_before_paren_exempt =? \\n\\$$
|
||||||
_space_before_paren_exempt = \
|
_space_before_paren_exempt = \
|
||||||
(^ *\#|(LA)?LR\([01]\)|percent_(code|define)|b4_syncline|m4_(define|init)|symbol)
|
(^ *\#|(LA)?LR\([01]\)|percent_(code|define)|b4_syncline|m4_(define|init))
|
||||||
# Ensure that there is a space before each open parenthesis in C code.
|
# Ensure that there is a space before each open parenthesis in C code.
|
||||||
sc_space_before_open_paren:
|
sc_space_before_open_paren:
|
||||||
@if $(VC_LIST_EXCEPT) | grep -l '\.[ch]$$' > /dev/null; then \
|
@if $(VC_LIST_EXCEPT) | grep -l '\.[ch]$$' > /dev/null; then \
|
||||||
@@ -156,6 +156,7 @@ exclude = \
|
|||||||
$(call exclude, \
|
$(call exclude, \
|
||||||
bindtextdomain=^lib/main.c$$ \
|
bindtextdomain=^lib/main.c$$ \
|
||||||
cast_of_argument_to_free=^src/muscle-tab.c$$ \
|
cast_of_argument_to_free=^src/muscle-tab.c$$ \
|
||||||
|
error_message_uppercase=etc/bench.pl.in$$ \
|
||||||
po_check=^tests|(^po/POTFILES.in|.md)$$ \
|
po_check=^tests|(^po/POTFILES.in|.md)$$ \
|
||||||
preprocessor_indentation=^data/|^lib/|^src/parse-gram.[ch]$$ \
|
preprocessor_indentation=^data/|^lib/|^src/parse-gram.[ch]$$ \
|
||||||
program_name=^lib/main.c$$ \
|
program_name=^lib/main.c$$ \
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ AC_PROG_CXX
|
|||||||
# Gnulib (early checks).
|
# Gnulib (early checks).
|
||||||
gl_EARLY
|
gl_EARLY
|
||||||
|
|
||||||
|
# We want ostream_printf and hyperlink support.
|
||||||
|
gl_LIBTEXTSTYLE_OPTIONAL([0.20.5])
|
||||||
|
|
||||||
# Gnulib uses '#pragma GCC diagnostic push' to silence some
|
# Gnulib uses '#pragma GCC diagnostic push' to silence some
|
||||||
# warnings, but older gcc doesn't support this.
|
# warnings, but older gcc doesn't support this.
|
||||||
AC_CACHE_CHECK([whether pragma GCC diagnostic push works],
|
AC_CACHE_CHECK([whether pragma GCC diagnostic push works],
|
||||||
|
|||||||
+3
-3
@@ -86,7 +86,7 @@ The macro `b4_symbol(NUM, FIELD)` gives access to the following FIELDS:
|
|||||||
- `has_id`: 0 or 1
|
- `has_id`: 0 or 1
|
||||||
Whether the symbol has an `id`.
|
Whether the symbol has an `id`.
|
||||||
|
|
||||||
- `id`: string
|
- `id`: string (e.g., `exp`, `NUM`, or `TOK_NUM` with api.token.prefix)
|
||||||
If `has_id`, the name of the token kind (prefixed by api.token.prefix if
|
If `has_id`, the name of the token kind (prefixed by api.token.prefix if
|
||||||
defined), otherwise empty. Guaranteed to be usable as a C identifier.
|
defined), otherwise empty. Guaranteed to be usable as a C identifier.
|
||||||
This is used to define the token kind (i.e., the enum used by the return
|
This is used to define the token kind (i.e., the enum used by the return
|
||||||
@@ -105,9 +105,9 @@ The macro `b4_symbol(NUM, FIELD)` gives access to the following FIELDS:
|
|||||||
- `is_token`: 0 or 1
|
- `is_token`: 0 or 1
|
||||||
Whether this is a terminal symbol.
|
Whether this is a terminal symbol.
|
||||||
|
|
||||||
- `kind_base`: string
|
- `kind_base`: string (e.g., `YYSYMBOL_exp`, `YYSYMBOL_NUM`)
|
||||||
The base of the symbol kind, i.e., the enumerator of this symbol (token or
|
The base of the symbol kind, i.e., the enumerator of this symbol (token or
|
||||||
nonterminal) which is mapping to its `number`.
|
nonterminal) which is mapped to its `number`.
|
||||||
|
|
||||||
- `kind`: string
|
- `kind`: string
|
||||||
Same as `kind_base`, but possibly with a prefix in some languages. E.g.,
|
Same as `kind_base`, but possibly with a prefix in some languages. E.g.,
|
||||||
|
|||||||
@@ -49,6 +49,10 @@
|
|||||||
.cex-5 { color: orange; }
|
.cex-5 { color: orange; }
|
||||||
.cex-6 { color: brown; }
|
.cex-6 { color: brown; }
|
||||||
.cex-7 { color: mauve; }
|
.cex-7 { color: mauve; }
|
||||||
|
.cex-8 { color: #013220; } /* Dark green. */
|
||||||
|
.cex-9 { color: #e75480; } /* Dark pink. */
|
||||||
|
.cex-10 { color: cyan; }
|
||||||
|
.cex-11 { color: orange; }
|
||||||
|
|
||||||
/* Cex: derivation rewriting steps. */
|
/* Cex: derivation rewriting steps. */
|
||||||
.cex-step { font-style: italic; }
|
.cex-step { font-style: italic; }
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ m4_define([m4_shift4], [m4_shift(m4_shift(m4_shift(m4_shift($@))))])
|
|||||||
# b4_generated_by
|
# b4_generated_by
|
||||||
# ---------------
|
# ---------------
|
||||||
m4_define([b4_generated_by],
|
m4_define([b4_generated_by],
|
||||||
[b4_comment([A Bison parser, made by GNU Bison b4_version.])
|
[b4_comment([A Bison parser, made by GNU Bison b4_version_string.])
|
||||||
])
|
])
|
||||||
|
|
||||||
# b4_copyright(TITLE, [YEARS])
|
# b4_copyright(TITLE, [YEARS])
|
||||||
@@ -633,11 +633,11 @@ m4_define([_b4_type_action],
|
|||||||
|
|
||||||
])])
|
])])
|
||||||
|
|
||||||
# b4_type_foreach(MACRO)
|
# b4_type_foreach(MACRO, [SEP])
|
||||||
# ----------------------
|
# -----------------------------
|
||||||
# Invoke MACRO(SYMBOL-NUMS) for each set of SYMBOL-NUMS for each type set.
|
# Invoke MACRO(SYMBOL-NUMS) for each set of SYMBOL-NUMS for each type set.
|
||||||
m4_define([b4_type_foreach],
|
m4_define([b4_type_foreach],
|
||||||
[m4_map([$1], m4_defn([b4_type_names]))])
|
[m4_map_sep([$1], [$2], m4_defn([b4_type_names]))])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -321,8 +321,9 @@ m4_define([b4_symbol_type_define],
|
|||||||
/// Copy constructor.
|
/// Copy constructor.
|
||||||
basic_symbol (const basic_symbol& that);]b4_variant_if([[
|
basic_symbol (const basic_symbol& that);]b4_variant_if([[
|
||||||
|
|
||||||
/// Constructor for valueless symbols, and symbols from each type.
|
/// Constructors for typed symbols.
|
||||||
]b4_type_foreach([b4_basic_symbol_constructor_define])], [[
|
]b4_type_foreach([b4_basic_symbol_constructor_define], [
|
||||||
|
])], [[
|
||||||
/// Constructor for valueless symbols.
|
/// Constructor for valueless symbols.
|
||||||
basic_symbol (typename Base::kind_type t]b4_locations_if([,
|
basic_symbol (typename Base::kind_type t]b4_locations_if([,
|
||||||
YY_MOVE_REF (location_type) l])[);
|
YY_MOVE_REF (location_type) l])[);
|
||||||
@@ -594,11 +595,12 @@ m4_define([b4_yytranslate_define],
|
|||||||
{
|
{
|
||||||
]b4_translate[
|
]b4_translate[
|
||||||
};
|
};
|
||||||
const int code_max_ = ]b4_code_max[;
|
// Last valid token kind.
|
||||||
|
const int code_max = ]b4_code_max[;
|
||||||
|
|
||||||
if (t <= 0)
|
if (t <= 0)
|
||||||
return symbol_kind::]b4_symbol_prefix[YYEOF;
|
return symbol_kind::]b4_symbol_prefix[YYEOF;
|
||||||
else if (t <= code_max_)
|
else if (t <= code_max)
|
||||||
return YY_CAST (symbol_kind_type, translate_table[t]);
|
return YY_CAST (symbol_kind_type, translate_table[t]);
|
||||||
else
|
else
|
||||||
return symbol_kind::]b4_symbol_prefix[YYUNDEF;]])[
|
return symbol_kind::]b4_symbol_prefix[YYUNDEF;]])[
|
||||||
|
|||||||
+8
-7
@@ -58,11 +58,11 @@ m4_define([b4_cpp_guard_close],
|
|||||||
# b4_pull_flag if they use the values of the %define variables api.pure or
|
# b4_pull_flag if they use the values of the %define variables api.pure or
|
||||||
# api.push-pull.
|
# api.push-pull.
|
||||||
m4_define([b4_identification],
|
m4_define([b4_identification],
|
||||||
[[/* Identify Bison output. */
|
[[/* Identify Bison output, and Bison version. */
|
||||||
#define YYBISON 1
|
#define YYBISON ]b4_version[
|
||||||
|
|
||||||
/* Bison version. */
|
/* Bison version string. */
|
||||||
#define YYBISON_VERSION "]b4_version["
|
#define YYBISON_VERSION "]b4_version_string["
|
||||||
|
|
||||||
/* Skeleton name. */
|
/* Skeleton name. */
|
||||||
#define YYSKELETON_NAME ]b4_skeleton[]m4_ifdef([b4_pure_flag], [[
|
#define YYSKELETON_NAME ]b4_skeleton[]m4_ifdef([b4_pure_flag], [[
|
||||||
@@ -509,10 +509,11 @@ m4_define([b4_token_define],
|
|||||||
# ----------------
|
# ----------------
|
||||||
# Output the definition of the tokens.
|
# Output the definition of the tokens.
|
||||||
m4_define([b4_token_defines],
|
m4_define([b4_token_defines],
|
||||||
[b4_any_token_visible_if([/* Token kinds. */
|
[[/* Token kinds. */
|
||||||
m4_join([
|
#define ]b4_symbol([-2], [id])[ -2
|
||||||
|
]m4_join([
|
||||||
], b4_symbol_map([b4_token_define]))
|
], b4_symbol_map([b4_token_define]))
|
||||||
])])
|
])
|
||||||
|
|
||||||
|
|
||||||
# b4_token_enum(TOKEN-NUM)
|
# b4_token_enum(TOKEN-NUM)
|
||||||
|
|||||||
+4
-4
@@ -103,12 +103,12 @@ m4_define([b4_location_type_if],
|
|||||||
# b4_identification
|
# b4_identification
|
||||||
# -----------------
|
# -----------------
|
||||||
m4_define([b4_identification],
|
m4_define([b4_identification],
|
||||||
[/** Version number for the Bison executable that generated this parser. */
|
[[/** Version number for the Bison executable that generated this parser. */
|
||||||
public static immutable string yy_bison_version = "b4_version";
|
public static immutable string yy_bison_version = "]b4_version_string[";
|
||||||
|
|
||||||
/** Name of the skeleton that generated this parser. */
|
/** Name of the skeleton that generated this parser. */
|
||||||
public static immutable string yy_bison_skeleton = b4_skeleton;
|
public static immutable string yy_bison_skeleton = ]b4_skeleton[;
|
||||||
])
|
]])
|
||||||
|
|
||||||
|
|
||||||
## ------------ ##
|
## ------------ ##
|
||||||
|
|||||||
@@ -333,7 +333,7 @@ static YYLTYPE yyloc_default][]b4_yyloc_default;])[
|
|||||||
accessed by $0, $-1, etc., in any rule. */
|
accessed by $0, $-1, etc., in any rule. */
|
||||||
#define YYMAXLEFT ]b4_max_left_semantic_context[
|
#define YYMAXLEFT ]b4_max_left_semantic_context[
|
||||||
|
|
||||||
/* YYMAXUTOK -- Last valid token number (for yychar). */
|
/* YYMAXUTOK -- Last valid token kind. */
|
||||||
#define YYMAXUTOK ]b4_code_max[
|
#define YYMAXUTOK ]b4_code_max[
|
||||||
|
|
||||||
/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
|
/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
|
|||||||
const location_type* yylocationp]])[) const
|
const location_type* yylocationp]])[) const
|
||||||
{
|
{
|
||||||
*yycdebug_ << (yykind < YYNTOKENS ? "token" : "nterm")
|
*yycdebug_ << (yykind < YYNTOKENS ? "token" : "nterm")
|
||||||
<< ' ' << yytname[yykind] << " ("]b4_locations_if([[
|
<< ' ' << yysymbol_name (yykind) << " ("]b4_locations_if([[
|
||||||
<< *yylocationp << ": "]])[;
|
<< *yylocationp << ": "]])[;
|
||||||
yy_symbol_value_print_ (yykind, yyvaluep]b4_locations_if([[, yylocationp]])[);
|
yy_symbol_value_print_ (yykind, yyvaluep]b4_locations_if([[, yylocationp]])[);
|
||||||
*yycdebug_ << ')';
|
*yycdebug_ << ')';
|
||||||
|
|||||||
@@ -71,12 +71,12 @@ m4_define([b4_lexer_if],
|
|||||||
# b4_identification
|
# b4_identification
|
||||||
# -----------------
|
# -----------------
|
||||||
m4_define([b4_identification],
|
m4_define([b4_identification],
|
||||||
[ /** Version number for the Bison executable that generated this parser. */
|
[[ /** Version number for the Bison executable that generated this parser. */
|
||||||
public static final String bisonVersion = "b4_version";
|
public static final String bisonVersion = "]b4_version_string[";
|
||||||
|
|
||||||
/** Name of the skeleton that generated this parser. */
|
/** Name of the skeleton that generated this parser. */
|
||||||
public static final String bisonSkeleton = b4_skeleton;
|
public static final String bisonSkeleton = ]b4_skeleton[;
|
||||||
])
|
]])
|
||||||
|
|
||||||
|
|
||||||
## ------------ ##
|
## ------------ ##
|
||||||
|
|||||||
@@ -428,8 +428,9 @@ b4_locations_if([, ref ]b4_location_type[ yylocationp])[)
|
|||||||
*/
|
*/
|
||||||
public bool parse ()
|
public bool parse ()
|
||||||
{
|
{
|
||||||
/// Lookahead and lookahead in internal form.
|
// Lookahead token kind.
|
||||||
int yychar = TokenKind.YYEMPTY;
|
int yychar = TokenKind.YYEMPTY;
|
||||||
|
// Lookahead symbol kind.
|
||||||
SymbolKind yytoken = ]b4_symbol(-2, kind)[;
|
SymbolKind yytoken = ]b4_symbol(-2, kind)[;
|
||||||
|
|
||||||
/* State. */
|
/* State. */
|
||||||
@@ -841,11 +842,12 @@ m4_popdef([b4_at_dollar])])dnl
|
|||||||
]b4_translate[
|
]b4_translate[
|
||||||
@};
|
@};
|
||||||
|
|
||||||
immutable int code_max_ = ]b4_code_max[;
|
// Last valid token kind.
|
||||||
|
immutable int code_max = ]b4_code_max[;
|
||||||
|
|
||||||
if (t <= 0)
|
if (t <= 0)
|
||||||
return ]b4_symbol(0, kind)[;
|
return ]b4_symbol(0, kind)[;
|
||||||
else if (t <= code_max_)
|
else if (t <= code_max)
|
||||||
{
|
{
|
||||||
import std.conv : to;
|
import std.conv : to;
|
||||||
return to!SymbolKind (translate_table[t]);
|
return to!SymbolKind (translate_table[t]);
|
||||||
|
|||||||
@@ -53,8 +53,9 @@ b4_use_push_for_pull_if([
|
|||||||
# allows them to be defined either in parse() when doing pull parsing,
|
# allows them to be defined either in parse() when doing pull parsing,
|
||||||
# or as class instance variable when doing push parsing.
|
# or as class instance variable when doing push parsing.
|
||||||
m4_define([b4_define_state],[[
|
m4_define([b4_define_state],[[
|
||||||
/* Lookahead and lookahead in internal form. */
|
/* Lookahead token kind. */
|
||||||
int yychar = YYEMPTY_;
|
int yychar = YYEMPTY_;
|
||||||
|
/* Lookahead symbol kind. */
|
||||||
SymbolKind yytoken = null;
|
SymbolKind yytoken = null;
|
||||||
|
|
||||||
/* State. */
|
/* State. */
|
||||||
@@ -1078,17 +1079,18 @@ b4_dollar_popdef[]dnl
|
|||||||
|
|
||||||
/* YYTRANSLATE_(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
|
/* YYTRANSLATE_(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
|
||||||
as returned by yylex, with out-of-bounds checking. */
|
as returned by yylex, with out-of-bounds checking. */
|
||||||
private static final SymbolKind yytranslate_ (int t)
|
private static final SymbolKind yytranslate_(int t)
|
||||||
]b4_api_token_raw_if(dnl
|
]b4_api_token_raw_if(dnl
|
||||||
[[ {
|
[[ {
|
||||||
return SymbolKind.get(t);
|
return SymbolKind.get(t);
|
||||||
}
|
}
|
||||||
]],
|
]],
|
||||||
[[ {
|
[[ {
|
||||||
int code_max_ = ]b4_code_max[;
|
// Last valid token kind.
|
||||||
|
int code_max = ]b4_code_max[;
|
||||||
if (t <= 0)
|
if (t <= 0)
|
||||||
return ]b4_symbol(0, kind)[;
|
return ]b4_symbol(0, kind)[;
|
||||||
else if (t <= code_max_)
|
else if (t <= code_max)
|
||||||
return SymbolKind.get(yytranslate_table_[t]);
|
return SymbolKind.get(yytranslate_table_[t]);
|
||||||
else
|
else
|
||||||
return ]b4_symbol(2, kind)[;
|
return ]b4_symbol(2, kind)[;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ m4_pushdef([b4_copyright_years],
|
|||||||
# b4_position_file
|
# b4_position_file
|
||||||
# ----------------
|
# ----------------
|
||||||
# Name of the file containing the position class, if we want this file.
|
# Name of the file containing the position class, if we want this file.
|
||||||
b4_defines_if([b4_required_version_if([302], [],
|
b4_defines_if([b4_required_version_if([30200], [],
|
||||||
[m4_define([b4_position_file], [position.hh])])])])
|
[m4_define([b4_position_file], [position.hh])])])])
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
# b4_stack_file
|
# b4_stack_file
|
||||||
# -------------
|
# -------------
|
||||||
# Name of the file containing the stack class, if we want this file.
|
# Name of the file containing the stack class, if we want this file.
|
||||||
b4_defines_if([b4_required_version_if([302], [],
|
b4_defines_if([b4_required_version_if([30200], [],
|
||||||
[m4_define([b4_stack_file], [stack.hh])])])
|
[m4_define([b4_stack_file], [stack.hh])])])
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+101
-41
@@ -20,6 +20,13 @@
|
|||||||
## variant. ##
|
## variant. ##
|
||||||
## --------- ##
|
## --------- ##
|
||||||
|
|
||||||
|
# b4_assert
|
||||||
|
# ---------
|
||||||
|
# The name of YY_ASSERT.
|
||||||
|
m4_define([b4_assert],
|
||||||
|
[b4_api_PREFIX[]_ASSERT])
|
||||||
|
|
||||||
|
|
||||||
# b4_symbol_variant(YYTYPE, YYVAL, ACTION, [ARGS])
|
# b4_symbol_variant(YYTYPE, YYVAL, ACTION, [ARGS])
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
# Run some ACTION ("build", or "destroy") on YYVAL of symbol type
|
# Run some ACTION ("build", or "destroy") on YYVAL of symbol type
|
||||||
@@ -71,12 +78,12 @@ m4_map([ b4_symbol_tag_comment], [$@])dnl
|
|||||||
# -------------------
|
# -------------------
|
||||||
# The needed includes for variants support.
|
# The needed includes for variants support.
|
||||||
m4_define([b4_variant_includes],
|
m4_define([b4_variant_includes],
|
||||||
[b4_parse_assert_if([[#include <typeinfo>]])[
|
[b4_parse_assert_if([[#include <typeinfo>
|
||||||
#ifndef YY_ASSERT
|
#ifndef ]b4_assert[
|
||||||
# include <cassert>
|
# include <cassert>
|
||||||
# define YY_ASSERT assert
|
# define ]b4_assert[ assert
|
||||||
#endif
|
#endif
|
||||||
]])
|
]])])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -110,8 +117,8 @@ m4_define([b4_value_type_declare],
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
semantic_type (YY_RVREF (T) t)]b4_parse_assert_if([
|
semantic_type (YY_RVREF (T) t)]b4_parse_assert_if([
|
||||||
: yytypeid_ (&typeid (T))])[
|
: yytypeid_ (&typeid (T))])[
|
||||||
{
|
{]b4_parse_assert_if([[
|
||||||
YY_ASSERT (sizeof (T) <= size);
|
]b4_assert[ (sizeof (T) <= size);]])[
|
||||||
new (yyas_<T> ()) T (YY_MOVE (t));
|
new (yyas_<T> ()) T (YY_MOVE (t));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +132,7 @@ m4_define([b4_value_type_declare],
|
|||||||
/// Destruction, allowed only if empty.
|
/// Destruction, allowed only if empty.
|
||||||
~semantic_type () YY_NOEXCEPT
|
~semantic_type () YY_NOEXCEPT
|
||||||
{]b4_parse_assert_if([
|
{]b4_parse_assert_if([
|
||||||
YY_ASSERT (!yytypeid_);
|
]b4_assert[ (!yytypeid_);
|
||||||
])[}
|
])[}
|
||||||
|
|
||||||
# if 201103L <= YY_CPLUSPLUS
|
# if 201103L <= YY_CPLUSPLUS
|
||||||
@@ -133,10 +140,10 @@ m4_define([b4_value_type_declare],
|
|||||||
template <typename T, typename... U>
|
template <typename T, typename... U>
|
||||||
T&
|
T&
|
||||||
emplace (U&&... u)
|
emplace (U&&... u)
|
||||||
{]b4_parse_assert_if([
|
{]b4_parse_assert_if([[
|
||||||
YY_ASSERT (!yytypeid_);
|
]b4_assert[ (!yytypeid_);
|
||||||
YY_ASSERT (sizeof (T) <= size);
|
]b4_assert[ (sizeof (T) <= size);
|
||||||
yytypeid_ = & typeid (T);])[
|
yytypeid_ = & typeid (T);]])[
|
||||||
return *new (yyas_<T> ()) T (std::forward <U>(u)...);
|
return *new (yyas_<T> ()) T (std::forward <U>(u)...);
|
||||||
}
|
}
|
||||||
# else
|
# else
|
||||||
@@ -144,10 +151,10 @@ m4_define([b4_value_type_declare],
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
T&
|
T&
|
||||||
emplace ()
|
emplace ()
|
||||||
{]b4_parse_assert_if([
|
{]b4_parse_assert_if([[
|
||||||
YY_ASSERT (!yytypeid_);
|
]b4_assert[ (!yytypeid_);
|
||||||
YY_ASSERT (sizeof (T) <= size);
|
]b4_assert[ (sizeof (T) <= size);
|
||||||
yytypeid_ = & typeid (T);])[
|
yytypeid_ = & typeid (T);]])[
|
||||||
return *new (yyas_<T> ()) T ();
|
return *new (yyas_<T> ()) T ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,10 +162,10 @@ m4_define([b4_value_type_declare],
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
T&
|
T&
|
||||||
emplace (const T& t)
|
emplace (const T& t)
|
||||||
{]b4_parse_assert_if([
|
{]b4_parse_assert_if([[
|
||||||
YY_ASSERT (!yytypeid_);
|
]b4_assert[ (!yytypeid_);
|
||||||
YY_ASSERT (sizeof (T) <= size);
|
]b4_assert[ (sizeof (T) <= size);
|
||||||
yytypeid_ = & typeid (T);])[
|
yytypeid_ = & typeid (T);]])[
|
||||||
return *new (yyas_<T> ()) T (t);
|
return *new (yyas_<T> ()) T (t);
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
@@ -185,10 +192,10 @@ m4_define([b4_value_type_declare],
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
T&
|
T&
|
||||||
as () YY_NOEXCEPT
|
as () YY_NOEXCEPT
|
||||||
{]b4_parse_assert_if([
|
{]b4_parse_assert_if([[
|
||||||
YY_ASSERT (yytypeid_);
|
]b4_assert[ (yytypeid_);
|
||||||
YY_ASSERT (*yytypeid_ == typeid (T));
|
]b4_assert[ (*yytypeid_ == typeid (T));
|
||||||
YY_ASSERT (sizeof (T) <= size);])[
|
]b4_assert[ (sizeof (T) <= size);]])[
|
||||||
return *yyas_<T> ();
|
return *yyas_<T> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,10 +203,10 @@ m4_define([b4_value_type_declare],
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
const T&
|
const T&
|
||||||
as () const YY_NOEXCEPT
|
as () const YY_NOEXCEPT
|
||||||
{]b4_parse_assert_if([
|
{]b4_parse_assert_if([[
|
||||||
YY_ASSERT (yytypeid_);
|
]b4_assert[ (yytypeid_);
|
||||||
YY_ASSERT (*yytypeid_ == typeid (T));
|
]b4_assert[ (*yytypeid_ == typeid (T));
|
||||||
YY_ASSERT (sizeof (T) <= size);])[
|
]b4_assert[ (sizeof (T) <= size);]])[
|
||||||
return *yyas_<T> ();
|
return *yyas_<T> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,9 +221,9 @@ m4_define([b4_value_type_declare],
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
void
|
void
|
||||||
swap (self_type& that) YY_NOEXCEPT
|
swap (self_type& that) YY_NOEXCEPT
|
||||||
{]b4_parse_assert_if([
|
{]b4_parse_assert_if([[
|
||||||
YY_ASSERT (yytypeid_);
|
]b4_assert[ (yytypeid_);
|
||||||
YY_ASSERT (*yytypeid_ == *that.yytypeid_);])[
|
]b4_assert[ (*yytypeid_ == *that.yytypeid_);]])[
|
||||||
std::swap (as<T> (), that.as<T> ());
|
std::swap (as<T> (), that.as<T> ());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,11 +395,67 @@ m4_define([_b4_token_maker_define],
|
|||||||
])])
|
])])
|
||||||
|
|
||||||
|
|
||||||
m4_define([_b4_type_clause],
|
# b4_token_kind(SYMBOL-NUM)
|
||||||
[b4_symbol_if([$1], [is_token],
|
# -------------------------
|
||||||
[b4_symbol_if([$1], [has_id],
|
# Some tokens don't have an ID.
|
||||||
[tok == token::b4_symbol([$1], [id])],
|
m4_define([b4_token_kind],
|
||||||
[tok == b4_symbol([$1], [code])])])])
|
[b4_symbol_if([$1], [has_id],
|
||||||
|
[token::b4_symbol([$1], [id])],
|
||||||
|
[b4_symbol([$1], [code])])])
|
||||||
|
|
||||||
|
|
||||||
|
# _b4_tok_in(SYMBOL-NUM, ...)
|
||||||
|
# ---------------------------
|
||||||
|
# See b4_tok_in below. The SYMBOL-NUMs... are tokens only.
|
||||||
|
#
|
||||||
|
# We iterate over the tokens to group them by "range" of token numbers (not
|
||||||
|
# symbols numbers!).
|
||||||
|
#
|
||||||
|
# b4_fst is the start of that range.
|
||||||
|
# b4_prev is the previous value.
|
||||||
|
# b4_val is the current value.
|
||||||
|
# If b4_val is the successor of b4_prev in token numbers, update the latter,
|
||||||
|
# otherwise emit the code for range b4_fst .. b4_prev.
|
||||||
|
# $1 is also used as a terminator in the foreach, but it will not be printed.
|
||||||
|
#
|
||||||
|
m4_define([_b4_tok_in],
|
||||||
|
[m4_pushdef([b4_prev], [$1])dnl
|
||||||
|
m4_pushdef([b4_fst], [$1])dnl
|
||||||
|
m4_pushdef([b4_sep], [])dnl
|
||||||
|
m4_foreach([b4_val], m4_dquote(m4_shift($@, $1)),
|
||||||
|
[m4_if(b4_symbol(b4_val, [code]), m4_eval(b4_symbol(b4_prev, [code]) + 1), [],
|
||||||
|
[b4_sep[]m4_if(b4_fst, b4_prev,
|
||||||
|
[tok == b4_token_kind(b4_fst)],
|
||||||
|
[(b4_token_kind(b4_fst) <= tok && tok <= b4_token_kind(b4_prev))])[]dnl
|
||||||
|
m4_define([b4_fst], b4_val)dnl
|
||||||
|
m4_define([b4_sep], [
|
||||||
|
|| ])])dnl
|
||||||
|
m4_define([b4_prev], b4_val)])dnl
|
||||||
|
m4_popdef([b4_sep])dnl
|
||||||
|
m4_popdef([b4_fst])dnl
|
||||||
|
m4_popdef([b4_prev])dnl
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
# _b4_filter_tokens(SYMBOL-NUM, ...)
|
||||||
|
# ----------------------------------
|
||||||
|
# Expand as the list of tokens amongst SYMBOL-NUM.
|
||||||
|
m4_define([_b4_filter_tokens],
|
||||||
|
[m4_pushdef([b4_sep])dnl
|
||||||
|
m4_foreach([b4_val], [$@],
|
||||||
|
[b4_symbol_if(b4_val, [is_token], [b4_sep[]b4_val[]m4_define([b4_sep], [,])])])dnl
|
||||||
|
m4_popdef([b4_sep])dnl
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
# b4_tok_in(SYMBOL-NUM, ...)
|
||||||
|
# ---------------------------
|
||||||
|
# A C++ conditional that checks that `tok` is a member of this list of symbol
|
||||||
|
# numbers.
|
||||||
|
m4_define([b4_tok_in],
|
||||||
|
[_$0(_b4_filter_tokens($@))])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# _b4_token_constructor_define(SYMBOL-NUM...)
|
# _b4_token_constructor_define(SYMBOL-NUM...)
|
||||||
@@ -410,9 +473,6 @@ m4_define([_b4_token_constructor_define],
|
|||||||
: super_type(]b4_join([token_type (tok)],
|
: super_type(]b4_join([token_type (tok)],
|
||||||
b4_symbol_if([$1], [has_type], [std::move (v)]),
|
b4_symbol_if([$1], [has_type], [std::move (v)]),
|
||||||
b4_locations_if([std::move (l)]))[)
|
b4_locations_if([std::move (l)]))[)
|
||||||
{
|
|
||||||
YY_ASSERT (]m4_join([ || ], m4_map_sep([_b4_type_clause], [, ], [$@]))[);
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
symbol_type (]b4_join(
|
symbol_type (]b4_join(
|
||||||
[int tok],
|
[int tok],
|
||||||
@@ -422,10 +482,10 @@ m4_define([_b4_token_constructor_define],
|
|||||||
: super_type(]b4_join([token_type (tok)],
|
: super_type(]b4_join([token_type (tok)],
|
||||||
b4_symbol_if([$1], [has_type], [v]),
|
b4_symbol_if([$1], [has_type], [v]),
|
||||||
b4_locations_if([l]))[)
|
b4_locations_if([l]))[)
|
||||||
{
|
|
||||||
YY_ASSERT (]m4_join([ || ], m4_map_sep([_b4_type_clause], [, ], [$@]))[);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
{]b4_parse_assert_if([[
|
||||||
|
]b4_assert[ (]b4_tok_in($@)[);
|
||||||
|
]])[}
|
||||||
]])])
|
]])])
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ m4_define([b4_pure_if],
|
|||||||
## api.push-pull. ##
|
## api.push-pull. ##
|
||||||
## --------------- ##
|
## --------------- ##
|
||||||
|
|
||||||
|
# b4_pull_if, b4_push_if
|
||||||
|
# ----------------------
|
||||||
|
# Whether the pull/push APIs are needed. Both can be enabled.
|
||||||
|
|
||||||
b4_percent_define_default([[api.push-pull]], [[pull]])
|
b4_percent_define_default([[api.push-pull]], [[pull]])
|
||||||
b4_percent_define_check_values([[[[api.push-pull]],
|
b4_percent_define_check_values([[[[api.push-pull]],
|
||||||
[[pull]], [[push]], [[both]]]])
|
[[pull]], [[push]], [[both]]]])
|
||||||
@@ -155,7 +159,7 @@ m4_define([b4_rhs_location],
|
|||||||
# Declare the variables that are global, or local to YYPARSE if
|
# Declare the variables that are global, or local to YYPARSE if
|
||||||
# pure-parser.
|
# pure-parser.
|
||||||
m4_define([b4_declare_scanner_communication_variables], [[
|
m4_define([b4_declare_scanner_communication_variables], [[
|
||||||
/* The lookahead symbol. */
|
/* Lookahead token kind. */
|
||||||
int yychar;
|
int yychar;
|
||||||
|
|
||||||
]b4_pure_if([[
|
]b4_pure_if([[
|
||||||
@@ -571,6 +575,7 @@ union yyalloc
|
|||||||
/* YYNSTATES -- Number of states. */
|
/* YYNSTATES -- Number of states. */
|
||||||
#define YYNSTATES ]b4_states_number[
|
#define YYNSTATES ]b4_states_number[
|
||||||
|
|
||||||
|
/* YYMAXUTOK -- Last valid token kind. */
|
||||||
#define YYMAXUTOK ]b4_code_max[
|
#define YYMAXUTOK ]b4_code_max[
|
||||||
|
|
||||||
|
|
||||||
@@ -1481,7 +1486,7 @@ yypstate_new (void)
|
|||||||
yypstate *yyps;]b4_pure_if([], [[
|
yypstate *yyps;]b4_pure_if([], [[
|
||||||
if (yypstate_allocated)
|
if (yypstate_allocated)
|
||||||
return YY_NULLPTR;]])[
|
return YY_NULLPTR;]])[
|
||||||
yyps = YY_CAST (yypstate *, malloc (sizeof *yyps));
|
yyps = YY_CAST (yypstate *, YYMALLOC (sizeof *yyps));
|
||||||
if (!yyps)
|
if (!yyps)
|
||||||
return YY_NULLPTR;]b4_pure_if([], [[
|
return YY_NULLPTR;]b4_pure_if([], [[
|
||||||
yypstate_allocated = 1;]])[
|
yypstate_allocated = 1;]])[
|
||||||
@@ -1510,7 +1515,7 @@ yypstate_delete (yypstate *yyps)
|
|||||||
#endif]b4_lac_if([[
|
#endif]b4_lac_if([[
|
||||||
if (yyes != yyesa)
|
if (yyes != yyesa)
|
||||||
YYSTACK_FREE (yyes);]])[
|
YYSTACK_FREE (yyes);]])[
|
||||||
free (yyps);]b4_pure_if([], [[
|
YYFREE (yyps);]b4_pure_if([], [[
|
||||||
yypstate_allocated = 0;]])[
|
yypstate_allocated = 0;]])[
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1544,7 +1549,7 @@ yyparse (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[)]])[
|
|||||||
int yyn;
|
int yyn;
|
||||||
/* The return value of yyparse. */
|
/* The return value of yyparse. */
|
||||||
int yyresult;
|
int yyresult;
|
||||||
/* Lookahead token as an internal (translated) token number. */
|
/* Lookahead symbol kind. */
|
||||||
yysymbol_kind_t yytoken = ]b4_symbol(-2, kind)[;
|
yysymbol_kind_t yytoken = ]b4_symbol(-2, kind)[;
|
||||||
/* The variables used to return semantic value and location from the
|
/* The variables used to return semantic value and location from the
|
||||||
action routines. */
|
action routines. */
|
||||||
|
|||||||
+14
-6
@@ -52,7 +52,7 @@
|
|||||||
<xsl:if test="nonterminal[@usefulness='useless-in-grammar']">
|
<xsl:if test="nonterminal[@usefulness='useless-in-grammar']">
|
||||||
<xsl:text>Nonterminals useless in grammar </xsl:text>
|
<xsl:text>Nonterminals useless in grammar </xsl:text>
|
||||||
<xsl:for-each select="nonterminal[@usefulness='useless-in-grammar']">
|
<xsl:for-each select="nonterminal[@usefulness='useless-in-grammar']">
|
||||||
<xsl:text> </xsl:text>
|
<xsl:text> </xsl:text>
|
||||||
<xsl:value-of select="@name"/>
|
<xsl:value-of select="@name"/>
|
||||||
<xsl:text> </xsl:text>
|
<xsl:text> </xsl:text>
|
||||||
</xsl:for-each>
|
</xsl:for-each>
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
<xsl:text>Terminals unused in grammar </xsl:text>
|
<xsl:text>Terminals unused in grammar </xsl:text>
|
||||||
<xsl:for-each select="terminal[@usefulness='unused-in-grammar']">
|
<xsl:for-each select="terminal[@usefulness='unused-in-grammar']">
|
||||||
<xsl:sort select="@symbol-number" data-type="number"/>
|
<xsl:sort select="@symbol-number" data-type="number"/>
|
||||||
<xsl:text> </xsl:text>
|
<xsl:text> </xsl:text>
|
||||||
<xsl:value-of select="@name"/>
|
<xsl:value-of select="@name"/>
|
||||||
<xsl:text> </xsl:text>
|
<xsl:text> </xsl:text>
|
||||||
</xsl:for-each>
|
</xsl:for-each>
|
||||||
@@ -136,6 +136,7 @@
|
|||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
<xsl:template match="terminal">
|
<xsl:template match="terminal">
|
||||||
|
<xsl:text> </xsl:text>
|
||||||
<xsl:value-of select="@name"/>
|
<xsl:value-of select="@name"/>
|
||||||
<xsl:call-template name="line-wrap">
|
<xsl:call-template name="line-wrap">
|
||||||
<xsl:with-param name="first-line-length">
|
<xsl:with-param name="first-line-length">
|
||||||
@@ -148,6 +149,9 @@
|
|||||||
</xsl:with-param>
|
</xsl:with-param>
|
||||||
<xsl:with-param name="line-length" select="66" />
|
<xsl:with-param name="line-length" select="66" />
|
||||||
<xsl:with-param name="text">
|
<xsl:with-param name="text">
|
||||||
|
<xsl:if test="string-length(@type) != 0">
|
||||||
|
<xsl:value-of select="concat(' <', @type, '>')"/>
|
||||||
|
</xsl:if>
|
||||||
<xsl:value-of select="concat(' (', @token-number, ')')"/>
|
<xsl:value-of select="concat(' (', @token-number, ')')"/>
|
||||||
<xsl:for-each select="key('bison:ruleByRhs', @name)">
|
<xsl:for-each select="key('bison:ruleByRhs', @name)">
|
||||||
<xsl:value-of select="concat(' ', @number)"/>
|
<xsl:value-of select="concat(' ', @number)"/>
|
||||||
@@ -157,14 +161,18 @@
|
|||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
<xsl:template match="nonterminal">
|
<xsl:template match="nonterminal">
|
||||||
|
<xsl:text> </xsl:text>
|
||||||
<xsl:value-of select="@name"/>
|
<xsl:value-of select="@name"/>
|
||||||
|
<xsl:if test="string-length(@type) != 0">
|
||||||
|
<xsl:value-of select="concat(' <', @type, '>')"/>
|
||||||
|
</xsl:if>
|
||||||
<xsl:value-of select="concat(' (', @symbol-number, ')')"/>
|
<xsl:value-of select="concat(' (', @symbol-number, ')')"/>
|
||||||
<xsl:text> </xsl:text>
|
<xsl:text> </xsl:text>
|
||||||
<xsl:variable name="output">
|
<xsl:variable name="output">
|
||||||
<xsl:call-template name="line-wrap">
|
<xsl:call-template name="line-wrap">
|
||||||
<xsl:with-param name="line-length" select="66" />
|
<xsl:with-param name="line-length" select="66" />
|
||||||
<xsl:with-param name="text">
|
<xsl:with-param name="text">
|
||||||
<xsl:text> </xsl:text>
|
<xsl:text> </xsl:text>
|
||||||
<xsl:if test="key('bison:ruleByLhs', @name)">
|
<xsl:if test="key('bison:ruleByLhs', @name)">
|
||||||
<xsl:text>on@left:</xsl:text>
|
<xsl:text>on@left:</xsl:text>
|
||||||
<xsl:for-each select="key('bison:ruleByLhs', @name)">
|
<xsl:for-each select="key('bison:ruleByLhs', @name)">
|
||||||
@@ -173,7 +181,7 @@
|
|||||||
</xsl:if>
|
</xsl:if>
|
||||||
<xsl:if test="key('bison:ruleByRhs', @name)">
|
<xsl:if test="key('bison:ruleByRhs', @name)">
|
||||||
<xsl:if test="key('bison:ruleByLhs', @name)">
|
<xsl:if test="key('bison:ruleByLhs', @name)">
|
||||||
<xsl:text>, </xsl:text>
|
<xsl:text> </xsl:text>
|
||||||
</xsl:if>
|
</xsl:if>
|
||||||
<xsl:text>on@right:</xsl:text>
|
<xsl:text>on@right:</xsl:text>
|
||||||
<xsl:for-each select="key('bison:ruleByRhs', @name)">
|
<xsl:for-each select="key('bison:ruleByRhs', @name)">
|
||||||
@@ -348,11 +356,11 @@
|
|||||||
<!-- RHS -->
|
<!-- RHS -->
|
||||||
<xsl:for-each select="rhs/*">
|
<xsl:for-each select="rhs/*">
|
||||||
<xsl:if test="position() = $dot + 1">
|
<xsl:if test="position() = $dot + 1">
|
||||||
<xsl:text> .</xsl:text>
|
<xsl:text> •</xsl:text>
|
||||||
</xsl:if>
|
</xsl:if>
|
||||||
<xsl:apply-templates select="."/>
|
<xsl:apply-templates select="."/>
|
||||||
<xsl:if test="position() = last() and position() = $dot">
|
<xsl:if test="position() = last() and position() = $dot">
|
||||||
<xsl:text> .</xsl:text>
|
<xsl:text> •</xsl:text>
|
||||||
</xsl:if>
|
</xsl:if>
|
||||||
</xsl:for-each>
|
</xsl:for-each>
|
||||||
<xsl:if test="$lookaheads">
|
<xsl:if test="$lookaheads">
|
||||||
|
|||||||
+72
-48
@@ -227,6 +227,7 @@
|
|||||||
<xsl:text> </xsl:text>
|
<xsl:text> </xsl:text>
|
||||||
<p class="pre">
|
<p class="pre">
|
||||||
<xsl:call-template name="style-rule-set">
|
<xsl:call-template name="style-rule-set">
|
||||||
|
<xsl:with-param name="anchor" select="'true'" />
|
||||||
<xsl:with-param
|
<xsl:with-param
|
||||||
name="rule-set" select="rules/rule[@usefulness!='useless-in-grammar']"
|
name="rule-set" select="rules/rule[@usefulness!='useless-in-grammar']"
|
||||||
/>
|
/>
|
||||||
@@ -238,9 +239,11 @@
|
|||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
<xsl:template name="style-rule-set">
|
<xsl:template name="style-rule-set">
|
||||||
|
<xsl:param name="anchor"/>
|
||||||
<xsl:param name="rule-set"/>
|
<xsl:param name="rule-set"/>
|
||||||
<xsl:for-each select="$rule-set">
|
<xsl:for-each select="$rule-set">
|
||||||
<xsl:apply-templates select=".">
|
<xsl:apply-templates select=".">
|
||||||
|
<xsl:with-param name="anchor" select="$anchor"/>
|
||||||
<xsl:with-param name="pad" select="'3'"/>
|
<xsl:with-param name="pad" select="'3'"/>
|
||||||
<xsl:with-param name="prev-lhs">
|
<xsl:with-param name="prev-lhs">
|
||||||
<xsl:if test="position()>1">
|
<xsl:if test="position()>1">
|
||||||
@@ -306,9 +309,10 @@
|
|||||||
<xsl:text> Terminals, with rules where they appear</xsl:text>
|
<xsl:text> Terminals, with rules where they appear</xsl:text>
|
||||||
</h3>
|
</h3>
|
||||||
<xsl:text> </xsl:text>
|
<xsl:text> </xsl:text>
|
||||||
<p class="pre">
|
<ul>
|
||||||
|
<xsl:text> </xsl:text>
|
||||||
<xsl:apply-templates select="terminal"/>
|
<xsl:apply-templates select="terminal"/>
|
||||||
</p>
|
</ul>
|
||||||
<xsl:text> </xsl:text>
|
<xsl:text> </xsl:text>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
@@ -318,41 +322,64 @@
|
|||||||
<xsl:text> Nonterminals, with rules where they appear</xsl:text>
|
<xsl:text> Nonterminals, with rules where they appear</xsl:text>
|
||||||
</h3>
|
</h3>
|
||||||
<xsl:text> </xsl:text>
|
<xsl:text> </xsl:text>
|
||||||
<p class="pre">
|
<ul>
|
||||||
|
<xsl:text> </xsl:text>
|
||||||
<xsl:apply-templates
|
<xsl:apply-templates
|
||||||
select="nonterminal[@usefulness!='useless-in-grammar']"
|
select="nonterminal[@usefulness!='useless-in-grammar']"
|
||||||
/>
|
/>
|
||||||
</p>
|
</ul>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
<xsl:template match="terminal">
|
<xsl:template match="terminal">
|
||||||
<b><xsl:value-of select="@name"/></b>
|
<xsl:text> </xsl:text>
|
||||||
<xsl:value-of select="concat(' (', @token-number, ')')"/>
|
<li>
|
||||||
<xsl:for-each select="key('bison:ruleByRhs', @name)">
|
<b><xsl:value-of select="@name"/></b>
|
||||||
<xsl:apply-templates select="." mode="number-link"/>
|
<xsl:if test="string-length(@type) != 0">
|
||||||
</xsl:for-each>
|
<xsl:value-of select="concat(' <', @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:text> </xsl:text>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
<xsl:template match="nonterminal">
|
<xsl:template match="nonterminal">
|
||||||
<b><xsl:value-of select="@name"/></b>
|
<xsl:text> </xsl:text>
|
||||||
<xsl:value-of select="concat(' (', @symbol-number, ')')"/>
|
<li>
|
||||||
<xsl:text> </xsl:text>
|
<b><xsl:value-of select="@name"/></b>
|
||||||
<xsl:if test="key('bison:ruleByLhs', @name)">
|
<xsl:if test="string-length(@type) != 0">
|
||||||
<xsl:text>on left:</xsl:text>
|
<xsl:value-of select="concat(' <', @type, '>')"/>
|
||||||
<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:if>
|
</xsl:if>
|
||||||
<xsl:text>on right:</xsl:text>
|
<xsl:value-of select="concat(' (', @symbol-number, ')')"/>
|
||||||
<xsl:for-each select="key('bison:ruleByRhs', @name)">
|
<xsl:text> </xsl:text>
|
||||||
<xsl:apply-templates select="." mode="number-link"/>
|
<ul>
|
||||||
</xsl:for-each>
|
<xsl:text> </xsl:text>
|
||||||
</xsl:if>
|
<xsl:if test="key('bison:ruleByLhs', @name)">
|
||||||
|
<xsl:text> </xsl:text>
|
||||||
|
<li>
|
||||||
|
<xsl:text>on left:</xsl:text>
|
||||||
|
<xsl:for-each select="key('bison:ruleByLhs', @name)">
|
||||||
|
<xsl:apply-templates select="." mode="number-link"/>
|
||||||
|
</xsl:for-each>
|
||||||
|
</li>
|
||||||
|
<xsl:text> </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:text> </xsl:text>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
@@ -385,7 +412,7 @@
|
|||||||
<xsl:value-of select="concat('state_', @number)"/>
|
<xsl:value-of select="concat('state_', @number)"/>
|
||||||
</xsl:attribute>
|
</xsl:attribute>
|
||||||
</a>
|
</a>
|
||||||
<xsl:text>state </xsl:text>
|
<xsl:text>State </xsl:text>
|
||||||
<xsl:value-of select="@number"/>
|
<xsl:value-of select="@number"/>
|
||||||
</h3>
|
</h3>
|
||||||
<xsl:text> </xsl:text>
|
<xsl:text> </xsl:text>
|
||||||
@@ -464,7 +491,12 @@
|
|||||||
</xsl:apply-templates>
|
</xsl:apply-templates>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
anchor = 'true': define as an <a> anchor.
|
||||||
|
itemset = 'true': show the items.
|
||||||
|
-->
|
||||||
<xsl:template match="rule">
|
<xsl:template match="rule">
|
||||||
|
<xsl:param name="anchor"/>
|
||||||
<xsl:param name="itemset"/>
|
<xsl:param name="itemset"/>
|
||||||
<xsl:param name="pad"/>
|
<xsl:param name="pad"/>
|
||||||
<xsl:param name="prev-lhs"/>
|
<xsl:param name="prev-lhs"/>
|
||||||
@@ -475,17 +507,21 @@
|
|||||||
<xsl:text> </xsl:text>
|
<xsl:text> </xsl:text>
|
||||||
</xsl:if>
|
</xsl:if>
|
||||||
|
|
||||||
<xsl:if test="$itemset != 'true'">
|
|
||||||
<a>
|
|
||||||
<xsl:attribute name="name">
|
|
||||||
<xsl:value-of select="concat('rule_', @number)"/>
|
|
||||||
</xsl:attribute>
|
|
||||||
</a>
|
|
||||||
</xsl:if>
|
|
||||||
<xsl:text> </xsl:text>
|
<xsl:text> </xsl:text>
|
||||||
|
|
||||||
<xsl:choose>
|
<xsl:choose>
|
||||||
<xsl:when test="$itemset = 'true'">
|
<xsl:when test="$anchor = 'true'">
|
||||||
|
<a>
|
||||||
|
<xsl:attribute name="name">
|
||||||
|
<xsl:value-of select="concat('rule_', @number)"/>
|
||||||
|
</xsl:attribute>
|
||||||
|
<xsl:call-template name="lpad">
|
||||||
|
<xsl:with-param name="str" select="string(@number)"/>
|
||||||
|
<xsl:with-param name="pad" select="number($pad)"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</a>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:otherwise>
|
||||||
<a>
|
<a>
|
||||||
<xsl:attribute name="href">
|
<xsl:attribute name="href">
|
||||||
<xsl:value-of select="concat('#rule_', @number)"/>
|
<xsl:value-of select="concat('#rule_', @number)"/>
|
||||||
@@ -495,25 +531,13 @@
|
|||||||
<xsl:with-param name="pad" select="number($pad)"/>
|
<xsl:with-param name="pad" select="number($pad)"/>
|
||||||
</xsl:call-template>
|
</xsl:call-template>
|
||||||
</a>
|
</a>
|
||||||
</xsl:when>
|
|
||||||
<xsl:otherwise>
|
|
||||||
<xsl:call-template name="lpad">
|
|
||||||
<xsl:with-param name="str" select="string(@number)"/>
|
|
||||||
<xsl:with-param name="pad" select="number($pad)"/>
|
|
||||||
</xsl:call-template>
|
|
||||||
</xsl:otherwise>
|
</xsl:otherwise>
|
||||||
</xsl:choose>
|
</xsl:choose>
|
||||||
<xsl:text> </xsl:text>
|
<xsl:text> </xsl:text>
|
||||||
|
|
||||||
<!-- LHS -->
|
<!-- LHS -->
|
||||||
<xsl:choose>
|
<xsl:choose>
|
||||||
<xsl:when test="$itemset != 'true' and $prev-lhs = lhs[text()]">
|
<xsl:when test="$prev-lhs = lhs[text()]">
|
||||||
<xsl:call-template name="lpad">
|
|
||||||
<xsl:with-param name="str" select="'|'"/>
|
|
||||||
<xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 2"/>
|
|
||||||
</xsl:call-template>
|
|
||||||
</xsl:when>
|
|
||||||
<xsl:when test="$itemset = 'true' and $prev-lhs = lhs[text()]">
|
|
||||||
<xsl:call-template name="lpad">
|
<xsl:call-template name="lpad">
|
||||||
<xsl:with-param name="str" select="'|'"/>
|
<xsl:with-param name="str" select="'|'"/>
|
||||||
<xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 2"/>
|
<xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 2"/>
|
||||||
|
|||||||
+548
-156
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;
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
%%
|
||||||
|
stmt:
|
||||||
|
expr
|
||||||
|
| if_stmt
|
||||||
|
;
|
||||||
|
|
||||||
|
if_stmt:
|
||||||
|
"if" expr "then" stmt
|
||||||
|
| "if" expr "then" stmt "else" stmt
|
||||||
|
;
|
||||||
|
|
||||||
|
expr:
|
||||||
|
"identifier"
|
||||||
+1
-1
@@ -57,7 +57,7 @@ MAINTAINERCLEANFILES = $(CROSS_OPTIONS_TEXI)
|
|||||||
|
|
||||||
# Fix Info's @code in @deftype
|
# Fix Info's @code in @deftype
|
||||||
# https://lists.gnu.org/archive/html/help-texinfo/2019-11/msg00004.html
|
# https://lists.gnu.org/archive/html/help-texinfo/2019-11/msg00004.html
|
||||||
all: $(srcdir)/$(%C%_bison).info.bak
|
all-local: $(srcdir)/$(%C%_bison).info.bak
|
||||||
$(srcdir)/$(%C%_bison).info.bak: $(srcdir)/$(%C%_bison).info
|
$(srcdir)/$(%C%_bison).info.bak: $(srcdir)/$(%C%_bison).info
|
||||||
$(AM_V_GEN) $(PERL) -pi.bak -0777 \
|
$(AM_V_GEN) $(PERL) -pi.bak -0777 \
|
||||||
-e 's{(^ --.*\n(?: {10}.*\n)*)}' \
|
-e 's{(^ --.*\n(?: {10}.*\n)*)}' \
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
%%
|
||||||
|
sequence:
|
||||||
|
%empty
|
||||||
|
| maybeword
|
||||||
|
| sequence "word"
|
||||||
|
;
|
||||||
|
maybeword:
|
||||||
|
%empty
|
||||||
|
| "word"
|
||||||
|
;
|
||||||
+41
-29
@@ -185,13 +185,13 @@ my $verbose = 1;
|
|||||||
|
|
||||||
=over 4
|
=over 4
|
||||||
|
|
||||||
=item C<verbose($level, $message)>
|
=item C<verbose ($level, $message)>
|
||||||
|
|
||||||
Report the C<$message> is C<$level> E<lt>= C<$verbose>.
|
Report the C<$message> is C<$level> E<lt>= C<$verbose>.
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
|
||||||
sub verbose($$)
|
sub verbose ($$)
|
||||||
{
|
{
|
||||||
my ($level, $message) = @_;
|
my ($level, $message) = @_;
|
||||||
print STDERR $message
|
print STDERR $message
|
||||||
@@ -201,13 +201,13 @@ sub verbose($$)
|
|||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
=item C<directives($bench, @directive)>
|
=item C<directives ($bench, @directive)>
|
||||||
|
|
||||||
Format the list of directives for Bison for bench named C<$bench>.
|
Format the list of directives for Bison for bench named C<$bench>.
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
|
||||||
sub directives($@)
|
sub directives ($@)
|
||||||
{
|
{
|
||||||
my ($bench, @directive) = @_;
|
my ($bench, @directive) = @_;
|
||||||
my $res = "/* Directives for bench '$bench'. */\n";
|
my $res = "/* Directives for bench '$bench'. */\n";
|
||||||
@@ -218,6 +218,27 @@ sub directives($@)
|
|||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
|
=item C<is_pure (@directive)>
|
||||||
|
|
||||||
|
Whether api.pure is set.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub is_pure (@)
|
||||||
|
{
|
||||||
|
my (@directive) = @_;
|
||||||
|
for my $dir (@directive)
|
||||||
|
{
|
||||||
|
if ($dir =~ /\A%define api.pure/)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
|
||||||
=item C<generate_grammar_triangular ($base, $max, @directive)>
|
=item C<generate_grammar_triangular ($base, $max, @directive)>
|
||||||
|
|
||||||
Create a large triangular grammar which looks like :
|
Create a large triangular grammar which looks like :
|
||||||
@@ -389,18 +410,14 @@ sub generate_grammar_calc ($$@)
|
|||||||
%define api.value.type union
|
%define api.value.type union
|
||||||
$directives
|
$directives
|
||||||
|
|
||||||
%{
|
%code provides {
|
||||||
static int power (int base, int exponent);
|
static int power (int base, int exponent);
|
||||||
/* yyerror receives the location if:
|
/* yyerror receives the location if:
|
||||||
- %location & %pure & %glr
|
- %location & %pure & %glr
|
||||||
- %location & %pure & %yacc & %parse-param. */
|
- %location & %pure & %yacc & %parse-param. */
|
||||||
static void yyerror (const char *s);
|
static void yyerror (const char *s);
|
||||||
#if YYPURE
|
static int yylex (@{[is_pure (@directive) ? "YYSTYPE *yylvalp" : "void"]});
|
||||||
static int yylex (YYSTYPE* yylvalp);
|
}
|
||||||
#else
|
|
||||||
static int yylex (void);
|
|
||||||
#endif
|
|
||||||
%}
|
|
||||||
|
|
||||||
/* Bison Declarations */
|
/* Bison Declarations */
|
||||||
%token
|
%token
|
||||||
@@ -467,12 +484,7 @@ yyerror (const char *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
#if YYPURE
|
yylex (@{[is_pure (@directive) ? "YYSTYPE *yylvalp" : "void"]})
|
||||||
# define yylval (*yylvalp)
|
|
||||||
yylex (YYSTYPE* yylvalp)
|
|
||||||
#else
|
|
||||||
yylex (void)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
@@ -498,7 +510,7 @@ yylex (void)
|
|||||||
case '5': case '6': case '7': case '8': case '9':
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
{
|
{
|
||||||
int nchars = 0;
|
int nchars = 0;
|
||||||
int n = sscanf (input - 1, "%d%n", &yylval.NUM, &nchars);
|
int n = sscanf (input - 1, "%d%n", &@{[is_pure (@directive) ? "yylvalp->" : "yylval."]}NUM, &nchars);
|
||||||
assert (n == 1);
|
assert (n == 1);
|
||||||
input += nchars - 1;
|
input += nchars - 1;
|
||||||
return NUM;
|
return NUM;
|
||||||
@@ -506,7 +518,7 @@ yylex (void)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
yyerror ("error: invalid character");
|
yyerror ("error: invalid character");
|
||||||
return yylex ();
|
return yylex (@{[is_pure (@directive) ? "yylvalp" : ""]});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
@@ -592,10 +604,10 @@ $directives
|
|||||||
// Prototype of the yylex function providing subsequent tokens.
|
// Prototype of the yylex function providing subsequent tokens.
|
||||||
static
|
static
|
||||||
#if USE_TOKEN_CTOR
|
#if USE_TOKEN_CTOR
|
||||||
yy::parser::symbol_type yylex();
|
yy::parser::symbol_type yylex ();
|
||||||
#else
|
#else
|
||||||
yy::parser::token_type yylex(yy::parser::semantic_type* yylvalp,
|
yy::parser::token_type yylex (yy::parser::semantic_type *yylvalp,
|
||||||
yy::parser::location_type* yyllocp);
|
yy::parser::location_type *yyllocp);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Conversion to string.
|
// Conversion to string.
|
||||||
@@ -618,8 +630,8 @@ EOF
|
|||||||
print $out <<'EOF';
|
print $out <<'EOF';
|
||||||
%token <std::string> TEXT
|
%token <std::string> TEXT
|
||||||
%token <int> NUMBER
|
%token <int> NUMBER
|
||||||
%printer { std::cerr << "Number: " << $$; } <int>
|
%printer { yyo << "Number: " << $$; } <int>
|
||||||
%printer { std::cerr << "Text: " << $$; } <std::string>
|
%printer { yyo << "Text: " << $$; } <std::string>
|
||||||
%type <std::string> text result
|
%type <std::string> text result
|
||||||
|
|
||||||
%%
|
%%
|
||||||
@@ -641,8 +653,8 @@ EOF
|
|||||||
%union {int ival; std::string* sval;}
|
%union {int ival; std::string* sval;}
|
||||||
%token <sval> TEXT
|
%token <sval> TEXT
|
||||||
%token <ival> NUMBER
|
%token <ival> NUMBER
|
||||||
%printer { std::cerr << "Number: " << $$; } <ival>
|
%printer { yyo << "Number: " << $$; } <ival>
|
||||||
%printer { std::cerr << "Text: " << *$$; } <sval>
|
%printer { yyo << "Text: " << *$$; } <sval>
|
||||||
%type <sval> text result
|
%type <sval> text result
|
||||||
|
|
||||||
%%
|
%%
|
||||||
@@ -664,10 +676,10 @@ EOF
|
|||||||
|
|
||||||
static
|
static
|
||||||
#if USE_TOKEN_CTOR
|
#if USE_TOKEN_CTOR
|
||||||
yy::parser::symbol_type yylex()
|
yy::parser::symbol_type yylex ()
|
||||||
#else
|
#else
|
||||||
yy::parser::token_type yylex(yy::parser::semantic_type* yylvalp,
|
yy::parser::token_type yylex (yy::parser::semantic_type *yylvalp,
|
||||||
yy::parser::location_type* yyllocp)
|
yy::parser::location_type *yyllocp)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
typedef yy::parser::location_type location_type;
|
typedef yy::parser::location_type location_type;
|
||||||
|
|||||||
+10
-1
@@ -53,7 +53,9 @@ push-parser model.
|
|||||||
This example demonstrates best practices when using Bison.
|
This example demonstrates best practices when using Bison.
|
||||||
- Its hand-written scanner tracks locations.
|
- Its hand-written scanner tracks locations.
|
||||||
- Its interface is pure.
|
- Its interface is pure.
|
||||||
- It uses the `error` token to get error recovery.
|
- It uses %params to pass user information to the parser and scanner.
|
||||||
|
- Its scanner uses the `error` token to signal lexical errors and enter
|
||||||
|
error recovery.
|
||||||
- Its interface is "incremental", well suited for interaction: it uses the
|
- Its interface is "incremental", well suited for interaction: it uses the
|
||||||
push-parser API to feed the parser with the incoming tokens.
|
push-parser API to feed the parser with the incoming tokens.
|
||||||
- It features an interactive command line with completion based on the
|
- It features an interactive command line with completion based on the
|
||||||
@@ -62,6 +64,13 @@ This example demonstrates best practices when using Bison.
|
|||||||
messages.
|
messages.
|
||||||
- It uses a custom syntax error with location, lookahead correction and
|
- It uses a custom syntax error with location, lookahead correction and
|
||||||
token internationalization.
|
token internationalization.
|
||||||
|
- Error messages quote the source with squiggles that underline the error:
|
||||||
|
```
|
||||||
|
> 123 456
|
||||||
|
1.5-7: syntax error: expected end of file or + or - or * or / or ^ before number
|
||||||
|
1 | 123 456
|
||||||
|
| ^~~
|
||||||
|
```
|
||||||
- It supports debug traces with semantic values.
|
- It supports debug traces with semantic values.
|
||||||
- It uses named references instead of the traditional $1, $2, etc.
|
- It uses named references instead of the traditional $1, $2, etc.
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
This example demonstrates best practices when using Bison.
|
This example demonstrates best practices when using Bison.
|
||||||
- Its hand-written scanner tracks locations.
|
- Its hand-written scanner tracks locations.
|
||||||
- Its interface is pure.
|
- Its interface is pure.
|
||||||
- It uses the `error` token to get error recovery.
|
- It uses %params to pass user information to the parser and scanner.
|
||||||
|
- Its scanner uses the `error` token to signal lexical errors and enter
|
||||||
|
error recovery.
|
||||||
- Its interface is "incremental", well suited for interaction: it uses the
|
- Its interface is "incremental", well suited for interaction: it uses the
|
||||||
push-parser API to feed the parser with the incoming tokens.
|
push-parser API to feed the parser with the incoming tokens.
|
||||||
- It features an interactive command line with completion based on the
|
- It features an interactive command line with completion based on the
|
||||||
@@ -11,6 +13,13 @@ This example demonstrates best practices when using Bison.
|
|||||||
messages.
|
messages.
|
||||||
- It uses a custom syntax error with location, lookahead correction and
|
- It uses a custom syntax error with location, lookahead correction and
|
||||||
token internationalization.
|
token internationalization.
|
||||||
|
- Error messages quote the source with squiggles that underline the error:
|
||||||
|
```
|
||||||
|
> 123 456
|
||||||
|
1.5-7: syntax error: expected end of file or + or - or * or / or ^ before number
|
||||||
|
1 | 123 456
|
||||||
|
| ^~~
|
||||||
|
```
|
||||||
- It supports debug traces with semantic values.
|
- It supports debug traces with semantic values.
|
||||||
- It uses named references instead of the traditional $1, $2, etc.
|
- It uses named references instead of the traditional $1, $2, etc.
|
||||||
|
|
||||||
|
|||||||
@@ -101,14 +101,28 @@ cat >input <<EOF
|
|||||||
EOF
|
EOF
|
||||||
run 0 '> *
|
run 0 '> *
|
||||||
> ''
|
> ''
|
||||||
err: 1.1: syntax error: expected end of file or - or ( or exit or number or function etc., before *'
|
err: 1.1: syntax error: expected end of file or - or ( or exit or number or function etc., before *
|
||||||
|
err: 1 | *
|
||||||
|
err: | ^'
|
||||||
|
|
||||||
|
# Underline long errors.
|
||||||
|
cat >input <<EOF
|
||||||
|
123 123456
|
||||||
|
EOF
|
||||||
|
run 0 '> 123 123456
|
||||||
|
> ''
|
||||||
|
err: 1.5-10: syntax error: expected end of file or + or - or * or / or ^ before number
|
||||||
|
err: 1 | 123 123456
|
||||||
|
err: | ^~~~~~'
|
||||||
|
|
||||||
cat >input <<EOF
|
cat >input <<EOF
|
||||||
1 + 2 * * 3
|
1 + 2 * * 3
|
||||||
EOF
|
EOF
|
||||||
run 0 '> 1 + 2 * * 3
|
run 0 '> 1 + 2 * * 3
|
||||||
> ''
|
> ''
|
||||||
err: 1.9: syntax error: expected - or ( or number or function or variable before *'
|
err: 1.9: syntax error: expected - or ( or number or function or variable before *
|
||||||
|
err: 1 | 1 + 2 * * 3
|
||||||
|
err: | ^'
|
||||||
|
|
||||||
cat >input <<EOF
|
cat >input <<EOF
|
||||||
1 / 0
|
1 / 0
|
||||||
@@ -132,8 +146,14 @@ run 0 '> ((1 ++ 2) ** 3)
|
|||||||
1332
|
1332
|
||||||
> ''
|
> ''
|
||||||
err: 1.6: syntax error: expected - or ( or number or function or variable before +
|
err: 1.6: syntax error: expected - or ( or number or function or variable before +
|
||||||
|
err: 1 | ((1 ++ 2) ** 3)
|
||||||
|
err: | ^
|
||||||
err: 2.5: syntax error: expected - or ( or number or function or variable before +
|
err: 2.5: syntax error: expected - or ( or number or function or variable before +
|
||||||
err: 2.16: syntax error: expected - or ( or number or function or variable before *'
|
err: 2 | (1 ++ 2) + (3 ** 4)
|
||||||
|
err: | ^
|
||||||
|
err: 2.16: syntax error: expected - or ( or number or function or variable before *
|
||||||
|
err: 2 | (1 ++ 2) + (3 ** 4)
|
||||||
|
err: | ^'
|
||||||
|
|
||||||
# The rule "( error )" should work even if there are no tokens between "(" and ")".
|
# The rule "( error )" should work even if there are no tokens between "(" and ")".
|
||||||
cat >input <<EOF
|
cat >input <<EOF
|
||||||
@@ -142,7 +162,9 @@ EOF
|
|||||||
run 0 '> ()
|
run 0 '> ()
|
||||||
666
|
666
|
||||||
> ''
|
> ''
|
||||||
err: 1.2: syntax error: expected - or ( or number or function or variable before )'
|
err: 1.2: syntax error: expected - or ( or number or function or variable before )
|
||||||
|
err: 1 | ()
|
||||||
|
err: | ^'
|
||||||
|
|
||||||
|
|
||||||
cat >input <<EOF
|
cat >input <<EOF
|
||||||
@@ -189,6 +211,8 @@ err: LAC: checking lookahead function: S5
|
|||||||
err: LAC: checking lookahead variable: S6
|
err: LAC: checking lookahead variable: S6
|
||||||
err: LAC: checking lookahead NEG: Err
|
err: LAC: checking lookahead NEG: Err
|
||||||
err: 1.2: syntax error: expected - or ( or number or function or variable before +
|
err: 1.2: syntax error: expected - or ( or number or function or variable before +
|
||||||
|
err: 1 | (+_)
|
||||||
|
err: | ^
|
||||||
err: LAC: initial context discarded due to error recovery
|
err: LAC: initial context discarded due to error recovery
|
||||||
err: Shifting token error (1.2: )
|
err: Shifting token error (1.2: )
|
||||||
err: Entering state 10
|
err: Entering state 10
|
||||||
@@ -227,29 +251,29 @@ err: Next token is token ) (1.4: )
|
|||||||
err: Shifting token ) (1.4: )
|
err: Shifting token ) (1.4: )
|
||||||
err: Entering state 20
|
err: Entering state 20
|
||||||
err: Stack now 0 2 10 20
|
err: Stack now 0 2 10 20
|
||||||
err: Reducing stack by rule 15 (line 151):
|
err: Reducing stack by rule XX (line XXX):
|
||||||
err: $1 = token ( (1.1: )
|
err: $1 = token ( (1.1: )
|
||||||
err: $2 = token error (1.2-3: )
|
err: $2 = token error (1.2-3: )
|
||||||
err: $3 = token ) (1.4: )
|
err: $3 = token ) (1.4: )
|
||||||
err: -> $$ = nterm exp (1.1-4: 666)
|
err: -> $$ = nterm exp (1.1-4: 666)
|
||||||
err: Entering state 7
|
err: Entering state 8
|
||||||
err: Stack now 0 7
|
err: Stack now 0 8
|
||||||
err: Return for a new token:
|
err: Return for a new token:
|
||||||
err: Reading a token
|
err: Reading a token
|
||||||
err: Now at end of input.
|
err: Now at end of input.
|
||||||
err: LAC: initial context established for end of file
|
err: LAC: initial context established for end of file
|
||||||
err: LAC: checking lookahead end of file: R2 G8 S19
|
err: LAC: checking lookahead end of file: R2 G7 S14
|
||||||
err: Reducing stack by rule 2 (line 126):
|
err: Reducing stack by rule XX (line XXX):
|
||||||
err: $1 = nterm exp (1.1-4: 666)
|
err: $1 = nterm exp (1.1-4: 666)
|
||||||
err: -> $$ = nterm input (1.1-4: )
|
err: -> $$ = nterm input (1.1-4: )
|
||||||
err: Entering state 8
|
err: Entering state 7
|
||||||
err: Stack now 0 8
|
err: Stack now 0 7
|
||||||
err: Now at end of input.
|
err: Now at end of input.
|
||||||
err: Shifting token end of file (1.5: )
|
err: Shifting token end of file (1.5: )
|
||||||
err: LAC: initial context discarded due to shift
|
err: LAC: initial context discarded due to shift
|
||||||
err: Entering state 19
|
err: Entering state 14
|
||||||
err: Stack now 0 8 19
|
err: Stack now 0 7 14
|
||||||
err: Stack now 0 8 19
|
err: Stack now 0 7 14
|
||||||
err: Cleanup: popping token end of file (1.5: )
|
err: Cleanup: popping token end of file (1.5: )
|
||||||
err: Cleanup: popping nterm input (1.1-4: )' -p
|
err: Cleanup: popping nterm input (1.1-4: )' -p
|
||||||
|
|
||||||
@@ -286,7 +310,9 @@ run 0 '> (1+
|
|||||||
( - atan cos exp ln number sin sqrt
|
( - atan cos exp ln number sin sqrt
|
||||||
> (1+
|
> (1+
|
||||||
> ''
|
> ''
|
||||||
err: 1.4: syntax error: expected - or ( or number or function or variable before end of file'
|
err: 1.4: syntax error: expected - or ( or number or function or variable before end of file
|
||||||
|
err: 1 | (1+
|
||||||
|
err: | ^'
|
||||||
|
|
||||||
# Check the completion of a word.
|
# Check the completion of a word.
|
||||||
sed -e 's/\\t/ /g' >input <<EOF
|
sed -e 's/\\t/ /g' >input <<EOF
|
||||||
@@ -294,7 +320,9 @@ sed -e 's/\\t/ /g' >input <<EOF
|
|||||||
EOF
|
EOF
|
||||||
run 0 '> (atan ( ''
|
run 0 '> (atan ( ''
|
||||||
> ''
|
> ''
|
||||||
err: 1.9: syntax error: expected - or ( or number or function or variable before end of file'
|
err: 1.9: syntax error: expected - or ( or number or function or variable before end of file
|
||||||
|
err: 1 | (atan ( ''
|
||||||
|
err: | ^'
|
||||||
|
|
||||||
# Check the completion at the very beginning.
|
# Check the completion at the very beginning.
|
||||||
sed -e 's/\\t/ /g' >input <<EOF
|
sed -e 's/\\t/ /g' >input <<EOF
|
||||||
@@ -313,8 +341,9 @@ sed -e 's/\\t/ /g' >input <<EOF
|
|||||||
EOF
|
EOF
|
||||||
run -n 0 '> 1++ ''
|
run -n 0 '> 1++ ''
|
||||||
> ''
|
> ''
|
||||||
err: 1.1: syntax error: expected - or ( or number or function or variable before +
|
|
||||||
err: 1.3: syntax error: expected - or ( or number or function or variable before +
|
err: 1.3: syntax error: expected - or ( or number or function or variable before +
|
||||||
|
err: 1 | 1++ ''
|
||||||
|
err: | ^
|
||||||
'
|
'
|
||||||
|
|
||||||
# And even when the error was recovered from.
|
# And even when the error was recovered from.
|
||||||
@@ -323,8 +352,10 @@ sed -e 's/\\t/ /g' >input <<EOF
|
|||||||
EOF
|
EOF
|
||||||
run -n 0 '> (1++2) + 3 + ''
|
run -n 0 '> (1++2) + 3 + ''
|
||||||
> ''
|
> ''
|
||||||
err: 1.1: syntax error: expected - or ( or number or function or variable before +
|
|
||||||
err: 1.1: syntax error: expected - or ( or number or function or variable before +
|
|
||||||
err: 1.4: syntax error: expected - or ( or number or function or variable before +
|
err: 1.4: syntax error: expected - or ( or number or function or variable before +
|
||||||
|
err: 1 | (1++2) + 3 + ''
|
||||||
|
err: | ^
|
||||||
err: 1.15: syntax error: expected - or ( or number or function or variable before end of file
|
err: 1.15: syntax error: expected - or ( or number or function or variable before end of file
|
||||||
|
err: 1 | (1++2) + 3 + ''
|
||||||
|
err: | ^
|
||||||
'
|
'
|
||||||
|
|||||||
@@ -1,5 +1,25 @@
|
|||||||
%require "3.6"
|
/* Parser and scanner for bistromathic. -*- C -*-
|
||||||
|
|
||||||
|
Copyright (C) 2019-2020 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of Bison, the GNU Compiler Compiler.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
%require "3.7"
|
||||||
|
|
||||||
|
// Emitted on top of the implementation file.
|
||||||
%code top {
|
%code top {
|
||||||
#include <ctype.h> // isdigit
|
#include <ctype.h> // isdigit
|
||||||
#include <locale.h> // LC_ALL
|
#include <locale.h> // LC_ALL
|
||||||
@@ -24,6 +44,7 @@
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emitted in the header file, before the definition of YYSTYPE.
|
||||||
%code requires {
|
%code requires {
|
||||||
// Function type.
|
// Function type.
|
||||||
typedef double (func_t) (double);
|
typedef double (func_t) (double);
|
||||||
@@ -44,19 +65,34 @@
|
|||||||
|
|
||||||
symrec *putsym (char const *name, int sym_type);
|
symrec *putsym (char const *name, int sym_type);
|
||||||
symrec *getsym (char const *name);
|
symrec *getsym (char const *name);
|
||||||
|
|
||||||
|
// Exchanging information with the parser.
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
// Whether to not emit error messages.
|
||||||
|
int silent;
|
||||||
|
// The current input line.
|
||||||
|
const char *line;
|
||||||
|
} user_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emitted in the header file, after the definition of YYSTYPE.
|
||||||
%code provides {
|
%code provides {
|
||||||
# ifndef __attribute__
|
# ifndef __attribute__
|
||||||
# ifndef __GNUC__
|
# ifndef __GNUC__
|
||||||
# define __attribute__(Spec) /* empty */
|
# define __attribute__(Spec) /* empty */
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
int yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc);
|
|
||||||
void yyerror (YYLTYPE *loc, char const *format, ...)
|
yytoken_kind_t
|
||||||
__attribute__ ((__format__ (__printf__, 2, 3)));
|
yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc,
|
||||||
|
const user_context *uctx);
|
||||||
|
void yyerror (YYLTYPE *loc, const user_context *uctx,
|
||||||
|
char const *format, ...)
|
||||||
|
__attribute__ ((__format__ (__printf__, 3, 4)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emitted in the implementation file.
|
||||||
%code {
|
%code {
|
||||||
#if defined ENABLE_NLS && ENABLE_NLS
|
#if defined ENABLE_NLS && ENABLE_NLS
|
||||||
# define _(Msgid) gettext (Msgid)
|
# define _(Msgid) gettext (Msgid)
|
||||||
@@ -68,6 +104,9 @@
|
|||||||
int done = 0;
|
int done = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Include the header in the implementation rather than duplicating it.
|
||||||
|
%define api.header.include {"parse.h"}
|
||||||
|
|
||||||
// Don't share global variables between the scanner and the parser.
|
// Don't share global variables between the scanner and the parser.
|
||||||
%define api.pure full
|
%define api.pure full
|
||||||
|
|
||||||
@@ -90,6 +129,9 @@
|
|||||||
// Generate the parser description file (calc.output).
|
// Generate the parser description file (calc.output).
|
||||||
%verbose
|
%verbose
|
||||||
|
|
||||||
|
// User information exchanged with the parser and scanner.
|
||||||
|
%param {const user_context *uctx}
|
||||||
|
|
||||||
// Generate YYSTYPE from the types assigned to symbols.
|
// Generate YYSTYPE from the types assigned to symbols.
|
||||||
%define api.value.type union
|
%define api.value.type union
|
||||||
%token
|
%token
|
||||||
@@ -145,7 +187,7 @@ exp:
|
|||||||
{
|
{
|
||||||
if ($r == 0)
|
if ($r == 0)
|
||||||
{
|
{
|
||||||
yyerror (&@$, "error: division by zero");
|
yyerror (&@$, uctx, "error: division by zero");
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -231,8 +273,9 @@ symbol_count (void)
|
|||||||
| Scanner. |
|
| Scanner. |
|
||||||
`----------*/
|
`----------*/
|
||||||
|
|
||||||
int
|
yytoken_kind_t
|
||||||
yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc)
|
yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc,
|
||||||
|
const user_context *uctx)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
@@ -302,7 +345,7 @@ yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc)
|
|||||||
|
|
||||||
// Stray characters.
|
// Stray characters.
|
||||||
default:
|
default:
|
||||||
yyerror (yylloc, "syntax error: invalid character: %c", c);
|
yyerror (yylloc, uctx, "syntax error: invalid character: %c", c);
|
||||||
return TOK_YYerror;
|
return TOK_YYerror;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -340,8 +383,11 @@ error_format_string (int argc)
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
yyreport_syntax_error (const yypcontext_t *ctx)
|
yyreport_syntax_error (const yypcontext_t *ctx, const user_context *uctx)
|
||||||
{
|
{
|
||||||
|
if (uctx->silent)
|
||||||
|
return 0;
|
||||||
|
|
||||||
enum { ARGS_MAX = 6 };
|
enum { ARGS_MAX = 6 };
|
||||||
yysymbol_kind_t arg[ARGS_MAX];
|
yysymbol_kind_t arg[ARGS_MAX];
|
||||||
int argsize = yypcontext_expected_tokens (ctx, arg, ARGS_MAX);
|
int argsize = yypcontext_expected_tokens (ctx, arg, ARGS_MAX);
|
||||||
@@ -352,11 +398,12 @@ yyreport_syntax_error (const yypcontext_t *ctx)
|
|||||||
argsize = ARGS_MAX;
|
argsize = ARGS_MAX;
|
||||||
const char *format = error_format_string (1 + argsize + too_many_expected_tokens);
|
const char *format = error_format_string (1 + argsize + too_many_expected_tokens);
|
||||||
|
|
||||||
|
const YYLTYPE *loc = yypcontext_location (ctx);
|
||||||
while (*format)
|
while (*format)
|
||||||
// %@: location.
|
// %@: location.
|
||||||
if (format[0] == '%' && format[1] == '@')
|
if (format[0] == '%' && format[1] == '@')
|
||||||
{
|
{
|
||||||
YY_LOCATION_PRINT (stderr, *yypcontext_location (ctx));
|
YY_LOCATION_PRINT (stderr, *loc);
|
||||||
format += 2;
|
format += 2;
|
||||||
}
|
}
|
||||||
// %u: unexpected token.
|
// %u: unexpected token.
|
||||||
@@ -381,13 +428,25 @@ yyreport_syntax_error (const yypcontext_t *ctx)
|
|||||||
++format;
|
++format;
|
||||||
}
|
}
|
||||||
fputc ('\n', stderr);
|
fputc ('\n', stderr);
|
||||||
|
|
||||||
|
// Quote the source line.
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%5d | %s\n", loc->first_line, uctx->line);
|
||||||
|
fprintf (stderr, "%5s | %*s", "", loc->first_column, "^");
|
||||||
|
for (int i = loc->last_column - loc->first_column - 1; 0 < i; --i)
|
||||||
|
putc ('~', stderr);
|
||||||
|
putc ('\n', stderr);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Called by yyparse on error.
|
// Called by yyparse on error.
|
||||||
void yyerror (YYLTYPE *loc, char const *format, ...)
|
void yyerror (YYLTYPE *loc, const user_context *uctx, char const *format, ...)
|
||||||
{
|
{
|
||||||
|
if (uctx->silent)
|
||||||
|
return;
|
||||||
|
|
||||||
YY_LOCATION_PRINT (stderr, *loc);
|
YY_LOCATION_PRINT (stderr, *loc);
|
||||||
fputs (": ", stderr);
|
fputs (": ", stderr);
|
||||||
va_list args;
|
va_list args;
|
||||||
@@ -423,11 +482,13 @@ xstrndup (const char *string, size_t n)
|
|||||||
static int
|
static int
|
||||||
process_line (YYLTYPE *lloc, const char *line)
|
process_line (YYLTYPE *lloc, const char *line)
|
||||||
{
|
{
|
||||||
|
user_context uctx = {0, line};
|
||||||
yypstate *ps = yypstate_new ();
|
yypstate *ps = yypstate_new ();
|
||||||
int status = 0;
|
int status = 0;
|
||||||
do {
|
do {
|
||||||
YYSTYPE lval;
|
YYSTYPE lval;
|
||||||
status = yypush_parse (ps, yylex (&line, &lval, lloc), &lval, lloc);
|
yytoken_kind_t token = yylex (&line, &lval, lloc, &uctx);
|
||||||
|
status = yypush_parse (ps, token, &lval, lloc, &uctx);
|
||||||
} while (status == YYPUSH_MORE);
|
} while (status == YYPUSH_MORE);
|
||||||
yypstate_delete (ps);
|
yypstate_delete (ps);
|
||||||
lloc->last_line++;
|
lloc->last_line++;
|
||||||
@@ -442,18 +503,19 @@ expected_tokens (const char *input,
|
|||||||
int *tokens, int ntokens)
|
int *tokens, int ntokens)
|
||||||
{
|
{
|
||||||
YYDPRINTF ((stderr, "expected_tokens (\"%s\")", input));
|
YYDPRINTF ((stderr, "expected_tokens (\"%s\")", input));
|
||||||
|
user_context uctx = {1, input};
|
||||||
|
|
||||||
// Parse the current state of the line.
|
// Parse the current state of the line.
|
||||||
yypstate *ps = yypstate_new ();
|
yypstate *ps = yypstate_new ();
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
YYLTYPE lloc = { 1, 1, 1, 1 };
|
||||||
do {
|
do {
|
||||||
YYLTYPE lloc = { 1, 1, 1, 1 };
|
|
||||||
YYSTYPE lval;
|
YYSTYPE lval;
|
||||||
int token = yylex (&input, &lval, &lloc);
|
yytoken_kind_t token = yylex (&input, &lval, &lloc, &uctx);
|
||||||
// Don't let the parse know when we reach the end of input.
|
// Don't let the parse know when we reach the end of input.
|
||||||
if (!token)
|
if (token == TOK_YYEOF)
|
||||||
break;
|
break;
|
||||||
status = yypush_parse (ps, token, &lval, &lloc);
|
status = yypush_parse (ps, token, &lval, &lloc, &uctx);
|
||||||
} while (status == YYPUSH_MORE);
|
} while (status == YYPUSH_MORE);
|
||||||
|
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|||||||
@@ -31,6 +31,13 @@ endif FLEX_WORKS
|
|||||||
|
|
||||||
%D%/parse.c: $(dependencies)
|
%D%/parse.c: $(dependencies)
|
||||||
|
|
||||||
|
# Tell Make scan.o depends on parse.h, except that Make sees only
|
||||||
|
# parse.c, not parse.h. We can't use BUILT_SOURCES to this end, since
|
||||||
|
# we use the built bison.
|
||||||
|
%D%/lexcalc$(DASH)scan.o: %D%/parse.c
|
||||||
|
# Likewise, but for Automake before 1.16.
|
||||||
|
%D%/examples_c_lexcalc_lexcalc$(DASH)scan.o: %D%/parse.c
|
||||||
|
|
||||||
EXTRA_DIST += %D%/lexcalc.test
|
EXTRA_DIST += %D%/lexcalc.test
|
||||||
dist_lexcalc_DATA = %D%/parse.y %D%/scan.l %D%/Makefile %D%/README.md
|
dist_lexcalc_DATA = %D%/parse.y %D%/scan.l %D%/Makefile %D%/README.md
|
||||||
CLEANFILES += %D%/parse.[ch] %D%/scan.c %D%/parse.output
|
CLEANFILES += %D%/parse.[ch] %D%/scan.c %D%/parse.output
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
|
/* Parser for lexcalc. -*- C -*-
|
||||||
|
|
||||||
|
Copyright (C) 2018-2020 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of Bison, the GNU Compiler Compiler.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
// Prologue (directives).
|
// Prologue (directives).
|
||||||
%expect 0
|
%expect 0
|
||||||
|
|
||||||
@@ -19,6 +38,9 @@
|
|||||||
#include <stdlib.h> // getenv.
|
#include <stdlib.h> // getenv.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Include the header in the implementation rather than duplicating it.
|
||||||
|
%define api.header.include {"parse.h"}
|
||||||
|
|
||||||
// Don't share global variables between the scanner and the parser.
|
// Don't share global variables between the scanner and the parser.
|
||||||
%define api.pure full
|
%define api.pure full
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,23 @@
|
|||||||
/* Prologue (directives). -*- C -*- */
|
/* Scanner for lexcalc. -*- C -*-
|
||||||
|
|
||||||
|
Copyright (C) 2018-2020 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of Bison, the GNU Compiler Compiler.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
/* Prologue (directives). */
|
||||||
|
|
||||||
/* Disable Flex features we don't need, to avoid warnings. */
|
/* Disable Flex features we don't need, to avoid warnings. */
|
||||||
%option nodefault noinput nounput noyywrap
|
%option nodefault noinput nounput noyywrap
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
|
/* Parser and scanner for pushcalc. -*- C -*-
|
||||||
|
|
||||||
|
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of Bison, the GNU Compiler Compiler.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
%code top {
|
%code top {
|
||||||
#include <ctype.h> /* isdigit. */
|
#include <ctype.h> /* isdigit. */
|
||||||
#include <stdio.h> /* printf. */
|
#include <stdio.h> /* printf. */
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
|
/* Parser for reccalc. -*- C -*-
|
||||||
|
|
||||||
|
Copyright (C) 2019-2020 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of Bison, the GNU Compiler Compiler.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
// Prologue (directives).
|
// Prologue (directives).
|
||||||
%expect 0
|
%expect 0
|
||||||
|
|
||||||
@@ -46,14 +65,29 @@
|
|||||||
result parse (void);
|
result parse (void);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Include the header in the implementation rather than duplicating it.
|
||||||
|
%define api.header.include {"parse.h"}
|
||||||
|
|
||||||
|
// Don't share global variables between the scanner and the parser.
|
||||||
%define api.pure full
|
%define api.pure full
|
||||||
|
|
||||||
|
// To avoid name clashes (e.g., with C's EOF) prefix token definitions
|
||||||
|
// with TOK_ (e.g., TOK_EOF).
|
||||||
%define api.token.prefix {TOK_}
|
%define api.token.prefix {TOK_}
|
||||||
|
|
||||||
|
// Generate YYSTYPE from the types assigned to symbols.
|
||||||
%define api.value.type union
|
%define api.value.type union
|
||||||
%define parse.error verbose
|
|
||||||
|
// Error messages with "unexpected XXX, expected XXX...".
|
||||||
|
%define parse.error detailed
|
||||||
|
|
||||||
|
// Enable run-time traces (yydebug).
|
||||||
%define parse.trace
|
%define parse.trace
|
||||||
|
|
||||||
|
// Generate the parser description file (parse.output).
|
||||||
%verbose
|
%verbose
|
||||||
|
|
||||||
// Scanner and error count are exchanged between main, yyparse and yylex.
|
// Scanner and error count are exchanged between main, yyparse and yylex.
|
||||||
%param {yyscan_t scanner}{result *res}
|
%param {yyscan_t scanner}{result *res}
|
||||||
|
|
||||||
%token
|
%token
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
|
/* Scanner for reccalc. -*- C -*-
|
||||||
|
|
||||||
|
Copyright (C) 2019-2020 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of Bison, the GNU Compiler Compiler.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
/* Prologue (directives). -*- C -*- */
|
/* Prologue (directives). -*- C -*- */
|
||||||
|
|
||||||
/* Disable Flex features we don't need, to avoid warnings. */
|
/* Disable Flex features we don't need, to avoid warnings. */
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
|
/* Parser and scanner for calc in D. -*- D -*-
|
||||||
|
|
||||||
|
Copyright (C) 2018-2020 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of Bison, the GNU Compiler Compiler.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
%language "D"
|
%language "D"
|
||||||
|
|
||||||
%define api.parser.class {Calc}
|
%define api.parser.class {Calc}
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ EXTRA_DIST += %D%/calc.test
|
|||||||
|
|
||||||
%D%/calc.d: %D%/calc.y $(dependencies)
|
%D%/calc.d: %D%/calc.y $(dependencies)
|
||||||
$(AM_V_GEN)$(MKDIR_P) %D%
|
$(AM_V_GEN)$(MKDIR_P) %D%
|
||||||
$(AM_V_at)$(BISON) $(srcdir)/%D%/calc.y -o $@
|
$(AM_V_at)$(BISON) -o $@ $(srcdir)/%D%/calc.y
|
||||||
|
|
||||||
%D%/calc: %D%/calc.d
|
%D%/calc: %D%/calc.d
|
||||||
$(AM_V_GEN) $(DC) $(DCFLAGS) -of$@ %D%/calc.d
|
$(AM_V_GEN) $(DC) $(DCFLAGS) -of$@ %D%/calc.d
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
|
/* Parser and scanner for calc in Java. -*- Java -*-
|
||||||
|
|
||||||
|
Copyright (C) 2018-2020 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of Bison, the GNU Compiler Compiler.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
%language "Java"
|
%language "Java"
|
||||||
|
|
||||||
%define api.parser.class {Calc}
|
%define api.parser.class {Calc}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ EXTRA_DIST += %D%/Calc.test
|
|||||||
|
|
||||||
%D%/Calc.java: %D%/Calc.y $(dependencies)
|
%D%/Calc.java: %D%/Calc.y $(dependencies)
|
||||||
$(AM_V_GEN)$(MKDIR_P) %D%
|
$(AM_V_GEN)$(MKDIR_P) %D%
|
||||||
$(AM_V_at)$(BISON) $(srcdir)/%D%/Calc.y -o $@
|
$(AM_V_at)$(BISON) -o $@ $(srcdir)/%D%/Calc.y
|
||||||
|
|
||||||
%D%/Calc.class: %D%/Calc.java
|
%D%/Calc.class: %D%/Calc.java
|
||||||
$(AM_V_GEN) $(SHELL) $(top_builddir)/javacomp.sh %D%/Calc.java
|
$(AM_V_GEN) $(SHELL) $(top_builddir)/javacomp.sh %D%/Calc.java
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
|
/* Simple parser and scanner in Java. -*- Java -*-
|
||||||
|
|
||||||
|
Copyright (C) 2018-2020 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of Bison, the GNU Compiler Compiler.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
%language "Java"
|
%language "Java"
|
||||||
|
|
||||||
%define api.parser.class {Calc}
|
%define api.parser.class {Calc}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ EXTRA_DIST += %D%/Calc.test
|
|||||||
|
|
||||||
%D%/Calc.java: %D%/Calc.y $(dependencies)
|
%D%/Calc.java: %D%/Calc.y $(dependencies)
|
||||||
$(AM_V_GEN)$(MKDIR_P) %D%
|
$(AM_V_GEN)$(MKDIR_P) %D%
|
||||||
$(AM_V_at)$(BISON) $(srcdir)/%D%/Calc.y -o $@
|
$(AM_V_at)$(BISON) -o $@ $(srcdir)/%D%/Calc.y
|
||||||
|
|
||||||
%D%/Calc.class: %D%/Calc.java
|
%D%/Calc.class: %D%/Calc.java
|
||||||
$(AM_V_GEN) $(SHELL) $(top_builddir)/javacomp.sh %D%/Calc.java
|
$(AM_V_GEN) $(SHELL) $(top_builddir)/javacomp.sh %D%/Calc.java
|
||||||
|
|||||||
+1
-1
Submodule gnulib updated: 845d69187a...839ed059f4
+5
-2
@@ -20,6 +20,7 @@
|
|||||||
/assure.h
|
/assure.h
|
||||||
/attribute.h
|
/attribute.h
|
||||||
/basename-lgpl.c
|
/basename-lgpl.c
|
||||||
|
/basename-lgpl.h
|
||||||
/basename.c
|
/basename.c
|
||||||
/binary-io.c
|
/binary-io.c
|
||||||
/binary-io.h
|
/binary-io.h
|
||||||
@@ -191,8 +192,6 @@
|
|||||||
/localcharset.h
|
/localcharset.h
|
||||||
/locale.h
|
/locale.h
|
||||||
/locale.in.h
|
/locale.in.h
|
||||||
/localtime-buffer.c
|
|
||||||
/localtime-buffer.h
|
|
||||||
/lstat.c
|
/lstat.c
|
||||||
/malloc.c
|
/malloc.c
|
||||||
/malloca.c
|
/malloca.c
|
||||||
@@ -312,6 +311,7 @@
|
|||||||
/stdlib.h
|
/stdlib.h
|
||||||
/stdlib.in.h
|
/stdlib.in.h
|
||||||
/stpcpy.c
|
/stpcpy.c
|
||||||
|
/stpncpy.c
|
||||||
/strchrnul.c
|
/strchrnul.c
|
||||||
/strchrnul.valgrind
|
/strchrnul.valgrind
|
||||||
/strdup.c
|
/strdup.c
|
||||||
@@ -336,8 +336,11 @@
|
|||||||
/sys_types.in.h
|
/sys_types.in.h
|
||||||
/sys_wait.in.h
|
/sys_wait.in.h
|
||||||
/sysexits.in.h
|
/sysexits.in.h
|
||||||
|
/termios.h
|
||||||
|
/termios.in.h
|
||||||
/textstyle.h
|
/textstyle.h
|
||||||
/textstyle.in.h
|
/textstyle.in.h
|
||||||
|
/thread-optim.h
|
||||||
/time.h
|
/time.h
|
||||||
/time.in.h
|
/time.in.h
|
||||||
/timespec.c
|
/timespec.c
|
||||||
|
|||||||
+5
-2
@@ -13,7 +13,6 @@
|
|||||||
/codeset.m4
|
/codeset.m4
|
||||||
/config-h.m4
|
/config-h.m4
|
||||||
/configmake.m4
|
/configmake.m4
|
||||||
/dirname.m4
|
|
||||||
/double-slash-root.m4
|
/double-slash-root.m4
|
||||||
/dup2.m4
|
/dup2.m4
|
||||||
/eealloc.m4
|
/eealloc.m4
|
||||||
@@ -98,7 +97,6 @@
|
|||||||
/locale-ja.m4
|
/locale-ja.m4
|
||||||
/locale-zh.m4
|
/locale-zh.m4
|
||||||
/locale_h.m4
|
/locale_h.m4
|
||||||
/localtime-buffer.m4
|
|
||||||
/lock.m4
|
/lock.m4
|
||||||
/longlong.m4
|
/longlong.m4
|
||||||
/lstat.m4
|
/lstat.m4
|
||||||
@@ -118,6 +116,7 @@
|
|||||||
/msvc-inval.m4
|
/msvc-inval.m4
|
||||||
/msvc-nothrow.m4
|
/msvc-nothrow.m4
|
||||||
/multiarch.m4
|
/multiarch.m4
|
||||||
|
/musl.m4
|
||||||
/nls.m4
|
/nls.m4
|
||||||
/nocrash.m4
|
/nocrash.m4
|
||||||
/non-recursive-gnulib-prefix-hack.m4
|
/non-recursive-gnulib-prefix-hack.m4
|
||||||
@@ -129,6 +128,7 @@
|
|||||||
/open.m4
|
/open.m4
|
||||||
/pathmax.m4
|
/pathmax.m4
|
||||||
/perror.m4
|
/perror.m4
|
||||||
|
/pid_t.m4
|
||||||
/pipe2.m4
|
/pipe2.m4
|
||||||
/po.m4
|
/po.m4
|
||||||
/posix_spawn.m4
|
/posix_spawn.m4
|
||||||
@@ -176,6 +176,7 @@
|
|||||||
/stdio_h.m4
|
/stdio_h.m4
|
||||||
/stdlib_h.m4
|
/stdlib_h.m4
|
||||||
/stpcpy.m4
|
/stpcpy.m4
|
||||||
|
/stpncpy.m4
|
||||||
/strchrnul.m4
|
/strchrnul.m4
|
||||||
/strdup.m4
|
/strdup.m4
|
||||||
/strerror.m4
|
/strerror.m4
|
||||||
@@ -184,6 +185,7 @@
|
|||||||
/strndup.m4
|
/strndup.m4
|
||||||
/strnlen.m4
|
/strnlen.m4
|
||||||
/strverscmp.m4
|
/strverscmp.m4
|
||||||
|
/sys_ioctl_h.m4
|
||||||
/sys_resource_h.m4
|
/sys_resource_h.m4
|
||||||
/sys_socket_h.m4
|
/sys_socket_h.m4
|
||||||
/sys_stat_h.m4
|
/sys_stat_h.m4
|
||||||
@@ -191,6 +193,7 @@
|
|||||||
/sys_times_h.m4
|
/sys_times_h.m4
|
||||||
/sys_types_h.m4
|
/sys_types_h.m4
|
||||||
/sys_wait_h.m4
|
/sys_wait_h.m4
|
||||||
|
/termios_h.m4
|
||||||
/threadlib.m4
|
/threadlib.m4
|
||||||
/time_h.m4
|
/time_h.m4
|
||||||
/timespec.m4
|
/timespec.m4
|
||||||
|
|||||||
@@ -169,10 +169,10 @@ AnnotationList__compute_conflicted_tokens (bitset shift_tokens,
|
|||||||
bitset_copy (tokens, shift_tokens);
|
bitset_copy (tokens, shift_tokens);
|
||||||
for (int i = 0; i < reds->num; ++i)
|
for (int i = 0; i < reds->num; ++i)
|
||||||
{
|
{
|
||||||
bitset_and (conflicted_tokens_rule, tokens, reds->lookahead_tokens[i]);
|
bitset_and (conflicted_tokens_rule, tokens, reds->lookaheads[i]);
|
||||||
bitset_or (conflicted_tokens,
|
bitset_or (conflicted_tokens,
|
||||||
conflicted_tokens, conflicted_tokens_rule);
|
conflicted_tokens, conflicted_tokens_rule);
|
||||||
bitset_or (tokens, tokens, reds->lookahead_tokens[i]);
|
bitset_or (tokens, tokens, reds->lookaheads[i]);
|
||||||
/* Check that rules are sorted on rule number or the next step in
|
/* Check that rules are sorted on rule number or the next step in
|
||||||
AnnotationList__compute_from_inadequacies will misbehave. */
|
AnnotationList__compute_from_inadequacies will misbehave. */
|
||||||
aver (i == 0 || reds->rules[i-1] < reds->rules[i]);
|
aver (i == 0 || reds->rules[i-1] < reds->rules[i]);
|
||||||
@@ -401,7 +401,7 @@ AnnotationList__compute_from_inadequacies (
|
|||||||
struct obstack *annotations_obstackp,
|
struct obstack *annotations_obstackp,
|
||||||
InadequacyListNodeCount *inadequacy_list_node_count)
|
InadequacyListNodeCount *inadequacy_list_node_count)
|
||||||
{
|
{
|
||||||
/* Return an empty list if s->lookahead_tokens = NULL. */
|
/* Return an empty list if s->lookaheads = NULL. */
|
||||||
if (s->consistent)
|
if (s->consistent)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -422,7 +422,7 @@ AnnotationList__compute_from_inadequacies (
|
|||||||
/* Allocate the annotation node. */
|
/* Allocate the annotation node. */
|
||||||
{
|
{
|
||||||
for (int rule_i = 0; rule_i < s->reductions->num; ++rule_i)
|
for (int rule_i = 0; rule_i < s->reductions->num; ++rule_i)
|
||||||
if (bitset_test (s->reductions->lookahead_tokens[rule_i],
|
if (bitset_test (s->reductions->lookaheads[rule_i],
|
||||||
conflicted_token))
|
conflicted_token))
|
||||||
++contribution_count;
|
++contribution_count;
|
||||||
if (bitset_test (shift_tokens, conflicted_token))
|
if (bitset_test (shift_tokens, conflicted_token))
|
||||||
@@ -445,7 +445,7 @@ AnnotationList__compute_from_inadequacies (
|
|||||||
for (int rule_i = 0; rule_i < s->reductions->num; ++rule_i)
|
for (int rule_i = 0; rule_i < s->reductions->num; ++rule_i)
|
||||||
{
|
{
|
||||||
rule *the_rule = s->reductions->rules[rule_i];
|
rule *the_rule = s->reductions->rules[rule_i];
|
||||||
if (bitset_test (s->reductions->lookahead_tokens[rule_i],
|
if (bitset_test (s->reductions->lookaheads[rule_i],
|
||||||
conflicted_token))
|
conflicted_token))
|
||||||
{
|
{
|
||||||
bitset_set (actions, rule_i);
|
bitset_set (actions, rule_i);
|
||||||
|
|||||||
+35
-3
@@ -35,6 +35,13 @@
|
|||||||
#include "getargs.h"
|
#include "getargs.h"
|
||||||
#include "quote.h"
|
#include "quote.h"
|
||||||
|
|
||||||
|
// The URL of the manual page about diagnostics. Use the per-node
|
||||||
|
// manual, to avoid downloading repeatedly the whole manual over the
|
||||||
|
// Internet.
|
||||||
|
static const char *diagnostics_url
|
||||||
|
= "https://www.gnu.org/software/bison/manual/html_node/Diagnostics.html";
|
||||||
|
|
||||||
|
|
||||||
err_status complaint_status = status_none;
|
err_status complaint_status = status_none;
|
||||||
|
|
||||||
bool warnings_are_errors = false;
|
bool warnings_are_errors = false;
|
||||||
@@ -96,6 +103,20 @@ end_use_class (const char *s, FILE *out)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
begin_hyperlink (FILE *out, const char *ref)
|
||||||
|
{
|
||||||
|
if (out == stderr)
|
||||||
|
styled_ostream_set_hyperlink (errstream, ref, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
end_hyperlink (FILE *out)
|
||||||
|
{
|
||||||
|
if (out == stderr)
|
||||||
|
styled_ostream_set_hyperlink (errstream, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
flush (FILE *out)
|
flush (FILE *out)
|
||||||
{
|
{
|
||||||
@@ -427,9 +448,20 @@ warnings_print_categories (warnings warn_flags, FILE *out)
|
|||||||
const char* style = severity_style (s);
|
const char* style = severity_style (s);
|
||||||
fputs (" [", out);
|
fputs (" [", out);
|
||||||
begin_use_class (style, out);
|
begin_use_class (style, out);
|
||||||
fprintf (out, "-W%s%s",
|
// E.g., "counterexamples".
|
||||||
s == severity_error ? "error=" : "",
|
const char *warning = argmatch_warning_argument (&w);
|
||||||
argmatch_warning_argument (&w));
|
char ref[200];
|
||||||
|
snprintf (ref, sizeof ref,
|
||||||
|
"%s#W%s", diagnostics_url, warning);
|
||||||
|
begin_hyperlink (out, ref);
|
||||||
|
ostream_printf (errstream,
|
||||||
|
"-W%s%s",
|
||||||
|
s == severity_error ? "error=" : "",
|
||||||
|
warning);
|
||||||
|
end_hyperlink (out);
|
||||||
|
// Because we mix stdio with ostream I/O, we need to flush
|
||||||
|
// here for sake of color == debug.
|
||||||
|
flush (out);
|
||||||
end_use_class (style, out);
|
end_use_class (style, out);
|
||||||
fputc (']', out);
|
fputc (']', out);
|
||||||
/* Display only the first match, the second is "-Wall". */
|
/* Display only the first match, the second is "-Wall". */
|
||||||
|
|||||||
+29
-25
@@ -250,9 +250,9 @@ flush_shift (state *s, int token)
|
|||||||
`--------------------------------------------------------------------*/
|
`--------------------------------------------------------------------*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
flush_reduce (bitset lookahead_tokens, int token)
|
flush_reduce (bitset lookaheads, int token)
|
||||||
{
|
{
|
||||||
bitset_reset (lookahead_tokens, token);
|
bitset_reset (lookaheads, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -275,10 +275,10 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
|
|||||||
/* Find the rule to reduce by to get precedence of reduction. */
|
/* Find the rule to reduce by to get precedence of reduction. */
|
||||||
rule *redrule = reds->rules[ruleno];
|
rule *redrule = reds->rules[ruleno];
|
||||||
int redprec = redrule->prec->prec;
|
int redprec = redrule->prec->prec;
|
||||||
bitset lookahead_tokens = reds->lookahead_tokens[ruleno];
|
bitset lookaheads = reds->lookaheads[ruleno];
|
||||||
|
|
||||||
for (symbol_number i = 0; i < ntokens; ++i)
|
for (symbol_number i = 0; i < ntokens; ++i)
|
||||||
if (bitset_test (lookahead_tokens, i)
|
if (bitset_test (lookaheads, i)
|
||||||
&& bitset_test (lookahead_set, i)
|
&& bitset_test (lookahead_set, i)
|
||||||
&& symbols[i]->content->prec)
|
&& symbols[i]->content->prec)
|
||||||
{
|
{
|
||||||
@@ -295,7 +295,7 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
|
|||||||
{
|
{
|
||||||
register_precedence (i, redrule->prec->number);
|
register_precedence (i, redrule->prec->number);
|
||||||
log_resolution (redrule, i, shift_resolution);
|
log_resolution (redrule, i, shift_resolution);
|
||||||
flush_reduce (lookahead_tokens, i);
|
flush_reduce (lookaheads, i);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* Matching precedence levels.
|
/* Matching precedence levels.
|
||||||
@@ -316,7 +316,7 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
|
|||||||
case right_assoc:
|
case right_assoc:
|
||||||
register_assoc (i, redrule->prec->number);
|
register_assoc (i, redrule->prec->number);
|
||||||
log_resolution (redrule, i, right_resolution);
|
log_resolution (redrule, i, right_resolution);
|
||||||
flush_reduce (lookahead_tokens, i);
|
flush_reduce (lookaheads, i);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case left_assoc:
|
case left_assoc:
|
||||||
@@ -329,7 +329,7 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
|
|||||||
register_assoc (i, redrule->prec->number);
|
register_assoc (i, redrule->prec->number);
|
||||||
log_resolution (redrule, i, nonassoc_resolution);
|
log_resolution (redrule, i, nonassoc_resolution);
|
||||||
flush_shift (s, i);
|
flush_shift (s, i);
|
||||||
flush_reduce (lookahead_tokens, i);
|
flush_reduce (lookaheads, i);
|
||||||
/* Record an explicit error for this token. */
|
/* Record an explicit error for this token. */
|
||||||
errors[(*nerrs)++] = symbols[i];
|
errors[(*nerrs)++] = symbols[i];
|
||||||
break;
|
break;
|
||||||
@@ -369,7 +369,7 @@ set_conflicts (state *s, symbol **errors)
|
|||||||
for (int i = 0; i < reds->num; ++i)
|
for (int i = 0; i < reds->num; ++i)
|
||||||
if (reds->rules[i]->prec
|
if (reds->rules[i]->prec
|
||||||
&& reds->rules[i]->prec->prec
|
&& reds->rules[i]->prec->prec
|
||||||
&& !bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set))
|
&& !bitset_disjoint_p (reds->lookaheads[i], lookahead_set))
|
||||||
resolve_sr_conflict (s, i, errors, &nerrs);
|
resolve_sr_conflict (s, i, errors, &nerrs);
|
||||||
|
|
||||||
if (nerrs)
|
if (nerrs)
|
||||||
@@ -385,13 +385,13 @@ set_conflicts (state *s, symbol **errors)
|
|||||||
/* Loop over all rules which require lookahead in this state. Check
|
/* Loop over all rules which require lookahead in this state. Check
|
||||||
for conflicts not resolved above.
|
for conflicts not resolved above.
|
||||||
|
|
||||||
reds->lookahead_tokens can be NULL if the LR type is LR(0). */
|
reds->lookaheads can be NULL if the LR type is LR(0). */
|
||||||
if (reds->lookahead_tokens)
|
if (reds->lookaheads)
|
||||||
for (int i = 0; i < reds->num; ++i)
|
for (int i = 0; i < reds->num; ++i)
|
||||||
{
|
{
|
||||||
if (!bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set))
|
if (!bitset_disjoint_p (reds->lookaheads[i], lookahead_set))
|
||||||
conflicts[s->number] = true;
|
conflicts[s->number] = true;
|
||||||
bitset_or (lookahead_set, lookahead_set, reds->lookahead_tokens[i]);
|
bitset_or (lookahead_set, lookahead_set, reds->lookaheads[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -460,7 +460,7 @@ count_state_sr_conflicts (const state *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < reds->num; ++i)
|
for (int i = 0; i < reds->num; ++i)
|
||||||
bitset_or (lookahead_set, lookahead_set, reds->lookahead_tokens[i]);
|
bitset_or (lookahead_set, lookahead_set, reds->lookaheads[i]);
|
||||||
|
|
||||||
bitset_and (lookahead_set, lookahead_set, shift_set);
|
bitset_and (lookahead_set, lookahead_set, shift_set);
|
||||||
|
|
||||||
@@ -499,7 +499,7 @@ count_state_rr_conflicts (const state *s)
|
|||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (int j = 0; j < reds->num; ++j)
|
for (int j = 0; j < reds->num; ++j)
|
||||||
count += bitset_test (reds->lookahead_tokens[j], i);
|
count += bitset_test (reds->lookaheads[j], i);
|
||||||
if (2 <= count)
|
if (2 <= count)
|
||||||
res += count-1;
|
res += count-1;
|
||||||
}
|
}
|
||||||
@@ -534,7 +534,7 @@ count_rule_state_sr_conflicts (rule *r, state *s)
|
|||||||
for (int i = 0; i < reds->num; ++i)
|
for (int i = 0; i < reds->num; ++i)
|
||||||
if (reds->rules[i] == r)
|
if (reds->rules[i] == r)
|
||||||
{
|
{
|
||||||
bitset lookaheads = reds->lookahead_tokens[i];
|
bitset lookaheads = reds->lookaheads[i];
|
||||||
int j;
|
int j;
|
||||||
FOR_EACH_SHIFT (trans, j)
|
FOR_EACH_SHIFT (trans, j)
|
||||||
res += bitset_test (lookaheads, TRANSITION_SYMBOL (trans, j));
|
res += bitset_test (lookaheads, TRANSITION_SYMBOL (trans, j));
|
||||||
@@ -576,8 +576,8 @@ count_rule_state_rr_conflicts (rule *r, state *s)
|
|||||||
if (reds->rules[j] != r)
|
if (reds->rules[j] != r)
|
||||||
{
|
{
|
||||||
bitset_and (lookaheads,
|
bitset_and (lookaheads,
|
||||||
reds->lookahead_tokens[i],
|
reds->lookaheads[i],
|
||||||
reds->lookahead_tokens[j]);
|
reds->lookaheads[j]);
|
||||||
res += bitset_count (lookaheads);
|
res += bitset_count (lookaheads);
|
||||||
}
|
}
|
||||||
bitset_free (lookaheads);
|
bitset_free (lookaheads);
|
||||||
@@ -686,7 +686,8 @@ conflicts_print (void)
|
|||||||
expected_rr_conflicts = -1;
|
expected_rr_conflicts = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_unexpected_conflicts = false;
|
// The warning flags used to emit a diagnostic, if we did.
|
||||||
|
warnings unexpected_conflicts_warning = Wnone;
|
||||||
/* The following two blocks scream for factoring, but i18n support
|
/* The following two blocks scream for factoring, but i18n support
|
||||||
would make it ugly. */
|
would make it ugly. */
|
||||||
{
|
{
|
||||||
@@ -703,7 +704,8 @@ conflicts_print (void)
|
|||||||
complain (NULL, complaint,
|
complain (NULL, complaint,
|
||||||
_("shift/reduce conflicts: %d found, %d expected"),
|
_("shift/reduce conflicts: %d found, %d expected"),
|
||||||
total, expected);
|
total, expected);
|
||||||
has_unexpected_conflicts = true;
|
if (total)
|
||||||
|
unexpected_conflicts_warning = complaint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (total)
|
else if (total)
|
||||||
@@ -713,7 +715,7 @@ conflicts_print (void)
|
|||||||
"%d shift/reduce conflicts",
|
"%d shift/reduce conflicts",
|
||||||
total),
|
total),
|
||||||
total);
|
total);
|
||||||
has_unexpected_conflicts = true;
|
unexpected_conflicts_warning = Wconflicts_sr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -731,7 +733,8 @@ conflicts_print (void)
|
|||||||
complain (NULL, complaint,
|
complain (NULL, complaint,
|
||||||
_("reduce/reduce conflicts: %d found, %d expected"),
|
_("reduce/reduce conflicts: %d found, %d expected"),
|
||||||
total, expected);
|
total, expected);
|
||||||
has_unexpected_conflicts = true;
|
if (total)
|
||||||
|
unexpected_conflicts_warning = complaint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (total)
|
else if (total)
|
||||||
@@ -741,15 +744,16 @@ conflicts_print (void)
|
|||||||
"%d reduce/reduce conflicts",
|
"%d reduce/reduce conflicts",
|
||||||
total),
|
total),
|
||||||
total);
|
total);
|
||||||
has_unexpected_conflicts = true;
|
unexpected_conflicts_warning = Wconflicts_rr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (warning_is_enabled (Wcounterexamples))
|
if (warning_is_enabled (Wcounterexamples))
|
||||||
report_counterexamples ();
|
report_counterexamples ();
|
||||||
else if (has_unexpected_conflicts)
|
else if (unexpected_conflicts_warning != Wnone)
|
||||||
complain (NULL, Wother,
|
subcomplain (NULL, unexpected_conflicts_warning,
|
||||||
_("rerun with option '-Wcounterexamples' to generate conflict counterexamples"));
|
_("rerun with option '-Wcounterexamples'"
|
||||||
|
" to generate conflict counterexamples"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
+173
-105
@@ -26,6 +26,7 @@
|
|||||||
#include <gl_linked_list.h>
|
#include <gl_linked_list.h>
|
||||||
#include <gl_rbtreehash_list.h>
|
#include <gl_rbtreehash_list.h>
|
||||||
#include <hash.h>
|
#include <hash.h>
|
||||||
|
#include <mbswidth.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <textstyle.h>
|
#include <textstyle.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
@@ -76,17 +77,29 @@ typedef struct
|
|||||||
{
|
{
|
||||||
derivation *d1;
|
derivation *d1;
|
||||||
derivation *d2;
|
derivation *d2;
|
||||||
|
bool shift_reduce;
|
||||||
bool unifying;
|
bool unifying;
|
||||||
bool timeout;
|
bool timeout;
|
||||||
} counterexample;
|
} counterexample;
|
||||||
|
|
||||||
static counterexample *
|
static counterexample *
|
||||||
new_counterexample (derivation *d1, derivation *d2,
|
new_counterexample (derivation *d1, derivation *d2,
|
||||||
|
bool shift_reduce,
|
||||||
bool u, bool t)
|
bool u, bool t)
|
||||||
{
|
{
|
||||||
counterexample *res = xmalloc (sizeof (counterexample));
|
counterexample *res = xmalloc (sizeof *res);
|
||||||
res->d1 = d1;
|
res->shift_reduce = shift_reduce;
|
||||||
res->d2 = d2;
|
if (shift_reduce)
|
||||||
|
{
|
||||||
|
// Display the shift first.
|
||||||
|
res->d1 = d2;
|
||||||
|
res->d2 = d1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res->d1 = d1;
|
||||||
|
res->d2 = d2;
|
||||||
|
}
|
||||||
res->unifying = u;
|
res->unifying = u;
|
||||||
res->timeout = t;
|
res->timeout = t;
|
||||||
return res;
|
return res;
|
||||||
@@ -101,13 +114,31 @@ free_counterexample (counterexample *cex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_counterexample (counterexample *cex, FILE *out, const char *prefix)
|
counterexample_print (const counterexample *cex, FILE *out, const char *prefix)
|
||||||
{
|
{
|
||||||
fprintf (out, " %s%-20s ",
|
const bool flat = getenv ("YYFLAT");
|
||||||
prefix, cex->unifying ? _("Example") : _("First example"));
|
const char *example1_label
|
||||||
derivation_print_leaves (cex->d1, out, prefix);
|
= cex->unifying ? _("Example") : _("First example");
|
||||||
fprintf (out, " %s%-20s ",
|
const char *example2_label
|
||||||
prefix, _("First derivation"));
|
= cex->unifying ? _("Example") : _("Second example");
|
||||||
|
const char *deriv1_label
|
||||||
|
= cex->shift_reduce ? _("Shift derivation") : _("First reduce derivation");
|
||||||
|
const char *deriv2_label
|
||||||
|
= cex->shift_reduce ? _("Reduce derivation") : _("Second reduce derivation");
|
||||||
|
const int width =
|
||||||
|
max_int (max_int (mbswidth (example1_label, 0), mbswidth (example2_label, 0)),
|
||||||
|
max_int (mbswidth (deriv1_label, 0), mbswidth (deriv2_label, 0)));
|
||||||
|
if (flat)
|
||||||
|
fprintf (out, " %s%s%*s ", prefix,
|
||||||
|
example1_label, width - mbswidth (example1_label, 0), "");
|
||||||
|
else
|
||||||
|
fprintf (out, " %s%s: ", prefix, example1_label);
|
||||||
|
derivation_print_leaves (cex->d1, out);
|
||||||
|
if (flat)
|
||||||
|
fprintf (out, " %s%s%*s ", prefix,
|
||||||
|
deriv1_label, width - mbswidth (deriv1_label, 0), "");
|
||||||
|
else
|
||||||
|
fprintf (out, " %s%s", prefix, deriv1_label);
|
||||||
derivation_print (cex->d1, out, prefix);
|
derivation_print (cex->d1, out, prefix);
|
||||||
|
|
||||||
// If we output to the terminal (via stderr) and we have color
|
// If we output to the terminal (via stderr) and we have color
|
||||||
@@ -115,15 +146,22 @@ print_counterexample (counterexample *cex, FILE *out, const char *prefix)
|
|||||||
// to see the differences.
|
// to see the differences.
|
||||||
if (!cex->unifying || is_styled (stderr))
|
if (!cex->unifying || is_styled (stderr))
|
||||||
{
|
{
|
||||||
fprintf (out, " %s%-20s ",
|
if (flat)
|
||||||
prefix, cex->unifying ? _("Example") : _("Second example"));
|
fprintf (out, " %s%s%*s ", prefix,
|
||||||
derivation_print_leaves (cex->d2, out, prefix);
|
example2_label, width - mbswidth (example2_label, 0), "");
|
||||||
|
else
|
||||||
|
fprintf (out, " %s%s: ", prefix, example2_label);
|
||||||
|
derivation_print_leaves (cex->d2, out);
|
||||||
}
|
}
|
||||||
fprintf (out, " %s%-20s ",
|
if (flat)
|
||||||
prefix, _("Second derivation"));
|
fprintf (out, " %s%s%*s ", prefix,
|
||||||
|
deriv2_label, width - mbswidth (deriv2_label, 0), "");
|
||||||
|
else
|
||||||
|
fprintf (out, " %s%s", prefix, deriv2_label);
|
||||||
derivation_print (cex->d2, out, prefix);
|
derivation_print (cex->d2, out, prefix);
|
||||||
|
|
||||||
fputc ('\n', out);
|
if (out != stderr)
|
||||||
|
putc ('\n', out);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -144,7 +182,7 @@ typedef struct si_bfs_node
|
|||||||
static si_bfs_node *
|
static si_bfs_node *
|
||||||
si_bfs_new (state_item_number si, si_bfs_node *parent)
|
si_bfs_new (state_item_number si, si_bfs_node *parent)
|
||||||
{
|
{
|
||||||
si_bfs_node *res = xcalloc (1, sizeof (si_bfs_node));
|
si_bfs_node *res = xcalloc (1, sizeof *res);
|
||||||
res->si = si;
|
res->si = si;
|
||||||
res->parent = parent;
|
res->parent = parent;
|
||||||
res->reference_count = 1;
|
res->reference_count = 1;
|
||||||
@@ -175,6 +213,8 @@ si_bfs_free (si_bfs_node *n)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef gl_list_t si_bfs_node_list;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* start is a state_item such that conflict_sym is an element of FIRSTS of the
|
* start is a state_item such that conflict_sym is an element of FIRSTS of the
|
||||||
* nonterminal after the dot in start. Because of this, we should be able to
|
* nonterminal after the dot in start. Because of this, we should be able to
|
||||||
@@ -188,15 +228,16 @@ expand_to_conflict (state_item_number start, symbol_number conflict_sym)
|
|||||||
{
|
{
|
||||||
si_bfs_node *init = si_bfs_new (start, NULL);
|
si_bfs_node *init = si_bfs_new (start, NULL);
|
||||||
|
|
||||||
gl_list_t queue = gl_list_create (GL_LINKED_LIST, NULL, NULL,
|
si_bfs_node_list queue
|
||||||
(gl_listelement_dispose_fn) si_bfs_free,
|
= gl_list_create (GL_LINKED_LIST, NULL, NULL,
|
||||||
true, 1, (const void **) &init);
|
(gl_listelement_dispose_fn) si_bfs_free,
|
||||||
|
true, 1, (const void **) &init);
|
||||||
si_bfs_node *node = NULL;
|
si_bfs_node *node = NULL;
|
||||||
// breadth-first search for a path of productions to the conflict symbol
|
// breadth-first search for a path of productions to the conflict symbol
|
||||||
while (gl_list_size (queue) > 0)
|
while (gl_list_size (queue) > 0)
|
||||||
{
|
{
|
||||||
node = (si_bfs_node *) gl_list_get_at (queue, 0);
|
node = (si_bfs_node *) gl_list_get_at (queue, 0);
|
||||||
state_item *silast = state_items + node->si;
|
state_item *silast = &state_items[node->si];
|
||||||
symbol_number sym = item_number_as_symbol_number (*silast->item);
|
symbol_number sym = item_number_as_symbol_number (*silast->item);
|
||||||
if (sym == conflict_sym)
|
if (sym == conflict_sym)
|
||||||
break;
|
break;
|
||||||
@@ -238,7 +279,7 @@ expand_to_conflict (state_item_number start, symbol_number conflict_sym)
|
|||||||
|
|
||||||
for (si_bfs_node *n = node; n != NULL; n = n->parent)
|
for (si_bfs_node *n = node; n != NULL; n = n->parent)
|
||||||
{
|
{
|
||||||
state_item *si = state_items + n->si;
|
state_item *si = &state_items[n->si];
|
||||||
item_number *pos = si->item;
|
item_number *pos = si->item;
|
||||||
if (SI_PRODUCTION (si))
|
if (SI_PRODUCTION (si))
|
||||||
{
|
{
|
||||||
@@ -274,7 +315,7 @@ expand_to_conflict (state_item_number start, symbol_number conflict_sym)
|
|||||||
*/
|
*/
|
||||||
static derivation *
|
static derivation *
|
||||||
complete_diverging_example (symbol_number conflict_sym,
|
complete_diverging_example (symbol_number conflict_sym,
|
||||||
gl_list_t path, derivation_list derivs)
|
state_item_list path, derivation_list derivs)
|
||||||
{
|
{
|
||||||
// The idea is to transfer each pending symbol on the productions
|
// The idea is to transfer each pending symbol on the productions
|
||||||
// associated with the given StateItems to the resulting derivation.
|
// associated with the given StateItems to the resulting derivation.
|
||||||
@@ -395,15 +436,15 @@ complete_diverging_example (symbol_number conflict_sym,
|
|||||||
/* Iterate backwards through the shifts of the path in the reduce
|
/* Iterate backwards through the shifts of the path in the reduce
|
||||||
conflict, and find a path of shifts from the shift conflict that
|
conflict, and find a path of shifts from the shift conflict that
|
||||||
goes through the same states. */
|
goes through the same states. */
|
||||||
static gl_list_t
|
static state_item_list
|
||||||
nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict)
|
nonunifying_shift_path (state_item_list reduce_path, state_item *shift_conflict)
|
||||||
{
|
{
|
||||||
gl_list_node_t tmp = gl_list_add_last (reduce_path, NULL);
|
gl_list_node_t tmp = gl_list_add_last (reduce_path, NULL);
|
||||||
gl_list_node_t next_node = gl_list_previous_node (reduce_path, tmp);
|
gl_list_node_t next_node = gl_list_previous_node (reduce_path, tmp);
|
||||||
gl_list_node_t node = gl_list_previous_node (reduce_path, next_node);
|
gl_list_node_t node = gl_list_previous_node (reduce_path, next_node);
|
||||||
gl_list_remove_node (reduce_path, tmp);
|
gl_list_remove_node (reduce_path, tmp);
|
||||||
state_item *si = shift_conflict;
|
state_item *si = shift_conflict;
|
||||||
gl_list_t result =
|
state_item_list result =
|
||||||
gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
|
gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
|
||||||
// FIXME: bool paths_merged;
|
// FIXME: bool paths_merged;
|
||||||
for (; node != NULL; next_node = node,
|
for (; node != NULL; next_node = node,
|
||||||
@@ -425,10 +466,10 @@ nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict)
|
|||||||
|
|
||||||
// bfs to find a shift to the right state
|
// bfs to find a shift to the right state
|
||||||
si_bfs_node *init = si_bfs_new (si - state_items, NULL);
|
si_bfs_node *init = si_bfs_new (si - state_items, NULL);
|
||||||
gl_list_t queue =
|
si_bfs_node_list queue
|
||||||
gl_list_create (GL_LINKED_LIST, NULL, NULL,
|
= gl_list_create (GL_LINKED_LIST, NULL, NULL,
|
||||||
(gl_listelement_dispose_fn) si_bfs_free,
|
(gl_listelement_dispose_fn) si_bfs_free,
|
||||||
true, 1, (const void **) &init);
|
true, 1, (const void **) &init);
|
||||||
si_bfs_node *sis = NULL;
|
si_bfs_node *sis = NULL;
|
||||||
state_item *prevsi = NULL;
|
state_item *prevsi = NULL;
|
||||||
while (gl_list_size (queue) > 0)
|
while (gl_list_size (queue) > 0)
|
||||||
@@ -438,7 +479,7 @@ nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict)
|
|||||||
if (sis->si == 0)
|
if (sis->si == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
state_item *search_si = state_items + sis->si;
|
state_item *search_si = &state_items[sis->si];
|
||||||
// if the current state-item is a production item,
|
// if the current state-item is a production item,
|
||||||
// its reverse production items get added to the queue.
|
// its reverse production items get added to the queue.
|
||||||
// Otherwise, look for a reverse transition to the target state.
|
// Otherwise, look for a reverse transition to the target state.
|
||||||
@@ -447,7 +488,7 @@ nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict)
|
|||||||
state_item_number sin;
|
state_item_number sin;
|
||||||
BITSET_FOR_EACH (biter, rsi, sin, 0)
|
BITSET_FOR_EACH (biter, rsi, sin, 0)
|
||||||
{
|
{
|
||||||
prevsi = state_items + sin;
|
prevsi = &state_items[sin];
|
||||||
if (SI_TRANSITION (search_si))
|
if (SI_TRANSITION (search_si))
|
||||||
{
|
{
|
||||||
if (prevsi->state == refsi->state)
|
if (prevsi->state == refsi->state)
|
||||||
@@ -465,9 +506,9 @@ nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict)
|
|||||||
// prepend path to shift we found
|
// prepend path to shift we found
|
||||||
if (sis)
|
if (sis)
|
||||||
{
|
{
|
||||||
gl_list_node_t ln = gl_list_add_first (result, state_items + sis->si);
|
gl_list_node_t ln = gl_list_add_first (result, &state_items[sis->si]);
|
||||||
for (si_bfs_node *n = sis->parent; n; n = n->parent)
|
for (si_bfs_node *n = sis->parent; n; n = n->parent)
|
||||||
ln = gl_list_add_after (result, ln, state_items + n->si);
|
ln = gl_list_add_after (result, ln, &state_items[n->si]);
|
||||||
|
|
||||||
}
|
}
|
||||||
si = prevsi;
|
si = prevsi;
|
||||||
@@ -480,7 +521,7 @@ nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict)
|
|||||||
for (gl_list_iterator_t it = gl_list_iterator (result);
|
for (gl_list_iterator_t it = gl_list_iterator (result);
|
||||||
state_item_list_next (&it, &sip);
|
state_item_list_next (&it, &sip);
|
||||||
)
|
)
|
||||||
print_state_item (sip, stderr, "");
|
state_item_print (sip, stderr, "");
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -493,17 +534,17 @@ nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict)
|
|||||||
static counterexample *
|
static counterexample *
|
||||||
example_from_path (bool shift_reduce,
|
example_from_path (bool shift_reduce,
|
||||||
state_item_number itm2,
|
state_item_number itm2,
|
||||||
gl_list_t shortest_path, symbol_number next_sym)
|
state_item_list shortest_path, symbol_number next_sym)
|
||||||
{
|
{
|
||||||
derivation *deriv1 =
|
derivation *deriv1 =
|
||||||
complete_diverging_example (next_sym, shortest_path, NULL);
|
complete_diverging_example (next_sym, shortest_path, NULL);
|
||||||
gl_list_t path_2
|
state_item_list path_2
|
||||||
= shift_reduce
|
= shift_reduce
|
||||||
? nonunifying_shift_path (shortest_path, &state_items [itm2])
|
? nonunifying_shift_path (shortest_path, &state_items [itm2])
|
||||||
: shortest_path_from_start (itm2, next_sym);
|
: shortest_path_from_start (itm2, next_sym);
|
||||||
derivation *deriv2 = complete_diverging_example (next_sym, path_2, NULL);
|
derivation *deriv2 = complete_diverging_example (next_sym, path_2, NULL);
|
||||||
gl_list_free (path_2);
|
gl_list_free (path_2);
|
||||||
return new_counterexample (deriv1, deriv2, false, true);
|
return new_counterexample (deriv1, deriv2, shift_reduce, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -525,7 +566,7 @@ typedef struct
|
|||||||
static search_state *
|
static search_state *
|
||||||
initial_search_state (state_item *conflict1, state_item *conflict2)
|
initial_search_state (state_item *conflict1, state_item *conflict2)
|
||||||
{
|
{
|
||||||
search_state *res = xmalloc (sizeof (search_state));
|
search_state *res = xmalloc (sizeof *res);
|
||||||
res->states[0] = new_parse_state (conflict1);
|
res->states[0] = new_parse_state (conflict1);
|
||||||
res->states[1] = new_parse_state (conflict2);
|
res->states[1] = new_parse_state (conflict2);
|
||||||
parse_state_retain (res->states[0]);
|
parse_state_retain (res->states[0]);
|
||||||
@@ -537,7 +578,7 @@ initial_search_state (state_item *conflict1, state_item *conflict2)
|
|||||||
static search_state *
|
static search_state *
|
||||||
new_search_state (parse_state *ps1, parse_state *ps2, int complexity)
|
new_search_state (parse_state *ps1, parse_state *ps2, int complexity)
|
||||||
{
|
{
|
||||||
search_state *res = xmalloc (sizeof (search_state));
|
search_state *res = xmalloc (sizeof *res);
|
||||||
res->states[0] = ps1;
|
res->states[0] = ps1;
|
||||||
res->states[1] = ps2;
|
res->states[1] = ps2;
|
||||||
parse_state_retain (res->states[0]);
|
parse_state_retain (res->states[0]);
|
||||||
@@ -549,8 +590,8 @@ new_search_state (parse_state *ps1, parse_state *ps2, int complexity)
|
|||||||
static search_state *
|
static search_state *
|
||||||
copy_search_state (search_state *parent)
|
copy_search_state (search_state *parent)
|
||||||
{
|
{
|
||||||
search_state *res = xmalloc (sizeof (search_state));
|
search_state *res = xmalloc (sizeof *res);
|
||||||
memcpy (res, parent, sizeof (search_state));
|
*res = *parent;
|
||||||
parse_state_retain (res->states[0]);
|
parse_state_retain (res->states[0]);
|
||||||
parse_state_retain (res->states[1]);
|
parse_state_retain (res->states[1]);
|
||||||
return res;
|
return res;
|
||||||
@@ -583,6 +624,8 @@ search_state_print (search_state *ss)
|
|||||||
putc ('\n', stderr);
|
putc ('\n', stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef gl_list_t search_state_list;
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
search_state_list_next (gl_list_iterator_t *it, search_state **ss)
|
search_state_list_next (gl_list_iterator_t *it, search_state **ss)
|
||||||
{
|
{
|
||||||
@@ -614,18 +657,20 @@ ss_set_parse_state (search_state *ss, int idx, parse_state *ps)
|
|||||||
*/
|
*/
|
||||||
static counterexample *
|
static counterexample *
|
||||||
complete_diverging_examples (search_state *ss,
|
complete_diverging_examples (search_state *ss,
|
||||||
symbol_number next_sym)
|
symbol_number next_sym,
|
||||||
|
bool shift_reduce)
|
||||||
{
|
{
|
||||||
derivation *new_derivs[2];
|
derivation *new_derivs[2];
|
||||||
for (int i = 0; i < 2; ++i)
|
for (int i = 0; i < 2; ++i)
|
||||||
{
|
{
|
||||||
gl_list_t sitems;
|
state_item_list sitems;
|
||||||
derivation_list derivs;
|
derivation_list derivs;
|
||||||
parse_state_lists (ss->states[i], &sitems, &derivs);
|
parse_state_lists (ss->states[i], &sitems, &derivs);
|
||||||
new_derivs[i] = complete_diverging_example (next_sym, sitems, derivs);
|
new_derivs[i] = complete_diverging_example (next_sym, sitems, derivs);
|
||||||
gl_list_free (sitems);
|
gl_list_free (sitems);
|
||||||
}
|
}
|
||||||
return new_counterexample (new_derivs[0], new_derivs[1], false, true);
|
return new_counterexample (new_derivs[0], new_derivs[1],
|
||||||
|
shift_reduce, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -635,7 +680,7 @@ complete_diverging_examples (search_state *ss,
|
|||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
gl_list_t states;
|
search_state_list states;
|
||||||
int complexity;
|
int complexity;
|
||||||
} search_state_bundle;
|
} search_state_bundle;
|
||||||
|
|
||||||
@@ -664,6 +709,8 @@ ssb_equals (const search_state_bundle *s1, const search_state_bundle *s2)
|
|||||||
return s1->complexity == s2->complexity;
|
return s1->complexity == s2->complexity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef gl_list_t ssb_list;
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
visited_hasher (const search_state *ss, size_t max)
|
visited_hasher (const search_state *ss, size_t max)
|
||||||
{
|
{
|
||||||
@@ -679,7 +726,7 @@ visited_comparator (const search_state *ss1, const search_state *ss2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Priority queue for search states with minimal complexity. */
|
/* Priority queue for search states with minimal complexity. */
|
||||||
static gl_list_t ssb_queue;
|
static ssb_list ssb_queue;
|
||||||
static Hash_table *visited;
|
static Hash_table *visited;
|
||||||
/* The set of parser states on the shortest lookahead-sensitive path. */
|
/* The set of parser states on the shortest lookahead-sensitive path. */
|
||||||
static bitset scp_set = NULL;
|
static bitset scp_set = NULL;
|
||||||
@@ -702,7 +749,7 @@ ssb_append (search_state *ss)
|
|||||||
parse_state_free_contents_early (ss->states[1]);
|
parse_state_free_contents_early (ss->states[1]);
|
||||||
parse_state_retain (ss->states[0]);
|
parse_state_retain (ss->states[0]);
|
||||||
parse_state_retain (ss->states[1]);
|
parse_state_retain (ss->states[1]);
|
||||||
search_state_bundle *ssb = xmalloc (sizeof (search_state_bundle));
|
search_state_bundle *ssb = xmalloc (sizeof *ssb);
|
||||||
ssb->complexity = ss->complexity;
|
ssb->complexity = ss->complexity;
|
||||||
gl_list_node_t n = gl_list_search (ssb_queue, ssb);
|
gl_list_node_t n = gl_list_search (ssb_queue, ssb);
|
||||||
if (!n)
|
if (!n)
|
||||||
@@ -756,12 +803,12 @@ reduction_cost (const parse_state *ps)
|
|||||||
return SHIFT_COST * shifts + PRODUCTION_COST * productions;
|
return SHIFT_COST * shifts + PRODUCTION_COST * productions;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gl_list_t
|
static search_state_list
|
||||||
reduction_step (search_state *ss, const item_number *conflict_item,
|
reduction_step (search_state *ss, const item_number *conflict_item,
|
||||||
int parser_state, int rule_len)
|
int parser_state, int rule_len)
|
||||||
{
|
{
|
||||||
(void) conflict_item; // FIXME: Unused
|
(void) conflict_item; // FIXME: Unused
|
||||||
gl_list_t result =
|
search_state_list result =
|
||||||
gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, 1);
|
gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, 1);
|
||||||
|
|
||||||
parse_state *ps = ss->states[parser_state];
|
parse_state *ps = ss->states[parser_state];
|
||||||
@@ -897,7 +944,7 @@ search_state_prepend (search_state *ss, symbol_number sym, bitset guide)
|
|||||||
* the same prefix up to the dot.
|
* the same prefix up to the dot.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
has_common_prefix (const item_number *itm1, const item_number *itm2)
|
have_common_prefix (const item_number *itm1, const item_number *itm2)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (; !item_number_is_rule_number (itm1[i]); ++i)
|
for (; !item_number_is_rule_number (itm1[i]); ++i)
|
||||||
@@ -988,14 +1035,14 @@ generate_next_states (search_state *ss, state_item *conflict1,
|
|||||||
// prepended further, reduce.
|
// prepended further, reduce.
|
||||||
if (ready1 && ready2)
|
if (ready1 && ready2)
|
||||||
{
|
{
|
||||||
gl_list_t reduced1 = reduction_step (ss, conflict1->item, 0, len1);
|
search_state_list reduced1 = reduction_step (ss, conflict1->item, 0, len1);
|
||||||
gl_list_add_last (reduced1, ss);
|
gl_list_add_last (reduced1, ss);
|
||||||
search_state *red1 = NULL;
|
search_state *red1 = NULL;
|
||||||
for (gl_list_iterator_t iter = gl_list_iterator (reduced1);
|
for (gl_list_iterator_t iter = gl_list_iterator (reduced1);
|
||||||
search_state_list_next (&iter, &red1);
|
search_state_list_next (&iter, &red1);
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
gl_list_t reduced2 =
|
search_state_list reduced2 =
|
||||||
reduction_step (red1, conflict2->item, 1, len2);
|
reduction_step (red1, conflict2->item, 1, len2);
|
||||||
search_state *red2 = NULL;
|
search_state *red2 = NULL;
|
||||||
for (gl_list_iterator_t iter2 = gl_list_iterator (reduced2);
|
for (gl_list_iterator_t iter2 = gl_list_iterator (reduced2);
|
||||||
@@ -1011,7 +1058,7 @@ generate_next_states (search_state *ss, state_item *conflict1,
|
|||||||
}
|
}
|
||||||
else if (ready1)
|
else if (ready1)
|
||||||
{
|
{
|
||||||
gl_list_t reduced1 = reduction_step (ss, conflict1->item, 0, len1);
|
search_state_list reduced1 = reduction_step (ss, conflict1->item, 0, len1);
|
||||||
search_state *red1 = NULL;
|
search_state *red1 = NULL;
|
||||||
for (gl_list_iterator_t iter = gl_list_iterator (reduced1);
|
for (gl_list_iterator_t iter = gl_list_iterator (reduced1);
|
||||||
search_state_list_next (&iter, &red1);
|
search_state_list_next (&iter, &red1);
|
||||||
@@ -1021,7 +1068,7 @@ generate_next_states (search_state *ss, state_item *conflict1,
|
|||||||
}
|
}
|
||||||
else if (ready2)
|
else if (ready2)
|
||||||
{
|
{
|
||||||
gl_list_t reduced2 = reduction_step (ss, conflict2->item, 1, len2);
|
search_state_list reduced2 = reduction_step (ss, conflict2->item, 1, len2);
|
||||||
search_state *red2 = NULL;
|
search_state *red2 = NULL;
|
||||||
for (gl_list_iterator_t iter2 = gl_list_iterator (reduced2);
|
for (gl_list_iterator_t iter2 = gl_list_iterator (reduced2);
|
||||||
search_state_list_next (&iter2, &red2);
|
search_state_list_next (&iter2, &red2);
|
||||||
@@ -1055,10 +1102,10 @@ static counterexample *
|
|||||||
unifying_example (state_item_number itm1,
|
unifying_example (state_item_number itm1,
|
||||||
state_item_number itm2,
|
state_item_number itm2,
|
||||||
bool shift_reduce,
|
bool shift_reduce,
|
||||||
gl_list_t reduce_path, symbol_number next_sym)
|
state_item_list reduce_path, symbol_number next_sym)
|
||||||
{
|
{
|
||||||
state_item *conflict1 = state_items + itm1;
|
state_item *conflict1 = &state_items[itm1];
|
||||||
state_item *conflict2 = state_items + itm2;
|
state_item *conflict2 = &state_items[itm2];
|
||||||
search_state *initial = initial_search_state (conflict1, conflict2);
|
search_state *initial = initial_search_state (conflict1, conflict2);
|
||||||
ssb_queue = gl_list_create_empty (GL_RBTREEHASH_LIST,
|
ssb_queue = gl_list_create_empty (GL_RBTREEHASH_LIST,
|
||||||
(gl_listelement_equals_fn) ssb_equals,
|
(gl_listelement_equals_fn) ssb_equals,
|
||||||
@@ -1094,7 +1141,7 @@ unifying_example (state_item_number itm1,
|
|||||||
const state_item *si1src = parse_state_head (ps1);
|
const state_item *si1src = parse_state_head (ps1);
|
||||||
const state_item *si2src = parse_state_head (ps2);
|
const state_item *si2src = parse_state_head (ps2);
|
||||||
if (item_rule (si1src->item)->lhs == item_rule (si2src->item)->lhs
|
if (item_rule (si1src->item)->lhs == item_rule (si2src->item)->lhs
|
||||||
&& has_common_prefix (si1src->item, si2src->item))
|
&& have_common_prefix (si1src->item, si2src->item))
|
||||||
{
|
{
|
||||||
// Stage 4: both paths share a prefix
|
// Stage 4: both paths share a prefix
|
||||||
derivation *d1 = parse_state_derivation (ps1);
|
derivation *d1 = parse_state_derivation (ps1);
|
||||||
@@ -1104,7 +1151,7 @@ unifying_example (state_item_number itm1,
|
|||||||
{
|
{
|
||||||
// Once we have two derivations for the same symbol,
|
// Once we have two derivations for the same symbol,
|
||||||
// we've found a unifying counterexample.
|
// we've found a unifying counterexample.
|
||||||
cex = new_counterexample (d1, d2, true, false);
|
cex = new_counterexample (d1, d2, shift_reduce, true, false);
|
||||||
derivation_retain (d1);
|
derivation_retain (d1);
|
||||||
derivation_retain (d2);
|
derivation_retain (d2);
|
||||||
goto cex_search_end;
|
goto cex_search_end;
|
||||||
@@ -1142,7 +1189,7 @@ cex_search_end:;
|
|||||||
// If a search state from Stage 3 is available, use it
|
// If a search state from Stage 3 is available, use it
|
||||||
// to construct a more compact nonunifying counterexample.
|
// to construct a more compact nonunifying counterexample.
|
||||||
if (stage3result)
|
if (stage3result)
|
||||||
cex = complete_diverging_examples (stage3result, next_sym);
|
cex = complete_diverging_examples (stage3result, next_sym, shift_reduce);
|
||||||
// Otherwise, construct a nonunifying counterexample that
|
// Otherwise, construct a nonunifying counterexample that
|
||||||
// begins from the start state using the shortest
|
// begins from the start state using the shortest
|
||||||
// lookahead-sensitive path to the reduce item.
|
// lookahead-sensitive path to the reduce item.
|
||||||
@@ -1190,7 +1237,7 @@ counterexample_report (state_item_number itm1, state_item_number itm2,
|
|||||||
{
|
{
|
||||||
// Compute the shortest lookahead-sensitive path and associated sets of
|
// Compute the shortest lookahead-sensitive path and associated sets of
|
||||||
// parser states.
|
// parser states.
|
||||||
gl_list_t shortest_path = shortest_path_from_start (itm1, next_sym);
|
state_item_list shortest_path = shortest_path_from_start (itm1, next_sym);
|
||||||
bool reduce_prod_reached = false;
|
bool reduce_prod_reached = false;
|
||||||
const rule *reduce_rule = item_rule (state_items[itm1].item);
|
const rule *reduce_rule = item_rule (state_items[itm1].item);
|
||||||
|
|
||||||
@@ -1215,21 +1262,31 @@ counterexample_report (state_item_number itm1, state_item_number itm2,
|
|||||||
: example_from_path (shift_reduce, itm2, shortest_path, next_sym);
|
: example_from_path (shift_reduce, itm2, shortest_path, next_sym);
|
||||||
|
|
||||||
gl_list_free (shortest_path);
|
gl_list_free (shortest_path);
|
||||||
print_counterexample (cex, out, prefix);
|
counterexample_print (cex, out, prefix);
|
||||||
free_counterexample (cex);
|
free_counterexample (cex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ITM1 denotes a shift, ITM2 a reduce.
|
||||||
static void
|
static void
|
||||||
counterexample_report_shift_reduce (state_item_number itm1, state_item_number itm2,
|
counterexample_report_shift_reduce (state_item_number itm1, state_item_number itm2,
|
||||||
symbol_number next_sym,
|
symbol_number next_sym,
|
||||||
FILE *out, const char *prefix)
|
FILE *out, const char *prefix)
|
||||||
{
|
{
|
||||||
fputs (prefix, out);
|
if (out == stderr)
|
||||||
fprintf (out, _("Shift/reduce conflict on token %s:\n"), symbols[next_sym]->tag);
|
complain (NULL, Wcounterexamples,
|
||||||
if (*prefix)
|
_("shift/reduce conflict on token %s"), symbols[next_sym]->tag);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
print_state_item (&state_items[itm1], out, prefix);
|
fputs (prefix, out);
|
||||||
print_state_item (&state_items[itm2], out, prefix);
|
fprintf (out, _("shift/reduce conflict on token %s"), symbols[next_sym]->tag);
|
||||||
|
fprintf (out, "%s\n", _(":"));
|
||||||
|
}
|
||||||
|
// In the report, print the items.
|
||||||
|
if (out != stderr || trace_flag & trace_cex)
|
||||||
|
{
|
||||||
|
state_item_print (&state_items[itm1], out, prefix);
|
||||||
|
state_item_print (&state_items[itm2], out, prefix);
|
||||||
}
|
}
|
||||||
counterexample_report (itm1, itm2, next_sym, true, out, prefix);
|
counterexample_report (itm1, itm2, next_sym, true, out, prefix);
|
||||||
}
|
}
|
||||||
@@ -1240,32 +1297,49 @@ counterexample_report_reduce_reduce (state_item_number itm1, state_item_number i
|
|||||||
FILE *out, const char *prefix)
|
FILE *out, const char *prefix)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
fputs (prefix, out);
|
struct obstack obstack;
|
||||||
fputs (ngettext ("Reduce/reduce conflict on token",
|
obstack_init (&obstack);
|
||||||
"Reduce/reduce conflict on tokens",
|
|
||||||
bitset_count (conflict_syms)), out);
|
|
||||||
bitset_iterator biter;
|
bitset_iterator biter;
|
||||||
state_item_number sym;
|
state_item_number sym;
|
||||||
const char *sep = " ";
|
const char *sep = "";
|
||||||
BITSET_FOR_EACH (biter, conflict_syms, sym, 0)
|
BITSET_FOR_EACH (biter, conflict_syms, sym, 0)
|
||||||
{
|
{
|
||||||
fprintf (out, "%s%s", sep, symbols[sym]->tag);
|
obstack_printf (&obstack, "%s%s", sep, symbols[sym]->tag);
|
||||||
sep = ", ";
|
sep = ", ";
|
||||||
}
|
}
|
||||||
fputs (_(":\n"), out);
|
char *tokens = obstack_finish0 (&obstack);
|
||||||
|
if (out == stderr)
|
||||||
|
complain (NULL, Wcounterexamples,
|
||||||
|
ngettext ("reduce/reduce conflict on token %s",
|
||||||
|
"reduce/reduce conflict on tokens %s",
|
||||||
|
bitset_count (conflict_syms)),
|
||||||
|
tokens);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fputs (prefix, out);
|
||||||
|
fprintf (out,
|
||||||
|
ngettext ("reduce/reduce conflict on token %s",
|
||||||
|
"reduce/reduce conflict on tokens %s",
|
||||||
|
bitset_count (conflict_syms)),
|
||||||
|
tokens);
|
||||||
|
fprintf (out, "%s\n", _(":"));
|
||||||
|
}
|
||||||
|
obstack_free (&obstack, NULL);
|
||||||
}
|
}
|
||||||
if (*prefix)
|
// In the report, print the items.
|
||||||
|
if (out != stderr || trace_flag & trace_cex)
|
||||||
{
|
{
|
||||||
print_state_item (&state_items[itm1], out, prefix);
|
state_item_print (&state_items[itm1], out, prefix);
|
||||||
print_state_item (&state_items[itm2], out, prefix);
|
state_item_print (&state_items[itm2], out, prefix);
|
||||||
}
|
}
|
||||||
counterexample_report (itm1, itm2, bitset_first (conflict_syms), false, out, prefix);
|
counterexample_report (itm1, itm2, bitset_first (conflict_syms),
|
||||||
|
false, out, prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
static state_item_number
|
static state_item_number
|
||||||
find_state_item_number (const rule *r, state_number sn)
|
find_state_item_number (const rule *r, state_number sn)
|
||||||
{
|
{
|
||||||
for (int i = state_item_map[sn]; i < state_item_map[sn + 1]; ++i)
|
for (state_item_number i = state_item_map[sn]; i < state_item_map[sn + 1]; ++i)
|
||||||
if (!SI_DISABLED (i)
|
if (!SI_DISABLED (i)
|
||||||
&& item_number_as_rule_number (*state_items[i].item) == r->number)
|
&& item_number_as_rule_number (*state_items[i].item) == r->number)
|
||||||
return i;
|
return i;
|
||||||
@@ -1277,41 +1351,35 @@ counterexample_report_state (const state *s, FILE *out, const char *prefix)
|
|||||||
{
|
{
|
||||||
const state_number sn = s->number;
|
const state_number sn = s->number;
|
||||||
const reductions *reds = s->reductions;
|
const reductions *reds = s->reductions;
|
||||||
|
bitset lookaheads = bitset_create (ntokens, BITSET_FIXED);
|
||||||
for (int i = 0; i < reds->num; ++i)
|
for (int i = 0; i < reds->num; ++i)
|
||||||
{
|
{
|
||||||
const rule *r1 = reds->rules[i];
|
const rule *r1 = reds->rules[i];
|
||||||
const state_item_number c1 = find_state_item_number (r1, sn);
|
const state_item_number c1 = find_state_item_number (r1, sn);
|
||||||
for (int j = state_item_map[sn]; j < state_item_map[sn + 1]; ++j)
|
for (state_item_number c2 = state_item_map[sn]; c2 < state_item_map[sn + 1]; ++c2)
|
||||||
if (!SI_DISABLED (j))
|
if (!SI_DISABLED (c2))
|
||||||
{
|
{
|
||||||
state_item *si = state_items + j;
|
item_number conf = *state_items[c2].item;
|
||||||
item_number conf = *si->item;
|
|
||||||
if (item_number_is_symbol_number (conf)
|
if (item_number_is_symbol_number (conf)
|
||||||
&& bitset_test (reds->lookahead_tokens[i], conf))
|
&& bitset_test (reds->lookaheads[i], conf))
|
||||||
counterexample_report_shift_reduce (c1, j, conf, out, prefix);
|
counterexample_report_shift_reduce (c1, c2, conf, out, prefix);
|
||||||
}
|
}
|
||||||
for (int j = i+1; j < reds->num; ++j)
|
for (int j = i+1; j < reds->num; ++j)
|
||||||
{
|
{
|
||||||
bitset conf = bitset_create (ntokens, BITSET_FIXED);
|
const rule *r2 = reds->rules[j];
|
||||||
bitset_intersection (conf,
|
// Conflicts: common lookaheads.
|
||||||
reds->lookahead_tokens[i],
|
bitset_intersection (lookaheads,
|
||||||
reds->lookahead_tokens[j]);
|
reds->lookaheads[i],
|
||||||
if (!bitset_empty_p (conf))
|
reds->lookaheads[j]);
|
||||||
{
|
if (!bitset_empty_p (lookaheads))
|
||||||
const rule *r2 = reds->rules[j];
|
for (state_item_number c2 = state_item_map[sn]; c2 < state_item_map[sn + 1]; ++c2)
|
||||||
for (int k = state_item_map[sn]; k < state_item_map[sn + 1]; ++k)
|
if (!SI_DISABLED (c2)
|
||||||
if (!SI_DISABLED (k))
|
&& item_rule (state_items[c2].item) == r2)
|
||||||
{
|
{
|
||||||
state_item *si = state_items + k;
|
counterexample_report_reduce_reduce (c1, c2, lookaheads, out, prefix);
|
||||||
const rule *r = item_rule (si->item);
|
break;
|
||||||
if (r == r2)
|
}
|
||||||
{
|
|
||||||
counterexample_report_reduce_reduce (c1, k, conf, out, prefix);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bitset_free (conf);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bitset_free (lookaheads);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,17 @@
|
|||||||
#ifndef COUNTEREXAMPLE_H
|
#ifndef COUNTEREXAMPLE_H
|
||||||
# define COUNTEREXAMPLE_H
|
# define COUNTEREXAMPLE_H
|
||||||
|
|
||||||
# include "state-item.h"
|
# include "state.h"
|
||||||
|
|
||||||
|
// Init/deinit this module.
|
||||||
void counterexample_init (void);
|
void counterexample_init (void);
|
||||||
void counterexample_free (void);
|
void counterexample_free (void);
|
||||||
|
|
||||||
void counterexample_report_state (const state *s, FILE *out, const char *prefix);
|
// Print the counterexamples for the conflicts of state S.
|
||||||
|
//
|
||||||
|
// Used both for the warnings on the terminal (OUT = stderr, PREFIX =
|
||||||
|
// ""), and for the reports (OUT != stderr, PREFIX != "").
|
||||||
|
void
|
||||||
|
counterexample_report_state (const state *s, FILE *out, const char *prefix);
|
||||||
|
|
||||||
#endif /* COUNTEREXAMPLE_H */
|
#endif /* COUNTEREXAMPLE_H */
|
||||||
|
|||||||
+271
-46
@@ -20,8 +20,11 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#include "derivation.h"
|
#include "derivation.h"
|
||||||
|
#include "glyphs.h"
|
||||||
|
|
||||||
|
#include <c-ctype.h>
|
||||||
#include <gl_linked_list.h>
|
#include <gl_linked_list.h>
|
||||||
|
#include <mbswidth.h>
|
||||||
|
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "complain.h"
|
#include "complain.h"
|
||||||
@@ -29,11 +32,15 @@
|
|||||||
struct derivation
|
struct derivation
|
||||||
{
|
{
|
||||||
symbol_number sym;
|
symbol_number sym;
|
||||||
gl_list_t children;
|
derivation_list children;
|
||||||
int reference_count;
|
int reference_count;
|
||||||
|
// Color assigned for styling. Guarantees that the derivation is
|
||||||
|
// always displayed with the same color, independently of the order
|
||||||
|
// in which the derivations are traversed.
|
||||||
|
int color;
|
||||||
};
|
};
|
||||||
|
|
||||||
static derivation d_dot = { -1, NULL, -1 };
|
static derivation d_dot = { -1, NULL, -1, -1 };
|
||||||
|
|
||||||
derivation *
|
derivation *
|
||||||
derivation_dot (void)
|
derivation_dot (void)
|
||||||
@@ -69,11 +76,12 @@ void derivation_list_free (derivation_list dl)
|
|||||||
derivation *
|
derivation *
|
||||||
derivation_new (symbol_number sym, derivation_list children)
|
derivation_new (symbol_number sym, derivation_list children)
|
||||||
{
|
{
|
||||||
derivation *deriv = xmalloc (sizeof (derivation));
|
derivation *res = xmalloc (sizeof *res);
|
||||||
deriv->sym = sym;
|
res->sym = sym;
|
||||||
deriv->children = children;
|
res->children = children;
|
||||||
deriv->reference_count = 0;
|
res->reference_count = 0;
|
||||||
return deriv;
|
res->color = -1;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -126,27 +134,236 @@ derivation_size (const derivation *deriv)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print DERIV, colored according to COUNTER.
|
|
||||||
Return false if nothing is printed. */
|
// Longest distance from root to leaf.
|
||||||
|
static int
|
||||||
|
derivation_depth (const derivation *deriv)
|
||||||
|
{
|
||||||
|
if (deriv->children)
|
||||||
|
{
|
||||||
|
// Children's depth cannot be 0, even if there are no children
|
||||||
|
// (the case of a derivation with an empty RHS).
|
||||||
|
int res = 1;
|
||||||
|
derivation *child;
|
||||||
|
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
|
||||||
|
derivation_list_next (&it, &child);
|
||||||
|
)
|
||||||
|
res = max_int (res, derivation_depth (child));
|
||||||
|
return res + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
derivation_print_impl (const derivation *deriv, FILE *f,
|
all_spaces (const char *s)
|
||||||
bool leaves_only,
|
{
|
||||||
int *counter, const char *prefix)
|
while (c_isspace (*s))
|
||||||
|
s++;
|
||||||
|
return *s == '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Printing the derivation as trees without trailing spaces is
|
||||||
|
// painful: we cannot simply pad one "column" before moving to the
|
||||||
|
// next:
|
||||||
|
//
|
||||||
|
// exp
|
||||||
|
// ↳ x1 e1 foo1 x1
|
||||||
|
// ↳ x2 ↳ ε ↳ foo2 ↳ x2
|
||||||
|
// ↳ x3 ↳ foo3 ↳ x3
|
||||||
|
// ↳ "X" • ↳ x1 foo4 ↳ "X"
|
||||||
|
// ↳ x2 ↳ "quuux"
|
||||||
|
// ↳ x3
|
||||||
|
// ↳ "X"
|
||||||
|
//
|
||||||
|
// It's hard for a column to know that it's "last" to decide whether
|
||||||
|
// to output the right-padding or not. So when we need to pad on the
|
||||||
|
// right to complete a column, we don't output the spaces, we
|
||||||
|
// accumulate the width of padding in *PADDING.
|
||||||
|
//
|
||||||
|
// Each time we actually print something (non space), we flush that
|
||||||
|
// padding. When we _don't_ print something, its width is added to
|
||||||
|
// the current padding.
|
||||||
|
//
|
||||||
|
// This function implements this.
|
||||||
|
//
|
||||||
|
// When COND is true, put S on OUT, preceded by *PADDING white spaces.
|
||||||
|
// Otherwise add the width to *PADDING. Return the width of S.
|
||||||
|
static int
|
||||||
|
fputs_if (bool cond, FILE *out, int *padding, const char *s)
|
||||||
|
{
|
||||||
|
int res = mbswidth (s, 0);
|
||||||
|
if (cond && !all_spaces (s))
|
||||||
|
{
|
||||||
|
fprintf (out, "%*s%s", *padding, "", s);
|
||||||
|
*padding = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*padding += res;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The width taken to report this derivation recursively down to its
|
||||||
|
// leaves.
|
||||||
|
static int
|
||||||
|
derivation_width (const derivation *deriv)
|
||||||
{
|
{
|
||||||
|
if (deriv->children)
|
||||||
|
{
|
||||||
|
const symbol *sym = symbols[deriv->sym];
|
||||||
|
int self_width = mbswidth (sym->tag, 0);
|
||||||
|
|
||||||
|
// Arrow and space.
|
||||||
|
int children_width = down_arrow_width;
|
||||||
|
if (gl_list_size (deriv->children) == 0)
|
||||||
|
// Empty rhs.
|
||||||
|
children_width += empty_width;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
derivation *child;
|
||||||
|
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
|
||||||
|
derivation_list_next (&it, &child);
|
||||||
|
)
|
||||||
|
children_width
|
||||||
|
+= derivation_separator_width + derivation_width (child);
|
||||||
|
// No separator at the beginning.
|
||||||
|
children_width -= derivation_separator_width;
|
||||||
|
}
|
||||||
|
return max_int (self_width, children_width);
|
||||||
|
}
|
||||||
|
else if (deriv == &d_dot)
|
||||||
|
{
|
||||||
|
return dot_width;
|
||||||
|
}
|
||||||
|
else // leaf.
|
||||||
|
{
|
||||||
|
const symbol *sym = symbols[deriv->sym];
|
||||||
|
return mbswidth (sym->tag, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Print DERIV for DEPTH.
|
||||||
|
//
|
||||||
|
// The tree is printed from top to bottom with DEPTH ranging from 0 to
|
||||||
|
// the total depth of the tree. DERIV should only printed when we
|
||||||
|
// reach its depth, i.e., then DEPTH is 0.
|
||||||
|
//
|
||||||
|
// When DEPTH is 1 and we're on a subderivation, then we print the RHS
|
||||||
|
// of the derivation (in DEPTH 0 we printed its LHS).
|
||||||
|
//
|
||||||
|
// Return the "logical printed" width. We might have not have reached
|
||||||
|
// that width, in which case the missing spaces are in *PADDING.
|
||||||
|
static int
|
||||||
|
derivation_print_tree_impl (const derivation *deriv, FILE *out,
|
||||||
|
int depth, int *padding)
|
||||||
|
{
|
||||||
|
const int width = derivation_width (deriv);
|
||||||
|
|
||||||
|
int res = 0;
|
||||||
if (deriv->children)
|
if (deriv->children)
|
||||||
{
|
{
|
||||||
const symbol *sym = symbols[deriv->sym];
|
const symbol *sym = symbols[deriv->sym];
|
||||||
char style[20];
|
char style[20];
|
||||||
snprintf (style, 20, "cex-%d", *counter);
|
snprintf (style, 20, "cex-%d", deriv->color);
|
||||||
|
|
||||||
|
if (depth == 0 || depth == 1)
|
||||||
|
{
|
||||||
|
begin_use_class (style, out);
|
||||||
|
begin_use_class ("cex-step", out);
|
||||||
|
}
|
||||||
|
if (depth == 0)
|
||||||
|
{
|
||||||
|
res += fputs_if (true, out, padding, sym->tag);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res += fputs_if (depth == 1, out, padding, down_arrow);
|
||||||
|
if (gl_list_size (deriv->children) == 0)
|
||||||
|
// Empty rhs.
|
||||||
|
res += fputs_if (depth == 1, out, padding, empty);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool first = true;
|
||||||
|
derivation *child;
|
||||||
|
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
|
||||||
|
derivation_list_next (&it, &child);
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!first)
|
||||||
|
res += fputs_if (depth == 1, out, padding, derivation_separator);
|
||||||
|
res += derivation_print_tree_impl (child, out, depth - 1, padding);
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (depth == 0 || depth == 1)
|
||||||
|
{
|
||||||
|
end_use_class ("cex-step", out);
|
||||||
|
end_use_class (style, out);
|
||||||
|
}
|
||||||
|
*padding += width - res;
|
||||||
|
res = width;
|
||||||
|
}
|
||||||
|
else if (deriv == &d_dot)
|
||||||
|
{
|
||||||
|
if (depth == 0)
|
||||||
|
begin_use_class ("cex-dot", out);
|
||||||
|
res += fputs_if (depth == 0, out, padding, dot);
|
||||||
|
if (depth == 0)
|
||||||
|
end_use_class ("cex-dot", out);
|
||||||
|
}
|
||||||
|
else // leaf.
|
||||||
|
{
|
||||||
|
const symbol *sym = symbols[deriv->sym];
|
||||||
|
if (depth == 0)
|
||||||
|
begin_use_class ("cex-leaf", out);
|
||||||
|
res += fputs_if (depth == 0, out, padding, sym->tag);
|
||||||
|
if (depth == 0)
|
||||||
|
end_use_class ("cex-leaf", out);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
derivation_print_tree (const derivation *deriv, FILE *out, const char *prefix)
|
||||||
|
{
|
||||||
|
fputc ('\n', out);
|
||||||
|
for (int depth = 0, max_depth = derivation_depth (deriv);
|
||||||
|
depth < max_depth; ++depth)
|
||||||
|
{
|
||||||
|
int padding = 0;
|
||||||
|
fprintf (out, " %s", prefix);
|
||||||
|
derivation_print_tree_impl (deriv, out, depth, &padding);
|
||||||
|
fputc ('\n', out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Print DERIV, colored according to COUNTER.
|
||||||
|
Return false if nothing is printed. */
|
||||||
|
static bool
|
||||||
|
derivation_print_flat_impl (derivation *deriv, FILE *out,
|
||||||
|
bool leaves_only,
|
||||||
|
int *counter, const char *prefix)
|
||||||
|
{
|
||||||
|
if (deriv->children)
|
||||||
|
{
|
||||||
|
const symbol *sym = symbols[deriv->sym];
|
||||||
|
deriv->color = *counter;
|
||||||
++*counter;
|
++*counter;
|
||||||
begin_use_class (style, f);
|
char style[20];
|
||||||
|
snprintf (style, 20, "cex-%d", deriv->color);
|
||||||
|
begin_use_class (style, out);
|
||||||
|
|
||||||
if (!leaves_only)
|
if (!leaves_only)
|
||||||
{
|
{
|
||||||
fputs (prefix, f);
|
fputs (prefix, out);
|
||||||
begin_use_class ("cex-step", f);
|
begin_use_class ("cex-step", out);
|
||||||
fprintf (f, "%s ::=[ ", sym->tag);
|
fprintf (out, "%s %s [ ", sym->tag, arrow);
|
||||||
end_use_class ("cex-step", f);
|
end_use_class ("cex-step", out);
|
||||||
prefix = "";
|
prefix = "";
|
||||||
}
|
}
|
||||||
bool res = false;
|
bool res = false;
|
||||||
@@ -155,7 +372,8 @@ derivation_print_impl (const derivation *deriv, FILE *f,
|
|||||||
derivation_list_next (&it, &child);
|
derivation_list_next (&it, &child);
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (derivation_print_impl (child, f, leaves_only, counter, prefix))
|
if (derivation_print_flat_impl (child, out,
|
||||||
|
leaves_only, counter, prefix))
|
||||||
{
|
{
|
||||||
prefix = " ";
|
prefix = " ";
|
||||||
res = true;
|
res = true;
|
||||||
@@ -165,49 +383,56 @@ derivation_print_impl (const derivation *deriv, FILE *f,
|
|||||||
}
|
}
|
||||||
if (!leaves_only)
|
if (!leaves_only)
|
||||||
{
|
{
|
||||||
begin_use_class ("cex-step", f);
|
begin_use_class ("cex-step", out);
|
||||||
if (res)
|
if (res)
|
||||||
fputs (" ]", f);
|
fputs (" ]", out);
|
||||||
else
|
else
|
||||||
fputs ("]", f);
|
fputs ("]", out);
|
||||||
end_use_class ("cex-step", f);
|
end_use_class ("cex-step", out);
|
||||||
}
|
}
|
||||||
end_use_class (style, f);
|
end_use_class (style, out);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
else if (deriv == &d_dot)
|
else if (deriv == &d_dot)
|
||||||
{
|
{
|
||||||
fputs (prefix, f);
|
fputs (prefix, out);
|
||||||
begin_use_class ("cex-dot", f);
|
begin_use_class ("cex-dot", out);
|
||||||
print_dot (f);
|
fputs (dot, out);
|
||||||
end_use_class ("cex-dot", f);
|
end_use_class ("cex-dot", out);
|
||||||
}
|
}
|
||||||
else // leaf.
|
else // leaf.
|
||||||
{
|
{
|
||||||
fputs (prefix, f);
|
fputs (prefix, out);
|
||||||
const symbol *sym = symbols[deriv->sym];
|
const symbol *sym = symbols[deriv->sym];
|
||||||
begin_use_class ("cex-leaf", f);
|
begin_use_class ("cex-leaf", out);
|
||||||
fprintf (f, "%s", sym->tag);
|
fprintf (out, "%s", sym->tag);
|
||||||
end_use_class ("cex-leaf", f);
|
end_use_class ("cex-leaf", out);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
derivation_print_flat (const derivation *deriv, FILE *out, const char *prefix)
|
||||||
|
{
|
||||||
|
int counter = 0;
|
||||||
|
fputs (prefix, out);
|
||||||
|
derivation_print_flat_impl ((derivation *)deriv, out, false, &counter, "");
|
||||||
|
fputc ('\n', out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
derivation_print_leaves (const derivation *deriv, FILE *out)
|
||||||
|
{
|
||||||
|
int counter = 0;
|
||||||
|
derivation_print_flat_impl ((derivation *)deriv, out, true, &counter, "");
|
||||||
|
fputc ('\n', out);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
derivation_print (const derivation *deriv, FILE *out, const char *prefix)
|
derivation_print (const derivation *deriv, FILE *out, const char *prefix)
|
||||||
{
|
{
|
||||||
int counter = 0;
|
if (getenv ("YYFLAT"))
|
||||||
fputs (prefix, out);
|
derivation_print_flat (deriv, out, prefix);
|
||||||
derivation_print_impl (deriv, out, false, &counter, "");
|
else
|
||||||
fputc ('\n', out);
|
derivation_print_tree (deriv, out, prefix);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
derivation_print_leaves (const derivation *deriv, FILE *out, const char *prefix)
|
|
||||||
{
|
|
||||||
int counter = 0;
|
|
||||||
fputs (prefix, out);
|
|
||||||
derivation_print_impl (deriv, out, true, &counter, "");
|
|
||||||
fputc ('\n', out);
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -60,12 +60,15 @@ static inline derivation *derivation_new_leaf (symbol_number sym)
|
|||||||
{
|
{
|
||||||
return derivation_new (sym, NULL);
|
return derivation_new (sym, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Number of symbols.
|
||||||
size_t derivation_size (const derivation *deriv);
|
size_t derivation_size (const derivation *deriv);
|
||||||
void derivation_print (const derivation *deriv, FILE *out, const char *prefix);
|
void derivation_print (const derivation *deriv, FILE *out, const char *prefix);
|
||||||
void derivation_print_leaves (const derivation *deriv, FILE *out, const char *prefix);
|
void derivation_print_leaves (const derivation *deriv, FILE *out);
|
||||||
void derivation_free (derivation *deriv);
|
void derivation_free (derivation *deriv);
|
||||||
void derivation_retain (derivation *deriv);
|
void derivation_retain (derivation *deriv);
|
||||||
|
|
||||||
|
// A derivation denoting the position of the dot.
|
||||||
derivation *derivation_dot (void);
|
derivation *derivation_dot (void);
|
||||||
|
|
||||||
#endif /* DERIVATION_H */
|
#endif /* DERIVATION_H */
|
||||||
|
|||||||
+9
-1
@@ -112,7 +112,15 @@ static struct obstack obstack_for_string;
|
|||||||
# define STRING_1GROW(Char) \
|
# define STRING_1GROW(Char) \
|
||||||
obstack_1grow (&obstack_for_string, Char)
|
obstack_1grow (&obstack_for_string, Char)
|
||||||
|
|
||||||
# define STRING_FREE() \
|
# ifdef NDEBUG
|
||||||
|
# define STRING_FREE() \
|
||||||
obstack_free (&obstack_for_string, last_string)
|
obstack_free (&obstack_for_string, last_string)
|
||||||
|
# else
|
||||||
|
# define STRING_FREE() \
|
||||||
|
do { \
|
||||||
|
obstack_free (&obstack_for_string, last_string); \
|
||||||
|
last_string = NULL; \
|
||||||
|
} while (0)
|
||||||
|
# endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+1
-1
@@ -221,7 +221,7 @@ static const argmatch_report_arg argmatch_report_args[] =
|
|||||||
{ "none", report_none },
|
{ "none", report_none },
|
||||||
{ "states", report_states },
|
{ "states", report_states },
|
||||||
{ "itemsets", report_states | report_itemsets },
|
{ "itemsets", report_states | report_itemsets },
|
||||||
{ "lookaheads", report_states | report_lookahead_tokens },
|
{ "lookaheads", report_states | report_lookaheads },
|
||||||
{ "solved", report_states | report_solved_conflicts },
|
{ "solved", report_states | report_solved_conflicts },
|
||||||
{ "counterexamples", report_cex },
|
{ "counterexamples", report_cex },
|
||||||
{ "cex", report_cex },
|
{ "cex", report_cex },
|
||||||
|
|||||||
+1
-1
@@ -77,7 +77,7 @@ enum report
|
|||||||
report_none = 0,
|
report_none = 0,
|
||||||
report_states = 1 << 0,
|
report_states = 1 << 0,
|
||||||
report_itemsets = 1 << 1,
|
report_itemsets = 1 << 1,
|
||||||
report_lookahead_tokens = 1 << 2,
|
report_lookaheads = 1 << 2,
|
||||||
report_solved_conflicts = 1 << 3,
|
report_solved_conflicts = 1 << 3,
|
||||||
report_cex = 1 << 4,
|
report_cex = 1 << 4,
|
||||||
report_all = ~0
|
report_all = ~0
|
||||||
|
|||||||
@@ -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 */
|
||||||
+2
-2
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include "complain.h"
|
#include "complain.h"
|
||||||
#include "getargs.h"
|
#include "getargs.h"
|
||||||
|
#include "glyphs.h"
|
||||||
#include "gram.h"
|
#include "gram.h"
|
||||||
#include "print-xml.h"
|
#include "print-xml.h"
|
||||||
#include "reader.h"
|
#include "reader.h"
|
||||||
@@ -56,8 +57,7 @@ item_print (item_number *item, rule const *previous_rule, FILE *out)
|
|||||||
|
|
||||||
for (item_number *sp = r->rhs; sp < item; sp++)
|
for (item_number *sp = r->rhs; sp < item; sp++)
|
||||||
fprintf (out, " %s", symbols[*sp]->tag);
|
fprintf (out, " %s", symbols[*sp]->tag);
|
||||||
putc (' ', out);
|
fprintf (out, " %s", dot);
|
||||||
print_dot (out);
|
|
||||||
if (0 <= *r->rhs)
|
if (0 <= *r->rhs)
|
||||||
for (item_number *sp = item; 0 <= *sp; ++sp)
|
for (item_number *sp = item; 0 <= *sp; ++sp)
|
||||||
fprintf (out, " %s", symbols[*sp]->tag);
|
fprintf (out, " %s", symbols[*sp]->tag);
|
||||||
|
|||||||
-21
@@ -103,8 +103,6 @@
|
|||||||
|
|
||||||
# include "system.h"
|
# include "system.h"
|
||||||
|
|
||||||
# include <unicodeio.h>
|
|
||||||
|
|
||||||
# include "location.h"
|
# include "location.h"
|
||||||
# include "symtab.h"
|
# include "symtab.h"
|
||||||
|
|
||||||
@@ -217,25 +215,6 @@ typedef struct
|
|||||||
extern rule *rules;
|
extern rule *rules;
|
||||||
extern rule_number nrules;
|
extern rule_number nrules;
|
||||||
|
|
||||||
/* Fallback in case we can't print "•". */
|
|
||||||
static inline long
|
|
||||||
print_dot_fallback (unsigned int code _GL_UNUSED,
|
|
||||||
const char *msg _GL_UNUSED,
|
|
||||||
void *callback_arg)
|
|
||||||
{
|
|
||||||
FILE *out = (FILE *) callback_arg;
|
|
||||||
putc ('.', out);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print "•", the symbol used to represent a point in an item (aka, a
|
|
||||||
dotted rule). */
|
|
||||||
static inline void
|
|
||||||
print_dot (FILE *out)
|
|
||||||
{
|
|
||||||
unicode_to_mb (0x2022, fwrite_success_callback, print_dot_fallback, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the rule associated to this item. ITEM points inside RITEM. */
|
/* Get the rule associated to this item. ITEM points inside RITEM. */
|
||||||
static inline rule const *
|
static inline rule const *
|
||||||
item_rule (item_number const *item)
|
item_rule (item_number const *item)
|
||||||
|
|||||||
+2
-2
@@ -184,9 +184,9 @@ output_red (state const *s, reductions const *reds, FILE *fout)
|
|||||||
bool firste = true;
|
bool firste = true;
|
||||||
rule_number ruleno = reds->rules[j]->number;
|
rule_number ruleno = reds->rules[j]->number;
|
||||||
|
|
||||||
if (reds->lookahead_tokens)
|
if (reds->lookaheads)
|
||||||
for (int i = 0; i < ntokens; i++)
|
for (int i = 0; i < ntokens; i++)
|
||||||
if (bitset_test (reds->lookahead_tokens[j], i))
|
if (bitset_test (reds->lookaheads[j], i))
|
||||||
{
|
{
|
||||||
if (bitset_test (no_reduce_set, i))
|
if (bitset_test (no_reduce_set, i))
|
||||||
firstd = print_token (&dout, firstd, symbols[i]->tag);
|
firstd = print_token (&dout, firstd, symbols[i]->tag);
|
||||||
|
|||||||
+2
-2
@@ -423,7 +423,7 @@ ielr_item_has_lookahead (state *s, symbol_number lhs, size_t item,
|
|||||||
check all predecessors' goto follows for the LHS. */
|
check all predecessors' goto follows for the LHS. */
|
||||||
if (item_number_is_rule_number (ritem[s->items[item] - 2]))
|
if (item_number_is_rule_number (ritem[s->items[item] - 2]))
|
||||||
{
|
{
|
||||||
aver (lhs != accept->content->number);
|
aver (lhs != acceptsymbol->content->number);
|
||||||
for (state **predecessor = predecessors[s->number];
|
for (state **predecessor = predecessors[s->number];
|
||||||
*predecessor;
|
*predecessor;
|
||||||
++predecessor)
|
++predecessor)
|
||||||
@@ -1025,7 +1025,7 @@ ielr_split_states (bitsetv follow_kernel_items, bitsetv always_follows,
|
|||||||
{
|
{
|
||||||
rule *this_rule = node->state->reductions->rules[r];
|
rule *this_rule = node->state->reductions->rules[r];
|
||||||
bitset lookahead_set =
|
bitset lookahead_set =
|
||||||
node->state->reductions->lookahead_tokens[r];
|
node->state->reductions->lookaheads[r];
|
||||||
if (item_number_is_rule_number (*this_rule->rhs))
|
if (item_number_is_rule_number (*this_rule->rhs))
|
||||||
ielr_compute_goto_follow_set (follow_kernel_items,
|
ielr_compute_goto_follow_set (follow_kernel_items,
|
||||||
always_follows, node,
|
always_follows, node,
|
||||||
|
|||||||
+24
-27
@@ -256,9 +256,9 @@ lookback_find_state (int lookback_index)
|
|||||||
state *res = NULL;
|
state *res = NULL;
|
||||||
for (int j = 0; j < nstates; ++j)
|
for (int j = 0; j < nstates; ++j)
|
||||||
if (states[j]->reductions
|
if (states[j]->reductions
|
||||||
&& states[j]->reductions->lookahead_tokens)
|
&& states[j]->reductions->lookaheads)
|
||||||
{
|
{
|
||||||
if (states[j]->reductions->lookahead_tokens - LA > lookback_index)
|
if (states[j]->reductions->lookaheads - LA > lookback_index)
|
||||||
/* Went too far. */
|
/* Went too far. */
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
@@ -280,7 +280,7 @@ lookback_print (FILE *out)
|
|||||||
{
|
{
|
||||||
fprintf (out, " %3d = ", i);
|
fprintf (out, " %3d = ", i);
|
||||||
const state *s = lookback_find_state (i);
|
const state *s = lookback_find_state (i);
|
||||||
int rnum = i - (s->reductions->lookahead_tokens - LA);
|
int rnum = i - (s->reductions->lookaheads - LA);
|
||||||
const rule *r = s->reductions->rules[rnum];
|
const rule *r = s->reductions->rules[rnum];
|
||||||
fprintf (out, "(%3d, ", s->number);
|
fprintf (out, "(%3d, ", s->number);
|
||||||
rule_print (r, NULL, out);
|
rule_print (r, NULL, out);
|
||||||
@@ -305,7 +305,7 @@ static void
|
|||||||
add_lookback_edge (state *s, rule const *r, goto_number gotono)
|
add_lookback_edge (state *s, rule const *r, goto_number gotono)
|
||||||
{
|
{
|
||||||
int ri = state_reduction_find (s, r);
|
int ri = state_reduction_find (s, r);
|
||||||
int idx = (s->reductions->lookahead_tokens - LA) + ri;
|
int idx = (s->reductions->lookaheads - LA) + ri;
|
||||||
lookback[idx] = goto_list_new (gotono, lookback[idx]);
|
lookback[idx] = goto_list_new (gotono, lookback[idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,7 +421,7 @@ compute_follows (void)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
compute_lookahead_tokens (void)
|
compute_lookaheads (void)
|
||||||
{
|
{
|
||||||
if (trace_flag & trace_automaton)
|
if (trace_flag & trace_automaton)
|
||||||
lookback_print (stderr);
|
lookback_print (stderr);
|
||||||
@@ -437,13 +437,12 @@ compute_lookahead_tokens (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*----------------------------------------------------.
|
/*------------------------------------------------------.
|
||||||
| Count the number of lookahead tokens required for S |
|
| Count the number of lookahead tokens required for S. |
|
||||||
| (N_LOOKAHEAD_TOKENS member). |
|
`------------------------------------------------------*/
|
||||||
`----------------------------------------------------*/
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
state_lookahead_tokens_count (state *s, bool default_reduction_only_for_accept)
|
state_lookaheads_count (state *s, bool default_reduction_only_for_accept)
|
||||||
{
|
{
|
||||||
const reductions *reds = s->reductions;
|
const reductions *reds = s->reductions;
|
||||||
const transitions *trans = s->transitions;
|
const transitions *trans = s->transitions;
|
||||||
@@ -473,9 +472,9 @@ state_lookahead_tokens_count (state *s, bool default_reduction_only_for_accept)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*----------------------------------------------------.
|
/*----------------------------------------------.
|
||||||
| Compute LA, NLA, and the lookahead_tokens members. |
|
| Compute LA, NLA, and the lookaheads members. |
|
||||||
`----------------------------------------------------*/
|
`----------------------------------------------*/
|
||||||
|
|
||||||
void
|
void
|
||||||
initialize_LA (void)
|
initialize_LA (void)
|
||||||
@@ -491,25 +490,23 @@ initialize_LA (void)
|
|||||||
/* Compute the total number of reductions requiring a lookahead. */
|
/* Compute the total number of reductions requiring a lookahead. */
|
||||||
nLA = 0;
|
nLA = 0;
|
||||||
for (state_number i = 0; i < nstates; ++i)
|
for (state_number i = 0; i < nstates; ++i)
|
||||||
nLA +=
|
nLA += state_lookaheads_count (states[i],
|
||||||
state_lookahead_tokens_count (states[i],
|
default_reduction_only_for_accept);
|
||||||
default_reduction_only_for_accept);
|
|
||||||
/* Avoid having to special case 0. */
|
/* Avoid having to special case 0. */
|
||||||
if (!nLA)
|
if (!nLA)
|
||||||
nLA = 1;
|
nLA = 1;
|
||||||
|
|
||||||
bitsetv pLA = LA = bitsetv_create (nLA, ntokens, BITSET_FIXED);
|
bitsetv pLA = LA = bitsetv_create (nLA, ntokens, BITSET_FIXED);
|
||||||
|
|
||||||
/* Initialize the members LOOKAHEAD_TOKENS for each state whose reductions
|
/* Initialize the members LOOKAHEADS for each state whose reductions
|
||||||
require lookahead tokens. */
|
require lookahead tokens. */
|
||||||
for (state_number i = 0; i < nstates; ++i)
|
for (state_number i = 0; i < nstates; ++i)
|
||||||
{
|
{
|
||||||
int count =
|
int count = state_lookaheads_count (states[i],
|
||||||
state_lookahead_tokens_count (states[i],
|
default_reduction_only_for_accept);
|
||||||
default_reduction_only_for_accept);
|
|
||||||
if (count)
|
if (count)
|
||||||
{
|
{
|
||||||
states[i]->reductions->lookahead_tokens = pLA;
|
states[i]->reductions->lookaheads = pLA;
|
||||||
pLA += count;
|
pLA += count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -521,7 +518,7 @@ initialize_LA (void)
|
|||||||
`---------------------------------------------*/
|
`---------------------------------------------*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lookahead_tokens_print (FILE *out)
|
lookaheads_print (FILE *out)
|
||||||
{
|
{
|
||||||
fputs ("Lookaheads:\n", out);
|
fputs ("Lookaheads:\n", out);
|
||||||
for (state_number i = 0; i < nstates; ++i)
|
for (state_number i = 0; i < nstates; ++i)
|
||||||
@@ -533,11 +530,11 @@ lookahead_tokens_print (FILE *out)
|
|||||||
for (int j = 0; j < reds->num; ++j)
|
for (int j = 0; j < reds->num; ++j)
|
||||||
{
|
{
|
||||||
fprintf (out, " rule %d:", reds->rules[j]->number);
|
fprintf (out, " rule %d:", reds->rules[j]->number);
|
||||||
if (reds->lookahead_tokens)
|
if (reds->lookaheads)
|
||||||
{
|
{
|
||||||
bitset_iterator iter;
|
bitset_iterator iter;
|
||||||
int k;
|
int k;
|
||||||
BITSET_FOR_EACH (iter, reds->lookahead_tokens[j], k, 0)
|
BITSET_FOR_EACH (iter, reds->lookaheads[j], k, 0)
|
||||||
fprintf (out, " %s", symbols[k]->tag);
|
fprintf (out, " %s", symbols[k]->tag);
|
||||||
}
|
}
|
||||||
fputc ('\n', out);
|
fputc ('\n', out);
|
||||||
@@ -564,10 +561,10 @@ lalr (void)
|
|||||||
lookback = xcalloc (nLA, sizeof *lookback);
|
lookback = xcalloc (nLA, sizeof *lookback);
|
||||||
build_relations ();
|
build_relations ();
|
||||||
compute_follows ();
|
compute_follows ();
|
||||||
compute_lookahead_tokens ();
|
compute_lookaheads ();
|
||||||
|
|
||||||
if (trace_flag & trace_sets)
|
if (trace_flag & trace_sets)
|
||||||
lookahead_tokens_print (stderr);
|
lookaheads_print (stderr);
|
||||||
if (trace_flag & trace_automaton)
|
if (trace_flag & trace_automaton)
|
||||||
{
|
{
|
||||||
begin_use_class ("trace0", stderr);
|
begin_use_class ("trace0", stderr);
|
||||||
@@ -614,6 +611,6 @@ void
|
|||||||
lalr_free (void)
|
lalr_free (void)
|
||||||
{
|
{
|
||||||
for (state_number s = 0; s < nstates; ++s)
|
for (state_number s = 0; s < nstates; ++s)
|
||||||
states[s]->reductions->lookahead_tokens = NULL;
|
states[s]->reductions->lookaheads = NULL;
|
||||||
bitsetv_free (LA);
|
bitsetv_free (LA);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -53,6 +53,8 @@ src_bison_SOURCES = \
|
|||||||
src/flex-scanner.h \
|
src/flex-scanner.h \
|
||||||
src/getargs.c \
|
src/getargs.c \
|
||||||
src/getargs.h \
|
src/getargs.h \
|
||||||
|
src/glyphs.c \
|
||||||
|
src/glyphs.h \
|
||||||
src/gram.c \
|
src/gram.c \
|
||||||
src/gram.h \
|
src/gram.h \
|
||||||
src/graphviz.c \
|
src/graphviz.c \
|
||||||
@@ -101,6 +103,8 @@ src_bison_SOURCES = \
|
|||||||
src/state.h \
|
src/state.h \
|
||||||
src/state-item.c \
|
src/state-item.c \
|
||||||
src/state-item.h \
|
src/state-item.h \
|
||||||
|
src/strversion.c \
|
||||||
|
src/strversion.h \
|
||||||
src/symlist.c \
|
src/symlist.c \
|
||||||
src/symlist.h \
|
src/symlist.h \
|
||||||
src/symtab.c \
|
src/symtab.c \
|
||||||
@@ -141,7 +145,6 @@ src_bison_LDADD = \
|
|||||||
$(LIB_SETLOCALE_NULL) \
|
$(LIB_SETLOCALE_NULL) \
|
||||||
$(LIBICONV) \
|
$(LIBICONV) \
|
||||||
$(LIBINTL) \
|
$(LIBINTL) \
|
||||||
$(LIBREADLINE) \
|
|
||||||
$(LIBTEXTSTYLE)
|
$(LIBTEXTSTYLE)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+3
-13
@@ -40,18 +40,6 @@
|
|||||||
|
|
||||||
location const empty_loc = EMPTY_LOCATION_INIT;
|
location const empty_loc = EMPTY_LOCATION_INIT;
|
||||||
|
|
||||||
static int
|
|
||||||
min_int (int a, int b)
|
|
||||||
{
|
|
||||||
return a < b ? a : b;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
max_int (int a, int b)
|
|
||||||
{
|
|
||||||
return a >= b ? a : b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The terminal width. Not less than 40. */
|
/* The terminal width. Not less than 40. */
|
||||||
static int
|
static int
|
||||||
columns (void)
|
columns (void)
|
||||||
@@ -167,7 +155,9 @@ int
|
|||||||
location_print (location loc, FILE *out)
|
location_print (location loc, FILE *out)
|
||||||
{
|
{
|
||||||
int res = 0;
|
int res = 0;
|
||||||
if (trace_flag & trace_locations)
|
if (location_empty (loc))
|
||||||
|
res += fprintf (out, "(empty location)");
|
||||||
|
else if (trace_flag & trace_locations)
|
||||||
{
|
{
|
||||||
res += boundary_print (&loc.start, out);
|
res += boundary_print (&loc.start, out);
|
||||||
res += fprintf (out, "-");
|
res += fprintf (out, "-");
|
||||||
|
|||||||
+14
-12
@@ -82,8 +82,10 @@ lssi_comparator (lssi *s1, lssi *s2)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef gl_list_t lssi_list;
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
append_lssi (lssi *sn, Hash_table *visited, gl_list_t queue)
|
append_lssi (lssi *sn, Hash_table *visited, lssi_list queue)
|
||||||
{
|
{
|
||||||
if (hash_lookup (visited, sn))
|
if (hash_lookup (visited, sn))
|
||||||
{
|
{
|
||||||
@@ -100,7 +102,7 @@ append_lssi (lssi *sn, Hash_table *visited, gl_list_t queue)
|
|||||||
static void
|
static void
|
||||||
lssi_print (lssi *l)
|
lssi_print (lssi *l)
|
||||||
{
|
{
|
||||||
print_state_item (state_items + l->si, stdout);
|
print_state_item (&state_items[l->si], stdout);
|
||||||
if (l->lookahead)
|
if (l->lookahead)
|
||||||
{
|
{
|
||||||
printf ("FOLLOWL = { ");
|
printf ("FOLLOWL = { ");
|
||||||
@@ -121,7 +123,7 @@ static bitset
|
|||||||
eligible_state_items (state_item *target)
|
eligible_state_items (state_item *target)
|
||||||
{
|
{
|
||||||
bitset result = bitset_create (nstate_items, BITSET_FIXED);
|
bitset result = bitset_create (nstate_items, BITSET_FIXED);
|
||||||
gl_list_t queue =
|
state_item_list queue =
|
||||||
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1,
|
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1,
|
||||||
(const void **) &target);
|
(const void **) &target);
|
||||||
while (gl_list_size (queue) > 0)
|
while (gl_list_size (queue) > 0)
|
||||||
@@ -147,7 +149,7 @@ eligible_state_items (state_item *target)
|
|||||||
* this conflict. If optimized is true, only consider parser states
|
* this conflict. If optimized is true, only consider parser states
|
||||||
* that can reach the conflict state.
|
* that can reach the conflict state.
|
||||||
*/
|
*/
|
||||||
gl_list_t
|
state_item_list
|
||||||
shortest_path_from_start (state_item_number target, symbol_number next_sym)
|
shortest_path_from_start (state_item_number target, symbol_number next_sym)
|
||||||
{
|
{
|
||||||
bitset eligible = eligible_state_items (&state_items[target]);
|
bitset eligible = eligible_state_items (&state_items[target]);
|
||||||
@@ -159,7 +161,7 @@ shortest_path_from_start (state_item_number target, symbol_number next_sym)
|
|||||||
bitset il = bitset_create (nsyms, BITSET_FIXED);
|
bitset il = bitset_create (nsyms, BITSET_FIXED);
|
||||||
bitset_set (il, 0);
|
bitset_set (il, 0);
|
||||||
lssi *init = new_lssi (0, NULL, il, true);
|
lssi *init = new_lssi (0, NULL, il, true);
|
||||||
gl_list_t queue = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL,
|
lssi_list queue = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL,
|
||||||
NULL, true);
|
NULL, true);
|
||||||
append_lssi (init, visited, queue);
|
append_lssi (init, visited, queue);
|
||||||
// breadth-first search
|
// breadth-first search
|
||||||
@@ -175,7 +177,7 @@ shortest_path_from_start (state_item_number target, symbol_number next_sym)
|
|||||||
finished = true;
|
finished = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
state_item *si = state_items + last;
|
state_item *si = &state_items[last];
|
||||||
// Transitions don't change follow_L
|
// Transitions don't change follow_L
|
||||||
if (si->trans >= 0)
|
if (si->trans >= 0)
|
||||||
{
|
{
|
||||||
@@ -240,10 +242,10 @@ shortest_path_from_start (state_item_number target, symbol_number next_sym)
|
|||||||
fputs ("Cannot find shortest path to conflict state.", stderr);
|
fputs ("Cannot find shortest path to conflict state.", stderr);
|
||||||
abort ();
|
abort ();
|
||||||
}
|
}
|
||||||
gl_list_t res =
|
state_item_list res =
|
||||||
gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
|
gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
|
||||||
for (lssi *sn = n; sn != NULL; sn = sn->parent)
|
for (lssi *sn = n; sn != NULL; sn = sn->parent)
|
||||||
gl_list_add_first (res, state_items + sn->si);
|
gl_list_add_first (res, &state_items[sn->si]);
|
||||||
|
|
||||||
hash_free (visited);
|
hash_free (visited);
|
||||||
gl_list_free (queue);
|
gl_list_free (queue);
|
||||||
@@ -254,7 +256,7 @@ shortest_path_from_start (state_item_number target, symbol_number next_sym)
|
|||||||
gl_list_iterator_t it = gl_list_iterator (res);
|
gl_list_iterator_t it = gl_list_iterator (res);
|
||||||
const void *sip;
|
const void *sip;
|
||||||
while (gl_list_iterator_next (&it, &sip, NULL))
|
while (gl_list_iterator_next (&it, &sip, NULL))
|
||||||
print_state_item ((state_item *) sip, stdout, "");
|
state_item_print ((state_item *) sip, stdout, "");
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -306,10 +308,10 @@ intersect (bitset ts, bitset syms)
|
|||||||
* Compute a list of state_items that have a production to n with respect
|
* Compute a list of state_items that have a production to n with respect
|
||||||
* to its lookahead
|
* to its lookahead
|
||||||
*/
|
*/
|
||||||
gl_list_t
|
state_item_list
|
||||||
lssi_reverse_production (const state_item *si, bitset lookahead)
|
lssi_reverse_production (const state_item *si, bitset lookahead)
|
||||||
{
|
{
|
||||||
gl_list_t result =
|
state_item_list result =
|
||||||
gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
|
gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
|
||||||
if (SI_TRANSITION (si))
|
if (SI_TRANSITION (si))
|
||||||
return result;
|
return result;
|
||||||
@@ -320,7 +322,7 @@ lssi_reverse_production (const state_item *si, bitset lookahead)
|
|||||||
state_item_number sin;
|
state_item_number sin;
|
||||||
BITSET_FOR_EACH (biter, si->revs, sin, 0)
|
BITSET_FOR_EACH (biter, si->revs, sin, 0)
|
||||||
{
|
{
|
||||||
state_item *prevsi = state_items + sin;
|
state_item *prevsi = &state_items[sin];
|
||||||
if (!production_allowed (prevsi, si))
|
if (!production_allowed (prevsi, si))
|
||||||
continue;
|
continue;
|
||||||
bitset prev_lookahead = prevsi->lookahead;
|
bitset prev_lookahead = prevsi->lookahead;
|
||||||
|
|||||||
+3
-3
@@ -32,8 +32,8 @@
|
|||||||
* find shortest lookahead-sensitive path of state-items to target such that
|
* find shortest lookahead-sensitive path of state-items to target such that
|
||||||
* next_sym is in the follow_L set of target in that position.
|
* next_sym is in the follow_L set of target in that position.
|
||||||
*/
|
*/
|
||||||
gl_list_t shortest_path_from_start (state_item_number target,
|
state_item_list shortest_path_from_start (state_item_number target,
|
||||||
symbol_number next_sym);
|
symbol_number next_sym);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the given terminal is in the given symbol set or can begin
|
* Determine if the given terminal is in the given symbol set or can begin
|
||||||
@@ -52,6 +52,6 @@ bool intersect (bitset ts, bitset syms);
|
|||||||
* to this state-item such that the resulting possible lookahead symbols are
|
* to this state-item such that the resulting possible lookahead symbols are
|
||||||
* as given.
|
* as given.
|
||||||
*/
|
*/
|
||||||
gl_list_t lssi_reverse_production (const state_item *si, bitset lookahead);
|
state_item_list lssi_reverse_production (const state_item *si, bitset lookahead);
|
||||||
|
|
||||||
#endif /* LSSI_H */
|
#endif /* LSSI_H */
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "fixits.h"
|
#include "fixits.h"
|
||||||
#include "getargs.h"
|
#include "getargs.h"
|
||||||
|
#include "glyphs.h"
|
||||||
#include "gram.h"
|
#include "gram.h"
|
||||||
#include "ielr.h"
|
#include "ielr.h"
|
||||||
#include "lalr.h"
|
#include "lalr.h"
|
||||||
@@ -85,6 +86,7 @@ main (int argc, char *argv[])
|
|||||||
|
|
||||||
atexit (close_stdout);
|
atexit (close_stdout);
|
||||||
|
|
||||||
|
glyphs_init ();
|
||||||
uniqstrs_new ();
|
uniqstrs_new ();
|
||||||
muscle_init ();
|
muscle_init ();
|
||||||
complain_init ();
|
complain_init ();
|
||||||
|
|||||||
@@ -127,9 +127,6 @@ muscle_init (void)
|
|||||||
|
|
||||||
muscle_table = hash_xinitialize (HT_INITIAL_CAPACITY, NULL, hash_muscle,
|
muscle_table = hash_xinitialize (HT_INITIAL_CAPACITY, NULL, hash_muscle,
|
||||||
hash_compare_muscles, muscle_entry_free);
|
hash_compare_muscles, muscle_entry_free);
|
||||||
|
|
||||||
/* Version and input file. */
|
|
||||||
MUSCLE_INSERT_STRING ("version", VERSION);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+8
-4
@@ -42,6 +42,7 @@
|
|||||||
#include "scan-skel.h"
|
#include "scan-skel.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
#include "tables.h"
|
#include "tables.h"
|
||||||
|
#include "strversion.h"
|
||||||
|
|
||||||
static struct obstack format_obstack;
|
static struct obstack format_obstack;
|
||||||
|
|
||||||
@@ -249,7 +250,7 @@ prepare_symbol_names (char const *muscle_name)
|
|||||||
if (i)
|
if (i)
|
||||||
obstack_1grow (&format_obstack, ' ');
|
obstack_1grow (&format_obstack, ' ');
|
||||||
if (translatable)
|
if (translatable)
|
||||||
obstack_sgrow (&format_obstack, "]b4_symbol_translate([");
|
obstack_sgrow (&format_obstack, "]b4_symbol_translate""([");
|
||||||
obstack_escape (&format_obstack, cp);
|
obstack_escape (&format_obstack, cp);
|
||||||
if (translatable)
|
if (translatable)
|
||||||
obstack_sgrow (&format_obstack, "])[");
|
obstack_sgrow (&format_obstack, "])[");
|
||||||
@@ -554,7 +555,7 @@ prepare_symbol_definitions (void)
|
|||||||
/* Map "orig NUM" to new numbers. See data/README. */
|
/* Map "orig NUM" to new numbers. See data/README. */
|
||||||
for (symbol_number i = ntokens; i < nsyms + nuseless_nonterminals; ++i)
|
for (symbol_number i = ntokens; i < nsyms + nuseless_nonterminals; ++i)
|
||||||
{
|
{
|
||||||
obstack_printf (&format_obstack, "symbol(orig %d, number)", i);
|
obstack_printf (&format_obstack, "symbol""(orig %d, number)", i);
|
||||||
const char *key = obstack_finish0 (&format_obstack);
|
const char *key = obstack_finish0 (&format_obstack);
|
||||||
MUSCLE_INSERT_INT (key, nterm_map ? nterm_map[i - ntokens] : i);
|
MUSCLE_INSERT_INT (key, nterm_map ? nterm_map[i - ntokens] : i);
|
||||||
}
|
}
|
||||||
@@ -565,12 +566,12 @@ prepare_symbol_definitions (void)
|
|||||||
const char *key;
|
const char *key;
|
||||||
|
|
||||||
#define SET_KEY(Entry) \
|
#define SET_KEY(Entry) \
|
||||||
obstack_printf (&format_obstack, "symbol(%d, %s)", \
|
obstack_printf (&format_obstack, "symbol""(%d, %s)", \
|
||||||
i, Entry); \
|
i, Entry); \
|
||||||
key = obstack_finish0 (&format_obstack);
|
key = obstack_finish0 (&format_obstack);
|
||||||
|
|
||||||
#define SET_KEY2(Entry, Suffix) \
|
#define SET_KEY2(Entry, Suffix) \
|
||||||
obstack_printf (&format_obstack, "symbol(%d, %s_%s)", \
|
obstack_printf (&format_obstack, "symbol""(%d, %s_%s)", \
|
||||||
i, Entry, Suffix); \
|
i, Entry, Suffix); \
|
||||||
key = obstack_finish0 (&format_obstack);
|
key = obstack_finish0 (&format_obstack);
|
||||||
|
|
||||||
@@ -807,6 +808,9 @@ prepare (void)
|
|||||||
char const *cp = getenv ("BISON_USE_PUSH_FOR_PULL");
|
char const *cp = getenv ("BISON_USE_PUSH_FOR_PULL");
|
||||||
bool use_push_for_pull_flag = cp && *cp && strtol (cp, 0, 10);
|
bool use_push_for_pull_flag = cp && *cp && strtol (cp, 0, 10);
|
||||||
|
|
||||||
|
/* Versions. */
|
||||||
|
MUSCLE_INSERT_STRING ("version_string", VERSION);
|
||||||
|
MUSCLE_INSERT_INT ("version", strversion_to_int (VERSION));
|
||||||
MUSCLE_INSERT_INT ("required_version", required_version);
|
MUSCLE_INSERT_INT ("required_version", required_version);
|
||||||
|
|
||||||
/* Flags. */
|
/* Flags. */
|
||||||
|
|||||||
+45
-75
@@ -1,4 +1,4 @@
|
|||||||
/* A Bison parser, made by GNU Bison 3.6.4.130-76c4d. */
|
/* A Bison parser, made by GNU Bison 3.7.3.7-d831b. */
|
||||||
|
|
||||||
/* Bison implementation for Yacc-like parsers in C
|
/* Bison implementation for Yacc-like parsers in C
|
||||||
|
|
||||||
@@ -46,10 +46,10 @@
|
|||||||
USER NAME SPACE" below. */
|
USER NAME SPACE" below. */
|
||||||
|
|
||||||
/* Identify Bison output. */
|
/* Identify Bison output. */
|
||||||
#define YYBISON 1
|
#define YYBISON 30703
|
||||||
|
|
||||||
/* Bison version. */
|
/* Bison version. */
|
||||||
#define YYBISON_VERSION "3.6.4.130-76c4d"
|
#define YYBISON_VERSION "3.7.3.7-d831b"
|
||||||
|
|
||||||
/* Skeleton name. */
|
/* Skeleton name. */
|
||||||
#define YYSKELETON_NAME "yacc.c"
|
#define YYSKELETON_NAME "yacc.c"
|
||||||
@@ -149,7 +149,7 @@ enum yysymbol_kind_t
|
|||||||
YYSYMBOL_BRACED_CODE = 41, /* "{...}" */
|
YYSYMBOL_BRACED_CODE = 41, /* "{...}" */
|
||||||
YYSYMBOL_BRACED_PREDICATE = 42, /* "%?{...}" */
|
YYSYMBOL_BRACED_PREDICATE = 42, /* "%?{...}" */
|
||||||
YYSYMBOL_BRACKETED_ID = 43, /* "[identifier]" */
|
YYSYMBOL_BRACKETED_ID = 43, /* "[identifier]" */
|
||||||
YYSYMBOL_CHAR = 44, /* "character literal" */
|
YYSYMBOL_CHAR_LITERAL = 44, /* "character literal" */
|
||||||
YYSYMBOL_COLON = 45, /* ":" */
|
YYSYMBOL_COLON = 45, /* ":" */
|
||||||
YYSYMBOL_EPILOGUE = 46, /* "epilogue" */
|
YYSYMBOL_EPILOGUE = 46, /* "epilogue" */
|
||||||
YYSYMBOL_EQUAL = 47, /* "=" */
|
YYSYMBOL_EQUAL = 47, /* "=" */
|
||||||
@@ -162,7 +162,7 @@ enum yysymbol_kind_t
|
|||||||
YYSYMBOL_TAG = 54, /* "<tag>" */
|
YYSYMBOL_TAG = 54, /* "<tag>" */
|
||||||
YYSYMBOL_TAG_ANY = 55, /* "<*>" */
|
YYSYMBOL_TAG_ANY = 55, /* "<*>" */
|
||||||
YYSYMBOL_TAG_NONE = 56, /* "<>" */
|
YYSYMBOL_TAG_NONE = 56, /* "<>" */
|
||||||
YYSYMBOL_INT = 57, /* "integer literal" */
|
YYSYMBOL_INT_LITERAL = 57, /* "integer literal" */
|
||||||
YYSYMBOL_PERCENT_PARAM = 58, /* "%param" */
|
YYSYMBOL_PERCENT_PARAM = 58, /* "%param" */
|
||||||
YYSYMBOL_PERCENT_UNION = 59, /* "%union" */
|
YYSYMBOL_PERCENT_UNION = 59, /* "%union" */
|
||||||
YYSYMBOL_PERCENT_EMPTY = 60, /* "%empty" */
|
YYSYMBOL_PERCENT_EMPTY = 60, /* "%empty" */
|
||||||
@@ -218,8 +218,6 @@ typedef enum yysymbol_kind_t yysymbol_kind_t;
|
|||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
|
||||||
#include <c-ctype.h>
|
#include <c-ctype.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <intprops.h>
|
|
||||||
#include <quotearg.h>
|
#include <quotearg.h>
|
||||||
#include <vasnprintf.h>
|
#include <vasnprintf.h>
|
||||||
#include <xmemdup0.h>
|
#include <xmemdup0.h>
|
||||||
@@ -233,6 +231,11 @@ typedef enum yysymbol_kind_t yysymbol_kind_t;
|
|||||||
#include "reader.h"
|
#include "reader.h"
|
||||||
#include "scan-code.h"
|
#include "scan-code.h"
|
||||||
#include "scan-gram.h"
|
#include "scan-gram.h"
|
||||||
|
#include "strversion.h"
|
||||||
|
|
||||||
|
/* Pretend to be at least that version, to check features published
|
||||||
|
in that version while developping it. */
|
||||||
|
static const char* api_version = "3.7";
|
||||||
|
|
||||||
static int current_prec = 0;
|
static int current_prec = 0;
|
||||||
static location current_lhs_loc;
|
static location current_lhs_loc;
|
||||||
@@ -623,6 +626,7 @@ union yyalloc
|
|||||||
/* YYNSTATES -- Number of states. */
|
/* YYNSTATES -- Number of states. */
|
||||||
#define YYNSTATES 167
|
#define YYNSTATES 167
|
||||||
|
|
||||||
|
/* YYMAXUTOK -- Last valid token kind. */
|
||||||
#define YYMAXUTOK 315
|
#define YYMAXUTOK 315
|
||||||
|
|
||||||
|
|
||||||
@@ -634,19 +638,19 @@ union yyalloc
|
|||||||
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
|
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
|
||||||
static const yytype_int16 yyrline[] =
|
static const yytype_int16 yyrline[] =
|
||||||
{
|
{
|
||||||
0, 308, 308, 317, 318, 322, 323, 329, 333, 338,
|
0, 311, 311, 320, 321, 325, 326, 332, 336, 341,
|
||||||
339, 340, 341, 342, 343, 344, 349, 354, 355, 356,
|
342, 343, 344, 345, 346, 347, 352, 357, 358, 359,
|
||||||
357, 358, 359, 359, 360, 361, 362, 363, 364, 365,
|
360, 361, 362, 362, 363, 364, 365, 366, 367, 368,
|
||||||
366, 367, 371, 372, 381, 382, 386, 397, 401, 405,
|
369, 370, 374, 375, 384, 385, 389, 400, 404, 408,
|
||||||
413, 423, 424, 434, 435, 441, 454, 454, 459, 459,
|
416, 426, 427, 437, 438, 444, 457, 457, 462, 462,
|
||||||
464, 468, 478, 479, 480, 481, 485, 486, 491, 492,
|
467, 471, 481, 482, 483, 484, 488, 489, 494, 495,
|
||||||
496, 497, 501, 502, 503, 516, 525, 529, 533, 541,
|
499, 500, 504, 505, 506, 519, 528, 532, 536, 544,
|
||||||
542, 546, 559, 560, 565, 566, 567, 585, 589, 593,
|
545, 549, 562, 563, 568, 569, 570, 588, 592, 596,
|
||||||
601, 603, 608, 615, 625, 629, 633, 641, 646, 658,
|
604, 606, 611, 618, 628, 632, 636, 644, 649, 661,
|
||||||
659, 665, 666, 667, 674, 674, 682, 683, 684, 689,
|
662, 668, 669, 670, 677, 677, 685, 686, 687, 692,
|
||||||
692, 694, 696, 698, 700, 702, 704, 706, 708, 713,
|
695, 697, 699, 701, 703, 705, 707, 709, 711, 716,
|
||||||
714, 723, 747, 748, 749, 750, 762, 764, 788, 793,
|
717, 726, 750, 751, 752, 753, 765, 767, 791, 796,
|
||||||
794, 799, 807, 808
|
797, 802, 810, 811
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1110,8 +1114,8 @@ tron (yyo);
|
|||||||
{ fprintf (yyo, "[%s]", ((*yyvaluep).BRACKETED_ID)); }
|
{ fprintf (yyo, "[%s]", ((*yyvaluep).BRACKETED_ID)); }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case YYSYMBOL_CHAR: /* "character literal" */
|
case YYSYMBOL_CHAR_LITERAL: /* "character literal" */
|
||||||
{ fputs (char_name (((*yyvaluep).CHAR)), yyo); }
|
{ fputs (char_name (((*yyvaluep).CHAR_LITERAL)), yyo); }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case YYSYMBOL_EPILOGUE: /* "epilogue" */
|
case YYSYMBOL_EPILOGUE: /* "epilogue" */
|
||||||
@@ -1134,8 +1138,8 @@ tron (yyo);
|
|||||||
{ fprintf (yyo, "<%s>", ((*yyvaluep).TAG)); }
|
{ fprintf (yyo, "<%s>", ((*yyvaluep).TAG)); }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case YYSYMBOL_INT: /* "integer literal" */
|
case YYSYMBOL_INT_LITERAL: /* "integer literal" */
|
||||||
{ fprintf (yyo, "%d", ((*yyvaluep).INT)); }
|
{ fprintf (yyo, "%d", ((*yyvaluep).INT_LITERAL)); }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case YYSYMBOL_PERCENT_PARAM: /* "%param" */
|
case YYSYMBOL_PERCENT_PARAM: /* "%param" */
|
||||||
@@ -1748,7 +1752,7 @@ yydestruct (const char *yymsg,
|
|||||||
int
|
int
|
||||||
yyparse (void)
|
yyparse (void)
|
||||||
{
|
{
|
||||||
/* The lookahead symbol. */
|
/* Lookahead token kind. */
|
||||||
int yychar;
|
int yychar;
|
||||||
|
|
||||||
|
|
||||||
@@ -1803,7 +1807,7 @@ YYLTYPE yylloc = yyloc_default;
|
|||||||
int yyn;
|
int yyn;
|
||||||
/* The return value of yyparse. */
|
/* The return value of yyparse. */
|
||||||
int yyresult;
|
int yyresult;
|
||||||
/* Lookahead token as an internal (translated) token number. */
|
/* Lookahead symbol kind. */
|
||||||
yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY;
|
yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY;
|
||||||
/* The variables used to return semantic value and location from the
|
/* The variables used to return semantic value and location from the
|
||||||
action routines. */
|
action routines. */
|
||||||
@@ -2082,11 +2086,11 @@ yyreduce:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 12: /* prologue_declaration: "%expect" "integer literal" */
|
case 12: /* prologue_declaration: "%expect" "integer literal" */
|
||||||
{ expected_sr_conflicts = (yyvsp[0].INT); }
|
{ expected_sr_conflicts = (yyvsp[0].INT_LITERAL); }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 13: /* prologue_declaration: "%expect-rr" "integer literal" */
|
case 13: /* prologue_declaration: "%expect-rr" "integer literal" */
|
||||||
{ expected_rr_conflicts = (yyvsp[0].INT); }
|
{ expected_rr_conflicts = (yyvsp[0].INT_LITERAL); }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 14: /* prologue_declaration: "%file-prefix" "string" */
|
case 14: /* prologue_declaration: "%file-prefix" "string" */
|
||||||
@@ -2334,13 +2338,13 @@ yyreduce:
|
|||||||
|
|
||||||
case 67: /* token_decls: "<tag>" token_decl.1 */
|
case 67: /* token_decls: "<tag>" token_decl.1 */
|
||||||
{
|
{
|
||||||
(yyval.token_decls) = symbol_list_type_set ((yyvsp[0].yykind_80), (yyvsp[-1].TAG), (yylsp[-1]));
|
(yyval.token_decls) = symbol_list_type_set ((yyvsp[0].yykind_80), (yyvsp[-1].TAG));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 68: /* token_decls: token_decls "<tag>" token_decl.1 */
|
case 68: /* token_decls: token_decls "<tag>" token_decl.1 */
|
||||||
{
|
{
|
||||||
(yyval.token_decls) = symbol_list_append ((yyvsp[-2].token_decls), symbol_list_type_set ((yyvsp[0].yykind_80), (yyvsp[-1].TAG), (yylsp[-1])));
|
(yyval.token_decls) = symbol_list_append ((yyvsp[-2].token_decls), symbol_list_type_set ((yyvsp[0].yykind_80), (yyvsp[-1].TAG)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -2391,13 +2395,13 @@ yyreduce:
|
|||||||
|
|
||||||
case 78: /* token_decls_for_prec: "<tag>" token_decl_for_prec.1 */
|
case 78: /* token_decls_for_prec: "<tag>" token_decl_for_prec.1 */
|
||||||
{
|
{
|
||||||
(yyval.token_decls_for_prec) = symbol_list_type_set ((yyvsp[0].yykind_85), (yyvsp[-1].TAG), (yylsp[-1]));
|
(yyval.token_decls_for_prec) = symbol_list_type_set ((yyvsp[0].yykind_85), (yyvsp[-1].TAG));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 79: /* token_decls_for_prec: token_decls_for_prec "<tag>" token_decl_for_prec.1 */
|
case 79: /* token_decls_for_prec: token_decls_for_prec "<tag>" token_decl_for_prec.1 */
|
||||||
{
|
{
|
||||||
(yyval.token_decls_for_prec) = symbol_list_append ((yyvsp[-2].token_decls_for_prec), symbol_list_type_set ((yyvsp[0].yykind_85), (yyvsp[-1].TAG), (yylsp[-1])));
|
(yyval.token_decls_for_prec) = symbol_list_append ((yyvsp[-2].token_decls_for_prec), symbol_list_type_set ((yyvsp[0].yykind_85), (yyvsp[-1].TAG)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -2426,13 +2430,13 @@ yyreduce:
|
|||||||
|
|
||||||
case 85: /* symbol_decls: "<tag>" symbol_decl.1 */
|
case 85: /* symbol_decls: "<tag>" symbol_decl.1 */
|
||||||
{
|
{
|
||||||
(yyval.symbol_decls) = symbol_list_type_set ((yyvsp[0].yykind_88), (yyvsp[-1].TAG), (yylsp[-1]));
|
(yyval.symbol_decls) = symbol_list_type_set ((yyvsp[0].yykind_88), (yyvsp[-1].TAG));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 86: /* symbol_decls: symbol_decls "<tag>" symbol_decl.1 */
|
case 86: /* symbol_decls: symbol_decls "<tag>" symbol_decl.1 */
|
||||||
{
|
{
|
||||||
(yyval.symbol_decls) = symbol_list_append ((yyvsp[-2].symbol_decls), symbol_list_type_set ((yyvsp[0].yykind_88), (yyvsp[-1].TAG), (yylsp[-1])));
|
(yyval.symbol_decls) = symbol_list_append ((yyvsp[-2].symbol_decls), symbol_list_type_set ((yyvsp[0].yykind_88), (yyvsp[-1].TAG)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -2501,7 +2505,7 @@ yyreduce:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 105: /* rhs: rhs "%dprec" "integer literal" */
|
case 105: /* rhs: rhs "%dprec" "integer literal" */
|
||||||
{ grammar_current_rule_dprec_set ((yyvsp[0].INT), (yylsp[0])); }
|
{ grammar_current_rule_dprec_set ((yyvsp[0].INT_LITERAL), (yylsp[0])); }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 106: /* rhs: rhs "%merge" "<tag>" */
|
case 106: /* rhs: rhs "%merge" "<tag>" */
|
||||||
@@ -2509,11 +2513,11 @@ yyreduce:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 107: /* rhs: rhs "%expect" "integer literal" */
|
case 107: /* rhs: rhs "%expect" "integer literal" */
|
||||||
{ grammar_current_rule_expect_sr ((yyvsp[0].INT), (yylsp[0])); }
|
{ grammar_current_rule_expect_sr ((yyvsp[0].INT_LITERAL), (yylsp[0])); }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 108: /* rhs: rhs "%expect-rr" "integer literal" */
|
case 108: /* rhs: rhs "%expect-rr" "integer literal" */
|
||||||
{ grammar_current_rule_expect_rr ((yyvsp[0].INT), (yylsp[0])); }
|
{ grammar_current_rule_expect_rr ((yyvsp[0].INT_LITERAL), (yylsp[0])); }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 109: /* named_ref.opt: %empty */
|
case 109: /* named_ref.opt: %empty */
|
||||||
@@ -2561,9 +2565,9 @@ yyreduce:
|
|||||||
location loc = muscle_percent_define_get_loc (var);
|
location loc = muscle_percent_define_get_loc (var);
|
||||||
subcomplain (&loc, complaint, _("definition of %s"), var);
|
subcomplain (&loc, complaint, _("definition of %s"), var);
|
||||||
}
|
}
|
||||||
(yyval.id) = symbol_get (char_name ((yyvsp[0].CHAR)), (yylsp[0]));
|
(yyval.id) = symbol_get (char_name ((yyvsp[0].CHAR_LITERAL)), (yylsp[0]));
|
||||||
symbol_class_set ((yyval.id), token_sym, (yylsp[0]), false);
|
symbol_class_set ((yyval.id), token_sym, (yylsp[0]), false);
|
||||||
symbol_code_set ((yyval.id), (yyvsp[0].CHAR), (yylsp[0]));
|
symbol_code_set ((yyval.id), (yyvsp[0].CHAR_LITERAL), (yylsp[0]));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -3027,41 +3031,11 @@ handle_pure_parser (location const *loc, char const *directive)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Convert VERSION into an int (MAJOR * 100 + MINOR). Return -1 on
|
|
||||||
errors.
|
|
||||||
|
|
||||||
Changes of behavior are only on minor version changes, so "3.0.5"
|
|
||||||
is the same as "3.0": 300. */
|
|
||||||
static int
|
|
||||||
str_to_version (char const *version)
|
|
||||||
{
|
|
||||||
IGNORE_TYPE_LIMITS_BEGIN
|
|
||||||
int res = 0;
|
|
||||||
errno = 0;
|
|
||||||
char *cp = NULL;
|
|
||||||
long major = strtol (version, &cp, 10);
|
|
||||||
if (errno || cp == version || *cp != '.' || major < 0
|
|
||||||
|| INT_MULTIPLY_WRAPV (major, 100, &res))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
++cp;
|
|
||||||
char *cp1 = NULL;
|
|
||||||
long minor = strtol (cp, &cp1, 10);
|
|
||||||
if (errno || cp1 == cp || (*cp1 != '\0' && *cp1 != '.')
|
|
||||||
|| ! (0 <= minor && minor < 100)
|
|
||||||
|| INT_ADD_WRAPV (minor, res, &res))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
IGNORE_TYPE_LIMITS_END
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_require (location const *loc, char const *version_quoted)
|
handle_require (location const *loc, char const *version_quoted)
|
||||||
{
|
{
|
||||||
char *version = unquote (version_quoted);
|
char *version = unquote (version_quoted);
|
||||||
required_version = str_to_version (version);
|
required_version = strversion_to_int (version);
|
||||||
if (required_version == -1)
|
if (required_version == -1)
|
||||||
{
|
{
|
||||||
complain (loc, complaint, _("invalid version requirement: %s"),
|
complain (loc, complaint, _("invalid version requirement: %s"),
|
||||||
@@ -3070,9 +3044,6 @@ handle_require (location const *loc, char const *version_quoted)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Pretend to be at least that version, to check features published
|
|
||||||
in that version while developping it. */
|
|
||||||
const char* api_version = "3.6";
|
|
||||||
const char* package_version =
|
const char* package_version =
|
||||||
0 < strverscmp (api_version, PACKAGE_VERSION)
|
0 < strverscmp (api_version, PACKAGE_VERSION)
|
||||||
? api_version : PACKAGE_VERSION;
|
? api_version : PACKAGE_VERSION;
|
||||||
@@ -3145,8 +3116,7 @@ char_name (char c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static void
|
||||||
void
|
|
||||||
current_lhs (symbol *sym, location loc, named_ref *ref)
|
current_lhs (symbol *sym, location loc, named_ref *ref)
|
||||||
{
|
{
|
||||||
current_lhs_symbol = sym;
|
current_lhs_symbol = sym;
|
||||||
|
|||||||
+5
-5
@@ -1,4 +1,4 @@
|
|||||||
/* A Bison parser, made by GNU Bison 3.6.4.130-76c4d. */
|
/* A Bison parser, made by GNU Bison 3.7.3.7-d831b. */
|
||||||
|
|
||||||
/* Bison interface for Yacc-like parsers in C
|
/* Bison interface for Yacc-like parsers in C
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ extern int gram_debug;
|
|||||||
BRACED_CODE = 41, /* "{...}" */
|
BRACED_CODE = 41, /* "{...}" */
|
||||||
BRACED_PREDICATE = 42, /* "%?{...}" */
|
BRACED_PREDICATE = 42, /* "%?{...}" */
|
||||||
BRACKETED_ID = 43, /* "[identifier]" */
|
BRACKETED_ID = 43, /* "[identifier]" */
|
||||||
CHAR = 44, /* "character literal" */
|
CHAR_LITERAL = 44, /* "character literal" */
|
||||||
COLON = 45, /* ":" */
|
COLON = 45, /* ":" */
|
||||||
EPILOGUE = 46, /* "epilogue" */
|
EPILOGUE = 46, /* "epilogue" */
|
||||||
EQUAL = 47, /* "=" */
|
EQUAL = 47, /* "=" */
|
||||||
@@ -136,7 +136,7 @@ extern int gram_debug;
|
|||||||
TAG = 54, /* "<tag>" */
|
TAG = 54, /* "<tag>" */
|
||||||
TAG_ANY = 55, /* "<*>" */
|
TAG_ANY = 55, /* "<*>" */
|
||||||
TAG_NONE = 56, /* "<>" */
|
TAG_NONE = 56, /* "<>" */
|
||||||
INT = 57, /* "integer literal" */
|
INT_LITERAL = 57, /* "integer literal" */
|
||||||
PERCENT_PARAM = 58, /* "%param" */
|
PERCENT_PARAM = 58, /* "%param" */
|
||||||
PERCENT_UNION = 59, /* "%union" */
|
PERCENT_UNION = 59, /* "%union" */
|
||||||
PERCENT_EMPTY = 60 /* "%empty" */
|
PERCENT_EMPTY = 60 /* "%empty" */
|
||||||
@@ -156,7 +156,7 @@ union GRAM_STYPE
|
|||||||
char* EPILOGUE; /* "epilogue" */
|
char* EPILOGUE; /* "epilogue" */
|
||||||
char* PROLOGUE; /* "%{...%}" */
|
char* PROLOGUE; /* "%{...%}" */
|
||||||
code_props_type code_props_type; /* code_props_type */
|
code_props_type code_props_type; /* code_props_type */
|
||||||
int INT; /* "integer literal" */
|
int INT_LITERAL; /* "integer literal" */
|
||||||
int yykind_82; /* int.opt */
|
int yykind_82; /* int.opt */
|
||||||
named_ref* yykind_95; /* named_ref.opt */
|
named_ref* yykind_95; /* named_ref.opt */
|
||||||
param_type PERCENT_PARAM; /* "%param" */
|
param_type PERCENT_PARAM; /* "%param" */
|
||||||
@@ -188,7 +188,7 @@ union GRAM_STYPE
|
|||||||
uniqstr yykind_74; /* tag.opt */
|
uniqstr yykind_74; /* tag.opt */
|
||||||
uniqstr tag; /* tag */
|
uniqstr tag; /* tag */
|
||||||
uniqstr variable; /* variable */
|
uniqstr variable; /* variable */
|
||||||
unsigned char CHAR; /* "character literal" */
|
unsigned char CHAR_LITERAL; /* "character literal" */
|
||||||
value_type value; /* value */
|
value_type value; /* value */
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+25
-56
@@ -42,8 +42,6 @@
|
|||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
|
||||||
#include <c-ctype.h>
|
#include <c-ctype.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <intprops.h>
|
|
||||||
#include <quotearg.h>
|
#include <quotearg.h>
|
||||||
#include <vasnprintf.h>
|
#include <vasnprintf.h>
|
||||||
#include <xmemdup0.h>
|
#include <xmemdup0.h>
|
||||||
@@ -57,6 +55,11 @@
|
|||||||
#include "reader.h"
|
#include "reader.h"
|
||||||
#include "scan-code.h"
|
#include "scan-code.h"
|
||||||
#include "scan-gram.h"
|
#include "scan-gram.h"
|
||||||
|
#include "strversion.h"
|
||||||
|
|
||||||
|
/* Pretend to be at least that version, to check features published
|
||||||
|
in that version while developping it. */
|
||||||
|
static const char* api_version = "3.7";
|
||||||
|
|
||||||
static int current_prec = 0;
|
static int current_prec = 0;
|
||||||
static location current_lhs_loc;
|
static location current_lhs_loc;
|
||||||
@@ -210,7 +213,7 @@
|
|||||||
BRACED_CODE "{...}"
|
BRACED_CODE "{...}"
|
||||||
BRACED_PREDICATE "%?{...}"
|
BRACED_PREDICATE "%?{...}"
|
||||||
BRACKETED_ID _("[identifier]")
|
BRACKETED_ID _("[identifier]")
|
||||||
CHAR _("character literal")
|
CHAR_LITERAL _("character literal")
|
||||||
COLON ":"
|
COLON ":"
|
||||||
EPILOGUE _("epilogue")
|
EPILOGUE _("epilogue")
|
||||||
EQUAL "="
|
EQUAL "="
|
||||||
@@ -228,7 +231,7 @@
|
|||||||
%code pre-printer {tron (yyo);}
|
%code pre-printer {tron (yyo);}
|
||||||
%code post-printer {troff (yyo);}
|
%code post-printer {troff (yyo);}
|
||||||
|
|
||||||
%type <unsigned char> CHAR
|
%type <unsigned char> CHAR_LITERAL
|
||||||
%printer { fputs (char_name ($$), yyo); } <unsigned char>
|
%printer { fputs (char_name ($$), yyo); } <unsigned char>
|
||||||
|
|
||||||
%type <char*> "{...}" "%?{...}" "%{...%}" EPILOGUE STRING TSTRING
|
%type <char*> "{...}" "%?{...}" "%{...%}" EPILOGUE STRING TSTRING
|
||||||
@@ -245,7 +248,7 @@
|
|||||||
%printer { fprintf (yyo, "%%%s", $$); } PERCENT_FLAG
|
%printer { fprintf (yyo, "%%%s", $$); } PERCENT_FLAG
|
||||||
%printer { fprintf (yyo, "<%s>", $$); } TAG tag
|
%printer { fprintf (yyo, "<%s>", $$); } TAG tag
|
||||||
|
|
||||||
%token <int> INT _("integer literal")
|
%token <int> INT_LITERAL _("integer literal")
|
||||||
%printer { fprintf (yyo, "%d", $$); } <int>
|
%printer { fprintf (yyo, "%d", $$); } <int>
|
||||||
|
|
||||||
%type <symbol*> id id_colon string_as_id symbol token_decl token_decl_for_prec
|
%type <symbol*> id id_colon string_as_id symbol token_decl token_decl_for_prec
|
||||||
@@ -338,8 +341,8 @@ prologue_declaration:
|
|||||||
| "%defines" { defines_flag = true; }
|
| "%defines" { defines_flag = true; }
|
||||||
| "%defines" STRING { handle_defines ($2); }
|
| "%defines" STRING { handle_defines ($2); }
|
||||||
| "%error-verbose" { handle_error_verbose (&@$, $1); }
|
| "%error-verbose" { handle_error_verbose (&@$, $1); }
|
||||||
| "%expect" INT { expected_sr_conflicts = $2; }
|
| "%expect" INT_LITERAL { expected_sr_conflicts = $2; }
|
||||||
| "%expect-rr" INT { expected_rr_conflicts = $2; }
|
| "%expect-rr" INT_LITERAL { expected_rr_conflicts = $2; }
|
||||||
| "%file-prefix" STRING { handle_file_prefix (&@$, &@1, $1, $2); }
|
| "%file-prefix" STRING { handle_file_prefix (&@$, &@1, $1, $2); }
|
||||||
| "%glr-parser"
|
| "%glr-parser"
|
||||||
{
|
{
|
||||||
@@ -528,11 +531,11 @@ token_decls:
|
|||||||
}
|
}
|
||||||
| TAG token_decl.1[syms]
|
| TAG token_decl.1[syms]
|
||||||
{
|
{
|
||||||
$$ = symbol_list_type_set ($syms, $TAG, @TAG);
|
$$ = symbol_list_type_set ($syms, $TAG);
|
||||||
}
|
}
|
||||||
| token_decls TAG token_decl.1[syms]
|
| token_decls TAG token_decl.1[syms]
|
||||||
{
|
{
|
||||||
$$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG, @TAG));
|
$$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG));
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -557,7 +560,7 @@ token_decl:
|
|||||||
%type <int> int.opt;
|
%type <int> int.opt;
|
||||||
int.opt:
|
int.opt:
|
||||||
%empty { $$ = -1; }
|
%empty { $$ = -1; }
|
||||||
| INT
|
| INT_LITERAL
|
||||||
;
|
;
|
||||||
|
|
||||||
%type <symbol*> alias;
|
%type <symbol*> alias;
|
||||||
@@ -588,11 +591,11 @@ token_decls_for_prec:
|
|||||||
}
|
}
|
||||||
| TAG token_decl_for_prec.1[syms]
|
| TAG token_decl_for_prec.1[syms]
|
||||||
{
|
{
|
||||||
$$ = symbol_list_type_set ($syms, $TAG, @TAG);
|
$$ = symbol_list_type_set ($syms, $TAG);
|
||||||
}
|
}
|
||||||
| token_decls_for_prec TAG token_decl_for_prec.1[syms]
|
| token_decls_for_prec TAG token_decl_for_prec.1[syms]
|
||||||
{
|
{
|
||||||
$$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG, @TAG));
|
$$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG));
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -628,11 +631,11 @@ symbol_decls:
|
|||||||
}
|
}
|
||||||
| TAG symbol_decl.1[syms]
|
| TAG symbol_decl.1[syms]
|
||||||
{
|
{
|
||||||
$$ = symbol_list_type_set ($syms, $TAG, @TAG);
|
$$ = symbol_list_type_set ($syms, $TAG);
|
||||||
}
|
}
|
||||||
| symbol_decls TAG symbol_decl.1[syms]
|
| symbol_decls TAG symbol_decl.1[syms]
|
||||||
{
|
{
|
||||||
$$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG, @TAG));
|
$$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG));
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -691,21 +694,21 @@ rhs:
|
|||||||
current_lhs_named_ref); }
|
current_lhs_named_ref); }
|
||||||
| rhs symbol named_ref.opt
|
| rhs symbol named_ref.opt
|
||||||
{ grammar_current_rule_symbol_append ($2, @2, $3); }
|
{ grammar_current_rule_symbol_append ($2, @2, $3); }
|
||||||
| rhs tag.opt "{...}"[act] named_ref.opt[name]
|
| rhs tag.opt "{...}"[action] named_ref.opt[name]
|
||||||
{ grammar_current_rule_action_append ($act, @act, $name, $[tag.opt]); }
|
{ grammar_current_rule_action_append ($action, @action, $name, $[tag.opt]); }
|
||||||
| rhs "%?{...}"
|
| rhs "%?{...}"
|
||||||
{ grammar_current_rule_predicate_append ($2, @2); }
|
{ grammar_current_rule_predicate_append ($2, @2); }
|
||||||
| rhs "%empty"
|
| rhs "%empty"
|
||||||
{ grammar_current_rule_empty_set (@2); }
|
{ grammar_current_rule_empty_set (@2); }
|
||||||
| rhs "%prec" symbol
|
| rhs "%prec" symbol
|
||||||
{ grammar_current_rule_prec_set ($3, @3); }
|
{ grammar_current_rule_prec_set ($3, @3); }
|
||||||
| rhs "%dprec" INT
|
| rhs "%dprec" INT_LITERAL
|
||||||
{ grammar_current_rule_dprec_set ($3, @3); }
|
{ grammar_current_rule_dprec_set ($3, @3); }
|
||||||
| rhs "%merge" TAG
|
| rhs "%merge" TAG
|
||||||
{ grammar_current_rule_merge_set ($3, @3); }
|
{ grammar_current_rule_merge_set ($3, @3); }
|
||||||
| rhs "%expect" INT
|
| rhs "%expect" INT_LITERAL
|
||||||
{ grammar_current_rule_expect_sr ($3, @3); }
|
{ grammar_current_rule_expect_sr ($3, @3); }
|
||||||
| rhs "%expect-rr" INT
|
| rhs "%expect-rr" INT_LITERAL
|
||||||
{ grammar_current_rule_expect_rr ($3, @3); }
|
{ grammar_current_rule_expect_rr ($3, @3); }
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -761,7 +764,7 @@ value:
|
|||||||
id:
|
id:
|
||||||
ID
|
ID
|
||||||
{ $$ = symbol_from_uniqstr ($1, @1); }
|
{ $$ = symbol_from_uniqstr ($1, @1); }
|
||||||
| CHAR
|
| CHAR_LITERAL
|
||||||
{
|
{
|
||||||
const char *var = "api.token.raw";
|
const char *var = "api.token.raw";
|
||||||
if (current_class == nterm_sym)
|
if (current_class == nterm_sym)
|
||||||
@@ -1039,41 +1042,11 @@ handle_pure_parser (location const *loc, char const *directive)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Convert VERSION into an int (MAJOR * 100 + MINOR). Return -1 on
|
|
||||||
errors.
|
|
||||||
|
|
||||||
Changes of behavior are only on minor version changes, so "3.0.5"
|
|
||||||
is the same as "3.0": 300. */
|
|
||||||
static int
|
|
||||||
str_to_version (char const *version)
|
|
||||||
{
|
|
||||||
IGNORE_TYPE_LIMITS_BEGIN
|
|
||||||
int res = 0;
|
|
||||||
errno = 0;
|
|
||||||
char *cp = NULL;
|
|
||||||
long major = strtol (version, &cp, 10);
|
|
||||||
if (errno || cp == version || *cp != '.' || major < 0
|
|
||||||
|| INT_MULTIPLY_WRAPV (major, 100, &res))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
++cp;
|
|
||||||
char *cp1 = NULL;
|
|
||||||
long minor = strtol (cp, &cp1, 10);
|
|
||||||
if (errno || cp1 == cp || (*cp1 != '\0' && *cp1 != '.')
|
|
||||||
|| ! (0 <= minor && minor < 100)
|
|
||||||
|| INT_ADD_WRAPV (minor, res, &res))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
IGNORE_TYPE_LIMITS_END
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_require (location const *loc, char const *version_quoted)
|
handle_require (location const *loc, char const *version_quoted)
|
||||||
{
|
{
|
||||||
char *version = unquote (version_quoted);
|
char *version = unquote (version_quoted);
|
||||||
required_version = str_to_version (version);
|
required_version = strversion_to_int (version);
|
||||||
if (required_version == -1)
|
if (required_version == -1)
|
||||||
{
|
{
|
||||||
complain (loc, complaint, _("invalid version requirement: %s"),
|
complain (loc, complaint, _("invalid version requirement: %s"),
|
||||||
@@ -1082,9 +1055,6 @@ handle_require (location const *loc, char const *version_quoted)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Pretend to be at least that version, to check features published
|
|
||||||
in that version while developping it. */
|
|
||||||
const char* api_version = "3.6";
|
|
||||||
const char* package_version =
|
const char* package_version =
|
||||||
0 < strverscmp (api_version, PACKAGE_VERSION)
|
0 < strverscmp (api_version, PACKAGE_VERSION)
|
||||||
? api_version : PACKAGE_VERSION;
|
? api_version : PACKAGE_VERSION;
|
||||||
@@ -1157,8 +1127,7 @@ char_name (char c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static void
|
||||||
void
|
|
||||||
current_lhs (symbol *sym, location loc, named_ref *ref)
|
current_lhs (symbol *sym, location loc, named_ref *ref)
|
||||||
{
|
{
|
||||||
current_lhs_symbol = sym;
|
current_lhs_symbol = sym;
|
||||||
|
|||||||
+47
-53
@@ -28,19 +28,19 @@
|
|||||||
#include "lssi.h"
|
#include "lssi.h"
|
||||||
#include "nullable.h"
|
#include "nullable.h"
|
||||||
|
|
||||||
typedef struct parse_state
|
struct parse_state
|
||||||
{
|
{
|
||||||
// path of state-items the parser has traversed
|
// Path of state-items the parser has traversed.
|
||||||
struct si_chunk
|
struct si_chunk
|
||||||
{
|
{
|
||||||
// elements newly added in this chunk
|
// Elements newly added in this chunk.
|
||||||
gl_list_t contents;
|
state_item_list contents;
|
||||||
// properties of the linked list this chunk represents
|
// Properties of the linked list this chunk represents.
|
||||||
const state_item *head_elt;
|
const state_item *head_elt;
|
||||||
const state_item *tail_elt;
|
const state_item *tail_elt;
|
||||||
size_t total_size;
|
size_t total_size;
|
||||||
} state_items;
|
} state_items;
|
||||||
// list of derivations of the symbols
|
// List of derivations of the symbols.
|
||||||
struct deriv_chunk
|
struct deriv_chunk
|
||||||
{
|
{
|
||||||
derivation_list contents;
|
derivation_list contents;
|
||||||
@@ -50,18 +50,15 @@ typedef struct parse_state
|
|||||||
} derivs;
|
} derivs;
|
||||||
struct parse_state *parent;
|
struct parse_state *parent;
|
||||||
int reference_count;
|
int reference_count;
|
||||||
// incremented during productions,
|
// Incremented during productions, decremented during reductions.
|
||||||
// decremented during reductions
|
|
||||||
int depth;
|
int depth;
|
||||||
// whether the contents of the chunks should be
|
// Whether the contents of the chunks should be prepended or
|
||||||
// prepended or appended to the list the chunks
|
// appended to the list the chunks represent.
|
||||||
// represent
|
|
||||||
bool prepend;
|
bool prepend;
|
||||||
// causes chunk contents to be freed when the
|
// Causes chunk contents to be freed when the reference count is
|
||||||
// reference count is one. Used when only the chunk metadata
|
// one. Used when only the chunk metadata will be needed.
|
||||||
// will be needed.
|
|
||||||
bool free_contents_early;
|
bool free_contents_early;
|
||||||
} parse_state;
|
};
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -135,7 +132,7 @@ static parse_state *
|
|||||||
copy_parse_state (bool prepend, parse_state *parent)
|
copy_parse_state (bool prepend, parse_state *parent)
|
||||||
{
|
{
|
||||||
parse_state *res = xmalloc (sizeof *res);
|
parse_state *res = xmalloc (sizeof *res);
|
||||||
memcpy (res, parent, sizeof *res);
|
*res = *parent;
|
||||||
res->state_items.contents
|
res->state_items.contents
|
||||||
= gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
|
= gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
|
||||||
res->derivs.contents = derivation_list_new ();
|
res->derivs.contents = derivation_list_new ();
|
||||||
@@ -252,7 +249,7 @@ parse_state_completed_steps (const parse_state *ps, int *shifts, int *production
|
|||||||
while (root_ps->parent)
|
while (root_ps->parent)
|
||||||
root_ps = root_ps->parent;
|
root_ps = root_ps->parent;
|
||||||
|
|
||||||
gl_list_t sis = root_ps->state_items.contents;
|
state_item_list sis = root_ps->state_items.contents;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
state_item *last = NULL;
|
state_item *last = NULL;
|
||||||
@@ -337,19 +334,17 @@ parser_pop (parse_state *ps, int deriv_index,
|
|||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
chunks[i] = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
|
chunks[i] = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
|
||||||
for (parse_state *pn = ps; pn != NULL; pn = pn->parent)
|
for (parse_state *pn = ps; pn != NULL; pn = pn->parent)
|
||||||
{
|
if (pn->prepend)
|
||||||
if (pn->prepend)
|
{
|
||||||
{
|
gl_list_add_last (chunks[0], pn->state_items.contents);
|
||||||
gl_list_add_last (chunks[0], pn->state_items.contents);
|
gl_list_add_last (chunks[2], pn->derivs.contents);
|
||||||
gl_list_add_last (chunks[2], pn->derivs.contents);
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
gl_list_add_first (chunks[1], pn->state_items.contents);
|
||||||
gl_list_add_first (chunks[1], pn->state_items.contents);
|
gl_list_add_first (chunks[3], pn->derivs.contents);
|
||||||
gl_list_add_first (chunks[3], pn->derivs.contents);
|
}
|
||||||
}
|
derivation_list popped_derivs = derivation_list_new ();
|
||||||
}
|
|
||||||
gl_list_t popped_derivs = derivation_list_new ();
|
|
||||||
gl_list_t ret_chunks[4] = { ret->state_items.contents, NULL,
|
gl_list_t ret_chunks[4] = { ret->state_items.contents, NULL,
|
||||||
ret->derivs.contents, popped_derivs
|
ret->derivs.contents, popped_derivs
|
||||||
};
|
};
|
||||||
@@ -390,7 +385,7 @@ parser_pop (parse_state *ps, int deriv_index,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
parse_state_lists (parse_state *ps, gl_list_t *sitems,
|
parse_state_lists (parse_state *ps, state_item_list *sitems,
|
||||||
derivation_list *derivs)
|
derivation_list *derivs)
|
||||||
{
|
{
|
||||||
parse_state *temp = empty_parse_state ();
|
parse_state *temp = empty_parse_state ();
|
||||||
@@ -418,12 +413,12 @@ nullable_closure (parse_state *ps, state_item *si, parse_state_list state_list)
|
|||||||
for (state_item_number sin = si->trans; sin != -1;
|
for (state_item_number sin = si->trans; sin != -1;
|
||||||
prev_sin = sin, sin = state_items[sin].trans)
|
prev_sin = sin, sin = state_items[sin].trans)
|
||||||
{
|
{
|
||||||
state_item *psi = state_items + prev_sin;
|
state_item *psi = &state_items[prev_sin];
|
||||||
symbol_number sp = item_number_as_symbol_number (*psi->item);
|
symbol_number sp = item_number_as_symbol_number (*psi->item);
|
||||||
if (ISTOKEN (sp) || !nullable[sp - ntokens])
|
if (ISTOKEN (sp) || !nullable[sp - ntokens])
|
||||||
break;
|
break;
|
||||||
|
|
||||||
state_item *nsi = state_items + sin;
|
state_item *nsi = &state_items[sin];
|
||||||
current_ps = copy_parse_state (false, current_ps);
|
current_ps = copy_parse_state (false, current_ps);
|
||||||
ps_si_append (current_ps, nsi);
|
ps_si_append (current_ps, nsi);
|
||||||
ps_derivs_append (current_ps, derivation_new (sp, derivation_list_new ()));
|
ps_derivs_append (current_ps, derivation_new (sp, derivation_list_new ()));
|
||||||
@@ -431,26 +426,25 @@ nullable_closure (parse_state *ps, state_item *si, parse_state_list state_list)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gl_list_t
|
parse_state_list
|
||||||
simulate_transition (parse_state *ps)
|
simulate_transition (parse_state *ps)
|
||||||
{
|
{
|
||||||
const state_item *si = ps->state_items.tail_elt;
|
const state_item *si = ps->state_items.tail_elt;
|
||||||
symbol_number sym = item_number_as_symbol_number (*si->item);
|
symbol_number sym = item_number_as_symbol_number (*si->item);
|
||||||
// Transition on the same next symbol, taking nullable
|
// Transition on the same next symbol, taking nullable
|
||||||
// symbols into account.
|
// symbols into account.
|
||||||
gl_list_t result = parse_state_list_new ();
|
parse_state_list result = parse_state_list_new ();
|
||||||
state_item_number si_next = si->trans;
|
state_item_number si_next = si->trans;
|
||||||
// check for disabled transition, shouldn't happen
|
// Check for disabled transition, shouldn't happen as any
|
||||||
// as any state_items that lead to these should be
|
// state_items that lead to these should be disabled.
|
||||||
// disabled.
|
|
||||||
if (si_next < 0)
|
if (si_next < 0)
|
||||||
return result;
|
return result;
|
||||||
parse_state *next_ps = copy_parse_state (false, ps);
|
parse_state *next_ps = copy_parse_state (false, ps);
|
||||||
ps_si_append (next_ps, state_items + si_next);
|
ps_si_append (next_ps, &state_items[si_next]);
|
||||||
ps_derivs_append (next_ps, derivation_new_leaf (sym));
|
ps_derivs_append (next_ps, derivation_new_leaf (sym));
|
||||||
parse_state_list_append (result, next_ps);
|
parse_state_list_append (result, next_ps);
|
||||||
|
|
||||||
nullable_closure (next_ps, state_items + si_next, result);
|
nullable_closure (next_ps, &state_items[si_next], result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,10 +467,10 @@ compatible (symbol_number sym1, symbol_number sym2)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
gl_list_t
|
parse_state_list
|
||||||
simulate_production (parse_state *ps, symbol_number compat_sym)
|
simulate_production (parse_state *ps, symbol_number compat_sym)
|
||||||
{
|
{
|
||||||
gl_list_t result = parse_state_list_new ();
|
parse_state_list result = parse_state_list_new ();
|
||||||
const state_item *si = parse_state_tail (ps);
|
const state_item *si = parse_state_tail (ps);
|
||||||
if (si->prods)
|
if (si->prods)
|
||||||
{
|
{
|
||||||
@@ -486,7 +480,7 @@ simulate_production (parse_state *ps, symbol_number compat_sym)
|
|||||||
{
|
{
|
||||||
// Take production step only if lhs is not nullable and
|
// Take production step only if lhs is not nullable and
|
||||||
// if first rhs symbol is compatible with compat_sym
|
// if first rhs symbol is compatible with compat_sym
|
||||||
state_item *next = state_items + sin;
|
state_item *next = &state_items[sin];
|
||||||
item_number *itm1 = next->item;
|
item_number *itm1 = next->item;
|
||||||
if (!compatible (*itm1, compat_sym) || !production_allowed (si, next))
|
if (!compatible (*itm1, compat_sym) || !production_allowed (si, next))
|
||||||
continue;
|
continue;
|
||||||
@@ -504,10 +498,10 @@ simulate_production (parse_state *ps, symbol_number compat_sym)
|
|||||||
// simulates a reduction on the given parse state, conflict_item is the
|
// simulates a reduction on the given parse state, conflict_item is the
|
||||||
// item associated with ps's conflict. symbol_set is a lookahead set this
|
// item associated with ps's conflict. symbol_set is a lookahead set this
|
||||||
// reduction must be compatible with
|
// reduction must be compatible with
|
||||||
gl_list_t
|
parse_state_list
|
||||||
simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set)
|
simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set)
|
||||||
{
|
{
|
||||||
gl_list_t result = parse_state_list_new ();
|
parse_state_list result = parse_state_list_new ();
|
||||||
|
|
||||||
int s_size = ps->state_items.total_size;
|
int s_size = ps->state_items.total_size;
|
||||||
int d_size = ps->derivs.total_size;
|
int d_size = ps->derivs.total_size;
|
||||||
@@ -529,7 +523,7 @@ simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set)
|
|||||||
if (s_size != rule_len + 1)
|
if (s_size != rule_len + 1)
|
||||||
{
|
{
|
||||||
state_item *tail = (state_item *) new_root->state_items.tail_elt;
|
state_item *tail = (state_item *) new_root->state_items.tail_elt;
|
||||||
ps_si_append (new_root, state_items + tail->trans);
|
ps_si_append (new_root, &state_items[tail->trans]);
|
||||||
parse_state_list_append (result, new_root);
|
parse_state_list_append (result, new_root);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -537,7 +531,7 @@ simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set)
|
|||||||
// The head state_item is a production item, so we need to prepend
|
// The head state_item is a production item, so we need to prepend
|
||||||
// with possible source state-items.
|
// with possible source state-items.
|
||||||
const state_item *head = ps->state_items.head_elt;
|
const state_item *head = ps->state_items.head_elt;
|
||||||
gl_list_t prev = lssi_reverse_production (head, symbol_set);
|
state_item_list prev = lssi_reverse_production (head, symbol_set);
|
||||||
// TODO: better understand what causes this case.
|
// TODO: better understand what causes this case.
|
||||||
if (gl_list_size (prev) == 0)
|
if (gl_list_size (prev) == 0)
|
||||||
{
|
{
|
||||||
@@ -560,7 +554,7 @@ simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set)
|
|||||||
copy = copy_parse_state (false, copy);
|
copy = copy_parse_state (false, copy);
|
||||||
struct si_chunk *sis = ©->state_items;
|
struct si_chunk *sis = ©->state_items;
|
||||||
const state_item *tail = sis->tail_elt;
|
const state_item *tail = sis->tail_elt;
|
||||||
ps_si_append (copy, state_items + tail->trans);
|
ps_si_append (copy, &state_items[tail->trans]);
|
||||||
parse_state_list_append (result, copy);
|
parse_state_list_append (result, copy);
|
||||||
nullable_closure (copy, (state_item *) sis->tail_elt, result);
|
nullable_closure (copy, (state_item *) sis->tail_elt, result);
|
||||||
}
|
}
|
||||||
@@ -570,10 +564,10 @@ simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gl_list_t
|
parse_state_list
|
||||||
parser_prepend (parse_state *ps)
|
parser_prepend (parse_state *ps)
|
||||||
{
|
{
|
||||||
gl_list_t res = parse_state_list_new ();
|
parse_state_list res = parse_state_list_new ();
|
||||||
const state_item *head = ps->state_items.head_elt;
|
const state_item *head = ps->state_items.head_elt;
|
||||||
symbol_number prepend_sym =
|
symbol_number prepend_sym =
|
||||||
item_number_as_symbol_number (*(head->item - 1));
|
item_number_as_symbol_number (*(head->item - 1));
|
||||||
@@ -582,7 +576,7 @@ parser_prepend (parse_state *ps)
|
|||||||
BITSET_FOR_EACH (biter, head->revs, sin, 0)
|
BITSET_FOR_EACH (biter, head->revs, sin, 0)
|
||||||
{
|
{
|
||||||
parse_state *copy = copy_parse_state (true, ps);
|
parse_state *copy = copy_parse_state (true, ps);
|
||||||
ps_si_prepend (copy, state_items + sin);
|
ps_si_prepend (copy, &state_items[sin]);
|
||||||
if (SI_TRANSITION (head))
|
if (SI_TRANSITION (head))
|
||||||
ps_derivs_prepend (copy, derivation_new_leaf (prepend_sym));
|
ps_derivs_prepend (copy, derivation_new_leaf (prepend_sym));
|
||||||
parse_state_list_append (res, copy);
|
parse_state_list_append (res, copy);
|
||||||
@@ -596,8 +590,8 @@ print_parse_state (parse_state *ps)
|
|||||||
FILE *out = stderr;
|
FILE *out = stderr;
|
||||||
fprintf (out, "(size %zu depth %d rc %d)\n",
|
fprintf (out, "(size %zu depth %d rc %d)\n",
|
||||||
ps->state_items.total_size, ps->depth, ps->reference_count);
|
ps->state_items.total_size, ps->depth, ps->reference_count);
|
||||||
print_state_item (ps->state_items.head_elt, out, "");
|
state_item_print (ps->state_items.head_elt, out, "");
|
||||||
print_state_item (ps->state_items.tail_elt, out, "");
|
state_item_print (ps->state_items.tail_elt, out, "");
|
||||||
if (ps->derivs.total_size > 0)
|
if (ps->derivs.total_size > 0)
|
||||||
derivation_print (ps->derivs.head_elt, out, "");
|
derivation_print (ps->derivs.head_elt, out, "");
|
||||||
putc ('\n', out);
|
putc ('\n', out);
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ int parse_state_length (const parse_state *ps);
|
|||||||
int parse_state_depth (const parse_state *ps);
|
int parse_state_depth (const parse_state *ps);
|
||||||
|
|
||||||
/* returns the linked lists that the parse state is supposed to represent */
|
/* returns the linked lists that the parse state is supposed to represent */
|
||||||
void parse_state_lists (parse_state *ps, gl_list_t *state_items,
|
void parse_state_lists (parse_state *ps, state_item_list *state_items,
|
||||||
derivation_list *derivs);
|
derivation_list *derivs);
|
||||||
|
|
||||||
/* various functions that return a list of states based off of
|
/* various functions that return a list of states based off of
|
||||||
|
|||||||
+3
-3
@@ -96,7 +96,7 @@ print_core (struct obstack *oout, state *s)
|
|||||||
obstack_sgrow (oout, " %empty");
|
obstack_sgrow (oout, " %empty");
|
||||||
|
|
||||||
/* Experimental feature: display the lookahead tokens. */
|
/* Experimental feature: display the lookahead tokens. */
|
||||||
if (report_flag & report_lookahead_tokens
|
if (report_flag & report_lookaheads
|
||||||
&& item_number_is_rule_number (*sp1))
|
&& item_number_is_rule_number (*sp1))
|
||||||
{
|
{
|
||||||
/* Find the reduction we are handling. */
|
/* Find the reduction we are handling. */
|
||||||
@@ -104,13 +104,13 @@ print_core (struct obstack *oout, state *s)
|
|||||||
int redno = state_reduction_find (s, r);
|
int redno = state_reduction_find (s, r);
|
||||||
|
|
||||||
/* Print them if there are. */
|
/* Print them if there are. */
|
||||||
if (reds->lookahead_tokens && redno != -1)
|
if (reds->lookaheads && redno != -1)
|
||||||
{
|
{
|
||||||
bitset_iterator biter;
|
bitset_iterator biter;
|
||||||
int k;
|
int k;
|
||||||
char const *sep = "";
|
char const *sep = "";
|
||||||
obstack_sgrow (oout, " [");
|
obstack_sgrow (oout, " [");
|
||||||
BITSET_FOR_EACH (biter, reds->lookahead_tokens[redno], k, 0)
|
BITSET_FOR_EACH (biter, reds->lookaheads[redno], k, 0)
|
||||||
{
|
{
|
||||||
obstack_sgrow (oout, sep);
|
obstack_sgrow (oout, sep);
|
||||||
obstack_backslash (oout, symbols[k]->tag);
|
obstack_backslash (oout, symbols[k]->tag);
|
||||||
|
|||||||
+29
-22
@@ -86,12 +86,12 @@ print_core (FILE *out, int level, state *s)
|
|||||||
reductions *reds = s->reductions;
|
reductions *reds = s->reductions;
|
||||||
int red = state_reduction_find (s, r);
|
int red = state_reduction_find (s, r);
|
||||||
/* Print item with lookaheads if there are. */
|
/* Print item with lookaheads if there are. */
|
||||||
if (reds->lookahead_tokens && red != -1)
|
if (reds->lookaheads && red != -1)
|
||||||
{
|
{
|
||||||
xml_printf (out, level + 1,
|
xml_printf (out, level + 1,
|
||||||
"<item rule-number=\"%d\" dot=\"%d\">",
|
"<item rule-number=\"%d\" dot=\"%d\">",
|
||||||
r->number, sp1 - sp);
|
r->number, sp1 - sp);
|
||||||
state_rule_lookahead_tokens_print_xml (s, r,
|
state_rule_lookaheads_print_xml (s, r,
|
||||||
out, level + 2);
|
out, level + 2);
|
||||||
xml_puts (out, level + 1, "</item>");
|
xml_puts (out, level + 1, "</item>");
|
||||||
printed = true;
|
printed = true;
|
||||||
@@ -202,26 +202,26 @@ print_errs (FILE *out, int level, state *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------.
|
/*-------------------------------------------------------------------.
|
||||||
| Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be 'default'). |
|
| Report a reduction of RULE on LOOKAHEAD (which can be 'default'). |
|
||||||
| If not ENABLED, the rule is masked by a shift or a reduce (S/R and |
|
| If not ENABLED, the rule is masked by a shift or a reduce (S/R and |
|
||||||
| R/R conflicts). |
|
| R/R conflicts). |
|
||||||
`-------------------------------------------------------------------------*/
|
`-------------------------------------------------------------------*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_reduction (FILE *out, int level, char const *lookahead_token,
|
print_reduction (FILE *out, int level, char const *lookahead,
|
||||||
rule *r, bool enabled)
|
rule *r, bool enabled)
|
||||||
{
|
{
|
||||||
if (r->number)
|
if (r->number)
|
||||||
xml_printf (out, level,
|
xml_printf (out, level,
|
||||||
"<reduction symbol=\"%s\" rule=\"%d\" enabled=\"%s\"/>",
|
"<reduction symbol=\"%s\" rule=\"%d\" enabled=\"%s\"/>",
|
||||||
xml_escape (lookahead_token),
|
xml_escape (lookahead),
|
||||||
r->number,
|
r->number,
|
||||||
enabled ? "true" : "false");
|
enabled ? "true" : "false");
|
||||||
else
|
else
|
||||||
xml_printf (out, level,
|
xml_printf (out, level,
|
||||||
"<reduction symbol=\"%s\" rule=\"accept\" enabled=\"%s\"/>",
|
"<reduction symbol=\"%s\" rule=\"accept\" enabled=\"%s\"/>",
|
||||||
xml_escape (lookahead_token),
|
xml_escape (lookahead),
|
||||||
enabled ? "true" : "false");
|
enabled ? "true" : "false");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,13 +258,13 @@ print_reductions (FILE *out, int level, state *s)
|
|||||||
if (default_reduction)
|
if (default_reduction)
|
||||||
report = true;
|
report = true;
|
||||||
|
|
||||||
if (reds->lookahead_tokens)
|
if (reds->lookaheads)
|
||||||
for (i = 0; i < ntokens; i++)
|
for (i = 0; i < ntokens; i++)
|
||||||
{
|
{
|
||||||
bool count = bitset_test (no_reduce_set, i);
|
bool count = bitset_test (no_reduce_set, i);
|
||||||
|
|
||||||
for (j = 0; j < reds->num; ++j)
|
for (j = 0; j < reds->num; ++j)
|
||||||
if (bitset_test (reds->lookahead_tokens[j], i))
|
if (bitset_test (reds->lookaheads[j], i))
|
||||||
{
|
{
|
||||||
if (! count)
|
if (! count)
|
||||||
{
|
{
|
||||||
@@ -289,14 +289,14 @@ print_reductions (FILE *out, int level, state *s)
|
|||||||
xml_puts (out, level, "<reductions>");
|
xml_puts (out, level, "<reductions>");
|
||||||
|
|
||||||
/* Report lookahead tokens (or $default) and reductions. */
|
/* Report lookahead tokens (or $default) and reductions. */
|
||||||
if (reds->lookahead_tokens)
|
if (reds->lookaheads)
|
||||||
for (i = 0; i < ntokens; i++)
|
for (i = 0; i < ntokens; i++)
|
||||||
{
|
{
|
||||||
bool defaulted = false;
|
bool defaulted = false;
|
||||||
bool count = bitset_test (no_reduce_set, i);
|
bool count = bitset_test (no_reduce_set, i);
|
||||||
|
|
||||||
for (j = 0; j < reds->num; ++j)
|
for (j = 0; j < reds->num; ++j)
|
||||||
if (bitset_test (reds->lookahead_tokens[j], i))
|
if (bitset_test (reds->lookaheads[j], i))
|
||||||
{
|
{
|
||||||
if (! count)
|
if (! count)
|
||||||
{
|
{
|
||||||
@@ -382,14 +382,17 @@ print_grammar (FILE *out, int level)
|
|||||||
for (int i = 0; i < max_code + 1; i++)
|
for (int i = 0; i < max_code + 1; i++)
|
||||||
if (token_translations[i] != undeftoken->content->number)
|
if (token_translations[i] != undeftoken->content->number)
|
||||||
{
|
{
|
||||||
char const *tag = symbols[token_translations[i]]->tag;
|
symbol const *sym = symbols[token_translations[i]];
|
||||||
int precedence = symbols[token_translations[i]]->content->prec;
|
char const *tag = sym->tag;
|
||||||
assoc associativity = symbols[token_translations[i]]->content->assoc;
|
char const *type = sym->content->type_name;
|
||||||
|
int precedence = sym->content->prec;
|
||||||
|
assoc associativity = sym->content->assoc;
|
||||||
xml_indent (out, level + 2);
|
xml_indent (out, level + 2);
|
||||||
fprintf (out,
|
fprintf (out,
|
||||||
"<terminal symbol-number=\"%d\" token-number=\"%d\""
|
"<terminal symbol-number=\"%d\" token-number=\"%d\""
|
||||||
" name=\"%s\" usefulness=\"%s\"",
|
" name=\"%s\" type=\"%s\" usefulness=\"%s\"",
|
||||||
token_translations[i], i, xml_escape (tag),
|
token_translations[i], i, xml_escape_n (0, tag),
|
||||||
|
type ? xml_escape_n (1, type) : "",
|
||||||
reduce_token_unused_in_grammar (token_translations[i])
|
reduce_token_unused_in_grammar (token_translations[i])
|
||||||
? "unused-in-grammar" : "useful");
|
? "unused-in-grammar" : "useful");
|
||||||
if (precedence)
|
if (precedence)
|
||||||
@@ -404,12 +407,16 @@ print_grammar (FILE *out, int level)
|
|||||||
xml_puts (out, level + 1, "<nonterminals>");
|
xml_puts (out, level + 1, "<nonterminals>");
|
||||||
for (symbol_number i = ntokens; i < nsyms + nuseless_nonterminals; i++)
|
for (symbol_number i = ntokens; i < nsyms + nuseless_nonterminals; i++)
|
||||||
{
|
{
|
||||||
char const *tag = symbols[i]->tag;
|
symbol const *sym = symbols[i];
|
||||||
|
char const *tag = sym->tag;
|
||||||
|
char const *type = sym->content->type_name;
|
||||||
xml_printf (out, level + 2,
|
xml_printf (out, level + 2,
|
||||||
"<nonterminal symbol-number=\"%d\" name=\"%s\""
|
"<nonterminal symbol-number=\"%d\" name=\"%s\""
|
||||||
|
" type=\"%s\""
|
||||||
" usefulness=\"%s\"/>",
|
" usefulness=\"%s\"/>",
|
||||||
i, xml_escape (tag),
|
i, xml_escape_n (0, tag),
|
||||||
reduce_nonterminal_useless_in_grammar (symbols[i]->content)
|
type ? xml_escape_n (1, type) : "",
|
||||||
|
reduce_nonterminal_useless_in_grammar (sym->content)
|
||||||
? "useless-in-grammar" : "useful");
|
? "useless-in-grammar" : "useful");
|
||||||
}
|
}
|
||||||
xml_puts (out, level + 1, "</nonterminals>");
|
xml_puts (out, level + 1, "</nonterminals>");
|
||||||
|
|||||||
+22
-21
@@ -90,9 +90,9 @@ print_core (FILE *out, const state *s)
|
|||||||
previous_rule = r;
|
previous_rule = r;
|
||||||
|
|
||||||
/* Display the lookahead tokens? */
|
/* Display the lookahead tokens? */
|
||||||
if (report_flag & report_lookahead_tokens
|
if (report_flag & report_lookaheads
|
||||||
&& item_number_is_rule_number (*sp1))
|
&& item_number_is_rule_number (*sp1))
|
||||||
state_rule_lookahead_tokens_print (s, r, out);
|
state_rule_lookaheads_print (s, r, out);
|
||||||
fputc ('\n', out);
|
fputc ('\n', out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,19 +180,19 @@ print_errs (FILE *out, const state *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------.
|
/*-------------------------------------------------------------------.
|
||||||
| Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be 'default'). |
|
| Report a reduction of RULE on LOOKAHEAD (which can be 'default'). |
|
||||||
| If not ENABLED, the rule is masked by a shift or a reduce (S/R and |
|
| If not ENABLED, the rule is masked by a shift or a reduce (S/R and |
|
||||||
| R/R conflicts). |
|
| R/R conflicts). |
|
||||||
`-------------------------------------------------------------------------*/
|
`-------------------------------------------------------------------*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_reduction (FILE *out, size_t width,
|
print_reduction (FILE *out, size_t width,
|
||||||
const char *lookahead_token,
|
const char *lookahead,
|
||||||
rule *r, bool enabled)
|
rule *r, bool enabled)
|
||||||
{
|
{
|
||||||
fprintf (out, " %s", lookahead_token);
|
fprintf (out, " %s", lookahead);
|
||||||
for (int j = width - mbswidth (lookahead_token, 0); j > 0; --j)
|
for (int j = width - mbswidth (lookahead, 0); j > 0; --j)
|
||||||
fputc (' ', out);
|
fputc (' ', out);
|
||||||
if (!enabled)
|
if (!enabled)
|
||||||
fputc ('[', out);
|
fputc ('[', out);
|
||||||
@@ -239,13 +239,13 @@ print_reductions (FILE *out, const state *s)
|
|||||||
if (default_reduction)
|
if (default_reduction)
|
||||||
width = mbswidth (_("$default"), 0);
|
width = mbswidth (_("$default"), 0);
|
||||||
|
|
||||||
if (reds->lookahead_tokens)
|
if (reds->lookaheads)
|
||||||
for (int i = 0; i < ntokens; i++)
|
for (int i = 0; i < ntokens; i++)
|
||||||
{
|
{
|
||||||
bool count = bitset_test (no_reduce_set, i);
|
bool count = bitset_test (no_reduce_set, i);
|
||||||
|
|
||||||
for (int j = 0; j < reds->num; ++j)
|
for (int j = 0; j < reds->num; ++j)
|
||||||
if (bitset_test (reds->lookahead_tokens[j], i))
|
if (bitset_test (reds->lookaheads[j], i))
|
||||||
{
|
{
|
||||||
if (! count)
|
if (! count)
|
||||||
{
|
{
|
||||||
@@ -268,7 +268,7 @@ print_reductions (FILE *out, const state *s)
|
|||||||
bool default_reduction_only = true;
|
bool default_reduction_only = true;
|
||||||
|
|
||||||
/* Report lookahead tokens (or $default) and reductions. */
|
/* Report lookahead tokens (or $default) and reductions. */
|
||||||
if (reds->lookahead_tokens)
|
if (reds->lookaheads)
|
||||||
for (int i = 0; i < ntokens; i++)
|
for (int i = 0; i < ntokens; i++)
|
||||||
{
|
{
|
||||||
bool defaulted = false;
|
bool defaulted = false;
|
||||||
@@ -277,7 +277,7 @@ print_reductions (FILE *out, const state *s)
|
|||||||
default_reduction_only = false;
|
default_reduction_only = false;
|
||||||
|
|
||||||
for (int j = 0; j < reds->num; ++j)
|
for (int j = 0; j < reds->num; ++j)
|
||||||
if (bitset_test (reds->lookahead_tokens[j], i))
|
if (bitset_test (reds->lookaheads[j], i))
|
||||||
{
|
{
|
||||||
if (! count)
|
if (! count)
|
||||||
{
|
{
|
||||||
@@ -377,11 +377,11 @@ print_terminal_symbols (FILE *out)
|
|||||||
for (int i = 0; i < max_code + 1; ++i)
|
for (int i = 0; i < max_code + 1; ++i)
|
||||||
if (token_translations[i] != undeftoken->content->number)
|
if (token_translations[i] != undeftoken->content->number)
|
||||||
{
|
{
|
||||||
const char *tag = symbols[token_translations[i]]->tag;
|
const symbol *sym = symbols[token_translations[i]];
|
||||||
|
const char *tag = sym->tag;
|
||||||
fprintf (out, "%4s%s", "", tag);
|
fprintf (out, "%4s%s", "", tag);
|
||||||
if (symbols[token_translations[i]]->content->type_name)
|
if (sym->content->type_name)
|
||||||
fprintf (out, " <%s>",
|
fprintf (out, " <%s>", sym->content->type_name);
|
||||||
symbols[token_translations[i]]->content->type_name);
|
|
||||||
fprintf (out, " (%d)", i);
|
fprintf (out, " (%d)", i);
|
||||||
|
|
||||||
for (rule_number r = 0; r < nrules; r++)
|
for (rule_number r = 0; r < nrules; r++)
|
||||||
@@ -403,7 +403,8 @@ print_nonterminal_symbols (FILE *out)
|
|||||||
fprintf (out, "%s\n\n", _("Nonterminals, with rules where they appear"));
|
fprintf (out, "%s\n\n", _("Nonterminals, with rules where they appear"));
|
||||||
for (symbol_number i = ntokens; i < nsyms; i++)
|
for (symbol_number i = ntokens; i < nsyms; i++)
|
||||||
{
|
{
|
||||||
const char *tag = symbols[i]->tag;
|
const symbol *sym = symbols[i];
|
||||||
|
const char *tag = sym->tag;
|
||||||
bool on_left = false;
|
bool on_left = false;
|
||||||
bool on_right = false;
|
bool on_right = false;
|
||||||
|
|
||||||
@@ -418,9 +419,9 @@ print_nonterminal_symbols (FILE *out)
|
|||||||
|
|
||||||
int column = 4 + mbswidth (tag, 0);
|
int column = 4 + mbswidth (tag, 0);
|
||||||
fprintf (out, "%4s%s", "", tag);
|
fprintf (out, "%4s%s", "", tag);
|
||||||
if (symbols[i]->content->type_name)
|
if (sym->content->type_name)
|
||||||
column += fprintf (out, " <%s>",
|
column += fprintf (out, " <%s>",
|
||||||
symbols[i]->content->type_name);
|
sym->content->type_name);
|
||||||
fprintf (out, " (%d)\n", i);
|
fprintf (out, " (%d)\n", i);
|
||||||
|
|
||||||
if (on_left)
|
if (on_left)
|
||||||
|
|||||||
+12
-11
@@ -406,8 +406,8 @@ grammar_midrule_action (void)
|
|||||||
action. Create the MIDRULE. */
|
action. Create the MIDRULE. */
|
||||||
location dummy_loc = current_rule->action_props.location;
|
location dummy_loc = current_rule->action_props.location;
|
||||||
symbol *dummy = dummy_symbol_get (dummy_loc);
|
symbol *dummy = dummy_symbol_get (dummy_loc);
|
||||||
symbol_type_set(dummy,
|
symbol_type_set (dummy,
|
||||||
current_rule->action_props.type, current_rule->action_props.location);
|
current_rule->action_props.type, current_rule->action_props.location);
|
||||||
symbol_list *midrule = symbol_list_sym_new (dummy, dummy_loc);
|
symbol_list *midrule = symbol_list_sym_new (dummy, dummy_loc);
|
||||||
|
|
||||||
/* Remember named_ref of previous action. */
|
/* Remember named_ref of previous action. */
|
||||||
@@ -695,12 +695,10 @@ packgram (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------.
|
/*--------------------------------------------------------------.
|
||||||
| Read in the grammar specification and record it in the format |
|
| Read in the grammar specification and record it in the format |
|
||||||
| described in gram.h. All actions are copied into ACTION_OBSTACK, |
|
| described in gram.h. |
|
||||||
| in each case forming the body of a C function (YYACTION) which |
|
`--------------------------------------------------------------*/
|
||||||
| contains a switch statement to decide which action to execute. |
|
|
||||||
`------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void
|
void
|
||||||
reader (const char *gram)
|
reader (const char *gram)
|
||||||
@@ -806,7 +804,7 @@ check_and_convert_grammar (void)
|
|||||||
|
|
||||||
$accept: %start $end. */
|
$accept: %start $end. */
|
||||||
{
|
{
|
||||||
symbol_list *p = symbol_list_sym_new (accept, empty_loc);
|
symbol_list *p = symbol_list_sym_new (acceptsymbol, empty_loc);
|
||||||
p->rhs_loc = grammar->rhs_loc;
|
p->rhs_loc = grammar->rhs_loc;
|
||||||
p->next = symbol_list_sym_new (startsymbol, empty_loc);
|
p->next = symbol_list_sym_new (startsymbol, empty_loc);
|
||||||
p->next->next = symbol_list_sym_new (eoftoken, empty_loc);
|
p->next->next = symbol_list_sym_new (eoftoken, empty_loc);
|
||||||
@@ -817,8 +815,11 @@ check_and_convert_grammar (void)
|
|||||||
grammar = p;
|
grammar = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
aver (nsyms <= SYMBOL_NUMBER_MAXIMUM);
|
if (SYMBOL_NUMBER_MAXIMUM - nnterms < ntokens)
|
||||||
aver (nsyms == ntokens + nnterms);
|
complain (NULL, fatal, "too many symbols in input grammar (limit is %d)",
|
||||||
|
SYMBOL_NUMBER_MAXIMUM);
|
||||||
|
|
||||||
|
nsyms = ntokens + nnterms;
|
||||||
|
|
||||||
/* Assign the symbols their symbol numbers. */
|
/* Assign the symbols their symbol numbers. */
|
||||||
symbols_pack ();
|
symbols_pack ();
|
||||||
|
|||||||
+4
-4
@@ -160,9 +160,9 @@ inaccessable_symbols (void)
|
|||||||
bitset Pp = bitset_create (nrules, BITSET_FIXED);
|
bitset Pp = bitset_create (nrules, BITSET_FIXED);
|
||||||
|
|
||||||
/* If the start symbol isn't useful, then nothing will be useful. */
|
/* If the start symbol isn't useful, then nothing will be useful. */
|
||||||
if (bitset_test (N, accept->content->number - ntokens))
|
if (bitset_test (N, acceptsymbol->content->number - ntokens))
|
||||||
{
|
{
|
||||||
bitset_set (V, accept->content->number);
|
bitset_set (V, acceptsymbol->content->number);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
@@ -301,7 +301,7 @@ nonterminals_reduce (void)
|
|||||||
for (item_number *rhsp = rules[r].rhs; 0 <= *rhsp; ++rhsp)
|
for (item_number *rhsp = rules[r].rhs; 0 <= *rhsp; ++rhsp)
|
||||||
if (ISVAR (*rhsp))
|
if (ISVAR (*rhsp))
|
||||||
*rhsp = symbol_number_as_item_number (nterm_map[*rhsp - ntokens]);
|
*rhsp = symbol_number_as_item_number (nterm_map[*rhsp - ntokens]);
|
||||||
accept->content->number = nterm_map[accept->content->number - ntokens];
|
acceptsymbol->content->number = nterm_map[acceptsymbol->content->number - ntokens];
|
||||||
}
|
}
|
||||||
|
|
||||||
nsyms -= nuseless_nonterminals;
|
nsyms -= nuseless_nonterminals;
|
||||||
@@ -381,7 +381,7 @@ reduce_grammar (void)
|
|||||||
{
|
{
|
||||||
reduce_print ();
|
reduce_print ();
|
||||||
|
|
||||||
if (!bitset_test (N, accept->content->number - ntokens))
|
if (!bitset_test (N, acceptsymbol->content->number - ntokens))
|
||||||
complain (&startsymbol_loc, fatal,
|
complain (&startsymbol_loc, fatal,
|
||||||
_("start symbol %s does not derive any sentence"),
|
_("start symbol %s does not derive any sentence"),
|
||||||
startsymbol->tag);
|
startsymbol->tag);
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ void code_props_symbol_action_init (code_props *self, char const *code,
|
|||||||
location code_loc);
|
location code_loc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* \param type type for midrule actions
|
||||||
* \pre
|
* \pre
|
||||||
* - <tt>self != NULL</tt>.
|
* - <tt>self != NULL</tt>.
|
||||||
* - <tt>code != NULL</tt>.
|
* - <tt>code != NULL</tt>.
|
||||||
|
|||||||
+21
-12
@@ -322,8 +322,8 @@ eqopt ({sp}=)?
|
|||||||
BEGIN SC_AFTER_IDENTIFIER;
|
BEGIN SC_AFTER_IDENTIFIER;
|
||||||
}
|
}
|
||||||
|
|
||||||
{int} RETURN_VALUE (INT, scan_integer (yytext, 10, *loc));
|
{int} RETURN_VALUE (INT_LITERAL, scan_integer (yytext, 10, *loc));
|
||||||
{xint} RETURN_VALUE (INT, scan_integer (yytext, 16, *loc));
|
{xint} RETURN_VALUE (INT_LITERAL, scan_integer (yytext, 16, *loc));
|
||||||
|
|
||||||
/* Identifiers may not start with a digit. Yet, don't silently
|
/* Identifiers may not start with a digit. Yet, don't silently
|
||||||
accept "1FOO" as "1 FOO". */
|
accept "1FOO" as "1 FOO". */
|
||||||
@@ -403,6 +403,7 @@ eqopt ({sp}=)?
|
|||||||
{
|
{
|
||||||
\0 {
|
\0 {
|
||||||
complain (loc, complaint, _("invalid null character"));
|
complain (loc, complaint, _("invalid null character"));
|
||||||
|
STRING_FINISH ();
|
||||||
STRING_FREE ();
|
STRING_FREE ();
|
||||||
return GRAM_error;
|
return GRAM_error;
|
||||||
}
|
}
|
||||||
@@ -566,6 +567,8 @@ eqopt ({sp}=)?
|
|||||||
_("POSIX Yacc does not support string literals"));
|
_("POSIX Yacc does not support string literals"));
|
||||||
RETURN_VALUE (STRING, last_string);
|
RETURN_VALUE (STRING, last_string);
|
||||||
}
|
}
|
||||||
|
<<EOF>> unexpected_eof (token_start, "\"");
|
||||||
|
"\n" unexpected_newline (token_start, "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
<SC_ESCAPED_TSTRING>
|
<SC_ESCAPED_TSTRING>
|
||||||
@@ -579,13 +582,10 @@ eqopt ({sp}=)?
|
|||||||
_("POSIX Yacc does not support string literals"));
|
_("POSIX Yacc does not support string literals"));
|
||||||
RETURN_VALUE (TSTRING, last_string);
|
RETURN_VALUE (TSTRING, last_string);
|
||||||
}
|
}
|
||||||
|
<<EOF>> unexpected_eof (token_start, "\")");
|
||||||
|
"\n" unexpected_newline (token_start, "\")");
|
||||||
}
|
}
|
||||||
|
|
||||||
<SC_ESCAPED_STRING,SC_ESCAPED_TSTRING>
|
|
||||||
{
|
|
||||||
<<EOF>> unexpected_eof (token_start, "\"");
|
|
||||||
"\n" unexpected_newline (token_start, "\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*----------------------------------------------------------.
|
/*----------------------------------------------------------.
|
||||||
@@ -599,7 +599,6 @@ eqopt ({sp}=)?
|
|||||||
STRING_FINISH ();
|
STRING_FINISH ();
|
||||||
BEGIN INITIAL;
|
BEGIN INITIAL;
|
||||||
loc->start = token_start;
|
loc->start = token_start;
|
||||||
val->CHAR = last_string[0];
|
|
||||||
|
|
||||||
if (last_string[0] == '\0')
|
if (last_string[0] == '\0')
|
||||||
{
|
{
|
||||||
@@ -615,8 +614,9 @@ eqopt ({sp}=)?
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
val->CHAR_LITERAL = last_string[0];
|
||||||
STRING_FREE ();
|
STRING_FREE ();
|
||||||
return CHAR;
|
return CHAR_LITERAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{eol} unexpected_newline (token_start, "'");
|
{eol} unexpected_newline (token_start, "'");
|
||||||
@@ -691,6 +691,15 @@ eqopt ({sp}=)?
|
|||||||
p);
|
p);
|
||||||
STRING_1GROW ('?');
|
STRING_1GROW ('?');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"\\" {
|
||||||
|
// None of the other rules matched: the last character of this
|
||||||
|
// file is "\". But Flex does not support "\\<<EOF>>".
|
||||||
|
unexpected_eof (token_start,
|
||||||
|
YY_START == SC_ESCAPED_CHARACTER ? "?'"
|
||||||
|
: YY_START == SC_ESCAPED_STRING ? "?\""
|
||||||
|
: "?\")");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------.
|
/*--------------------------------------------.
|
||||||
@@ -933,9 +942,9 @@ convert_ucn_to_byte (char const *ucn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------.
|
/*----------------------------------------------------------------------------.
|
||||||
| Handle '#line INT( "FILE")?\n'. ARGS has already skipped '#line '. |
|
| Handle '#line INT_LITERAL( "FILE")?\n'. ARGS has already skipped '#line '. |
|
||||||
`---------------------------------------------------------------------*/
|
`----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_syncline (char *args, location loc)
|
handle_syncline (char *args, location loc)
|
||||||
|
|||||||
+33
-35
@@ -144,13 +144,13 @@ init_state_items (void)
|
|||||||
for (int j = 0; j < s->nitems; ++j)
|
for (int j = 0; j < s->nitems; ++j)
|
||||||
{
|
{
|
||||||
state_item_set (sidx, s, s->items[j]);
|
state_item_set (sidx, s, s->items[j]);
|
||||||
state_item *si = state_items + sidx;
|
state_item *si = &state_items[sidx];
|
||||||
const rule *r = item_rule (si->item);
|
const rule *r = item_rule (si->item);
|
||||||
if (rule_search_idx < red->num && red->rules[rule_search_idx] < r)
|
if (rule_search_idx < red->num && red->rules[rule_search_idx] < r)
|
||||||
++rule_search_idx;
|
++rule_search_idx;
|
||||||
if (rule_search_idx < red->num && r == red->rules[rule_search_idx])
|
if (rule_search_idx < red->num && r == red->rules[rule_search_idx])
|
||||||
{
|
{
|
||||||
bitsetv lookahead = red->lookahead_tokens;
|
bitsetv lookahead = red->lookaheads;
|
||||||
if (lookahead)
|
if (lookahead)
|
||||||
si->lookahead = lookahead[rule_search_idx];
|
si->lookahead = lookahead[rule_search_idx];
|
||||||
}
|
}
|
||||||
@@ -163,7 +163,7 @@ init_state_items (void)
|
|||||||
state_item_set (sidx, s, off);
|
state_item_set (sidx, s, off);
|
||||||
if (item_number_is_rule_number (ritem[off]))
|
if (item_number_is_rule_number (ritem[off]))
|
||||||
{
|
{
|
||||||
bitsetv lookahead = red->lookahead_tokens;
|
bitsetv lookahead = red->lookaheads;
|
||||||
if (lookahead)
|
if (lookahead)
|
||||||
state_items[sidx].lookahead = lookahead[rule_search_idx];
|
state_items[sidx].lookahead = lookahead[rule_search_idx];
|
||||||
++rule_search_idx;
|
++rule_search_idx;
|
||||||
@@ -211,7 +211,7 @@ init_trans (void)
|
|||||||
for (int j = 0; j < t->num; ++j)
|
for (int j = 0; j < t->num; ++j)
|
||||||
if (!TRANSITION_IS_DISABLED (t, j))
|
if (!TRANSITION_IS_DISABLED (t, j))
|
||||||
hash_xinsert (transition_set, t->states[j]);
|
hash_xinsert (transition_set, t->states[j]);
|
||||||
for (int j = state_item_map[i]; j < state_item_map[i + 1]; ++j)
|
for (state_item_number j = state_item_map[i]; j < state_item_map[i + 1]; ++j)
|
||||||
{
|
{
|
||||||
item_number *item = state_items[j].item;
|
item_number *item = state_items[j].item;
|
||||||
if (item_number_is_rule_number (*item))
|
if (item_number_is_rule_number (*item))
|
||||||
@@ -222,16 +222,14 @@ init_trans (void)
|
|||||||
// find the item in the destination state that corresponds
|
// find the item in the destination state that corresponds
|
||||||
// to the transition of item
|
// to the transition of item
|
||||||
for (int k = 0; k < dst->nitems; ++k)
|
for (int k = 0; k < dst->nitems; ++k)
|
||||||
{
|
if (item + 1 == ritem + dst->items[k])
|
||||||
if (item + 1 == ritem + dst->items[k])
|
{
|
||||||
{
|
state_item_number dstSI =
|
||||||
state_item_number dstSI =
|
state_item_index_lookup (dst->number, k);
|
||||||
state_item_index_lookup (dst->number, k);
|
|
||||||
|
|
||||||
state_items[j].trans = dstSI;
|
state_items[j].trans = dstSI;
|
||||||
bitset_set (state_items[dstSI].revs, j);
|
bitset_set (state_items[dstSI].revs, j);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hash_free (transition_set);
|
hash_free (transition_set);
|
||||||
@@ -250,10 +248,10 @@ init_prods (void)
|
|||||||
|
|
||||||
// Add the nitems of state to skip to the production portion
|
// Add the nitems of state to skip to the production portion
|
||||||
// of that state's state_items
|
// of that state's state_items
|
||||||
for (int j = state_item_map[i] + s->nitems;
|
for (state_item_number j = state_item_map[i] + s->nitems;
|
||||||
j < state_item_map[i + 1]; ++j)
|
j < state_item_map[i + 1]; ++j)
|
||||||
{
|
{
|
||||||
state_item *src = state_items + j;
|
state_item *src = &state_items[j];
|
||||||
item_number *item = src->item;
|
item_number *item = src->item;
|
||||||
symbol_number lhs = item_rule (item)->lhs->number;
|
symbol_number lhs = item_rule (item)->lhs->number;
|
||||||
bitset itms = hash_pair_lookup (closure_map, lhs);
|
bitset itms = hash_pair_lookup (closure_map, lhs);
|
||||||
@@ -266,9 +264,9 @@ init_prods (void)
|
|||||||
}
|
}
|
||||||
// For each item with a dot followed by a nonterminal,
|
// For each item with a dot followed by a nonterminal,
|
||||||
// try to create a production edge.
|
// try to create a production edge.
|
||||||
for (int j = state_item_map[i]; j < state_item_map[i + 1]; ++j)
|
for (state_item_number j = state_item_map[i]; j < state_item_map[i + 1]; ++j)
|
||||||
{
|
{
|
||||||
state_item *src = state_items + j;
|
state_item *src = &state_items[j];
|
||||||
item_number item = *(src->item);
|
item_number item = *(src->item);
|
||||||
// Skip reduce items and items with terminals after the dot
|
// Skip reduce items and items with terminals after the dot
|
||||||
if (item_number_is_rule_number (item) || ISTOKEN (item))
|
if (item_number_is_rule_number (item) || ISTOKEN (item))
|
||||||
@@ -301,12 +299,12 @@ gen_lookaheads (void)
|
|||||||
{
|
{
|
||||||
for (state_item_number i = 0; i < nstate_items; ++i)
|
for (state_item_number i = 0; i < nstate_items; ++i)
|
||||||
{
|
{
|
||||||
state_item *si = state_items + i;
|
state_item *si = &state_items[i];
|
||||||
if (item_number_is_symbol_number (*(si->item)) || !si->lookahead)
|
if (item_number_is_symbol_number (*(si->item)) || !si->lookahead)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bitset lookahead = si->lookahead;
|
bitset lookahead = si->lookahead;
|
||||||
gl_list_t queue =
|
state_item_list queue =
|
||||||
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1,
|
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1,
|
||||||
(const void **) &si);
|
(const void **) &si);
|
||||||
|
|
||||||
@@ -339,7 +337,7 @@ init_firsts (void)
|
|||||||
firsts = bitsetv_create (nnterms, nsyms, BITSET_FIXED);
|
firsts = bitsetv_create (nnterms, nsyms, BITSET_FIXED);
|
||||||
for (rule_number i = 0; i < nrules; ++i)
|
for (rule_number i = 0; i < nrules; ++i)
|
||||||
{
|
{
|
||||||
rule *r = rules + i;
|
rule *r = &rules[i];
|
||||||
item_number *n = r->rhs;
|
item_number *n = r->rhs;
|
||||||
// Iterate through nullable nonterminals to try to find a terminal.
|
// Iterate through nullable nonterminals to try to find a terminal.
|
||||||
while (item_number_is_symbol_number (*n) && ISVAR (*n)
|
while (item_number_is_symbol_number (*n) && ISVAR (*n)
|
||||||
@@ -357,7 +355,7 @@ init_firsts (void)
|
|||||||
change = false;
|
change = false;
|
||||||
for (rule_number i = 0; i < nrules; ++i)
|
for (rule_number i = 0; i < nrules; ++i)
|
||||||
{
|
{
|
||||||
rule *r = rules + i;
|
rule *r = &rules[i];
|
||||||
symbol_number lhs = r->lhs->number;
|
symbol_number lhs = r->lhs->number;
|
||||||
bitset f_lhs = FIRSTS (lhs);
|
bitset f_lhs = FIRSTS (lhs);
|
||||||
for (item_number *n = r->rhs;
|
for (item_number *n = r->rhs;
|
||||||
@@ -392,7 +390,7 @@ disable_state_item (state_item *si)
|
|||||||
static void
|
static void
|
||||||
prune_forward (const state_item *si)
|
prune_forward (const state_item *si)
|
||||||
{
|
{
|
||||||
gl_list_t queue =
|
state_item_list queue =
|
||||||
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1,
|
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1,
|
||||||
(const void **) &si);
|
(const void **) &si);
|
||||||
|
|
||||||
@@ -401,7 +399,7 @@ prune_forward (const state_item *si)
|
|||||||
state_item *dsi = (state_item *) gl_list_get_at (queue, 0);
|
state_item *dsi = (state_item *) gl_list_get_at (queue, 0);
|
||||||
gl_list_remove_at (queue, 0);
|
gl_list_remove_at (queue, 0);
|
||||||
if (dsi->trans >= 0)
|
if (dsi->trans >= 0)
|
||||||
gl_list_add_last (queue, state_items + dsi->trans);
|
gl_list_add_last (queue, &state_items[dsi->trans]);
|
||||||
|
|
||||||
if (dsi->prods)
|
if (dsi->prods)
|
||||||
{
|
{
|
||||||
@@ -409,7 +407,7 @@ prune_forward (const state_item *si)
|
|||||||
state_item_number sin;
|
state_item_number sin;
|
||||||
BITSET_FOR_EACH (biter, dsi->prods, sin, 0)
|
BITSET_FOR_EACH (biter, dsi->prods, sin, 0)
|
||||||
{
|
{
|
||||||
const state_item *prod = state_items + sin;
|
const state_item *prod = &state_items[sin];
|
||||||
bitset_reset (prod->revs, dsi - state_items);
|
bitset_reset (prod->revs, dsi - state_items);
|
||||||
if (bitset_empty_p (prod->revs))
|
if (bitset_empty_p (prod->revs))
|
||||||
gl_list_add_last (queue, prod);
|
gl_list_add_last (queue, prod);
|
||||||
@@ -427,7 +425,7 @@ prune_forward (const state_item *si)
|
|||||||
static void
|
static void
|
||||||
prune_backward (const state_item *si)
|
prune_backward (const state_item *si)
|
||||||
{
|
{
|
||||||
gl_list_t queue =
|
state_item_list queue =
|
||||||
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1,
|
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1,
|
||||||
(const void **) &si);
|
(const void **) &si);
|
||||||
|
|
||||||
@@ -441,7 +439,7 @@ prune_backward (const state_item *si)
|
|||||||
{
|
{
|
||||||
if (SI_DISABLED (sin))
|
if (SI_DISABLED (sin))
|
||||||
continue;
|
continue;
|
||||||
state_item *rev = state_items + sin;
|
state_item *rev = &state_items[sin];
|
||||||
if (rev->prods)
|
if (rev->prods)
|
||||||
{
|
{
|
||||||
bitset_reset (rev->prods, dsi - state_items);
|
bitset_reset (rev->prods, dsi - state_items);
|
||||||
@@ -466,7 +464,7 @@ prune_disabled_paths (void)
|
|||||||
{
|
{
|
||||||
for (int i = nstate_items - 1; i >= 0; --i)
|
for (int i = nstate_items - 1; i >= 0; --i)
|
||||||
{
|
{
|
||||||
state_item *si = state_items + i;
|
state_item *si = &state_items[i];
|
||||||
if (si->trans == -1 && item_number_is_symbol_number (*si->item))
|
if (si->trans == -1 && item_number_is_symbol_number (*si->item))
|
||||||
{
|
{
|
||||||
prune_forward (si);
|
prune_forward (si);
|
||||||
@@ -477,7 +475,7 @@ prune_disabled_paths (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
print_state_item (const state_item *si, FILE *out, const char *prefix)
|
state_item_print (const state_item *si, FILE *out, const char *prefix)
|
||||||
{
|
{
|
||||||
fputs (prefix, out);
|
fputs (prefix, out);
|
||||||
item_print (si->item, NULL, out);
|
item_print (si->item, NULL, out);
|
||||||
@@ -494,9 +492,9 @@ state_items_report (void)
|
|||||||
for (state_number i = 0; i < nstates; ++i)
|
for (state_number i = 0; i < nstates; ++i)
|
||||||
{
|
{
|
||||||
printf ("State %d:\n", i);
|
printf ("State %d:\n", i);
|
||||||
for (int j = state_item_map[i]; j < state_item_map[i + 1]; ++j)
|
for (state_item_number j = state_item_map[i]; j < state_item_map[i + 1]; ++j)
|
||||||
{
|
{
|
||||||
state_item *si = state_items + j;
|
state_item *si = &state_items[j];
|
||||||
item_print (si->item, NULL, stdout);
|
item_print (si->item, NULL, stdout);
|
||||||
if (SI_DISABLED (j))
|
if (SI_DISABLED (j))
|
||||||
{
|
{
|
||||||
@@ -508,7 +506,7 @@ state_items_report (void)
|
|||||||
if (si->trans >= 0)
|
if (si->trans >= 0)
|
||||||
{
|
{
|
||||||
fputs (" -> ", stdout);
|
fputs (" -> ", stdout);
|
||||||
print_state_item (state_items + si->trans, stdout, "");
|
state_item_print (&state_items[si->trans], stdout, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
bitset sets[2] = { si->prods, si->revs };
|
bitset sets[2] = { si->prods, si->revs };
|
||||||
@@ -523,7 +521,7 @@ state_items_report (void)
|
|||||||
BITSET_FOR_EACH (biter, b, sin, 0)
|
BITSET_FOR_EACH (biter, b, sin, 0)
|
||||||
{
|
{
|
||||||
fputs (txt[seti], stdout);
|
fputs (txt[seti], stdout);
|
||||||
print_state_item (state_items + sin, stdout, "");
|
state_item_print (&state_items[sin], stdout, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -562,10 +560,10 @@ state_items_init (void)
|
|||||||
void
|
void
|
||||||
state_items_free (void)
|
state_items_free (void)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < nstate_items; ++i)
|
for (state_item_number i = 0; i < nstate_items; ++i)
|
||||||
if (!SI_DISABLED (i))
|
if (!SI_DISABLED (i))
|
||||||
{
|
{
|
||||||
state_item *si = state_items + i;
|
state_item *si = &state_items[i];
|
||||||
if (si->prods)
|
if (si->prods)
|
||||||
bitset_free (si->prods);
|
bitset_free (si->prods);
|
||||||
bitset_free (si->revs);
|
bitset_free (si->revs);
|
||||||
@@ -594,5 +592,5 @@ production_allowed (const state_item *si, const state_item *next)
|
|||||||
if (prec1 == prec2 && s1->assoc == left_assoc)
|
if (prec1 == prec2 && s1->assoc == left_assoc)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-9
@@ -28,16 +28,16 @@
|
|||||||
# include "state.h"
|
# include "state.h"
|
||||||
|
|
||||||
/* Initializes a graph connecting (state, production item) pairs to
|
/* Initializes a graph connecting (state, production item) pairs to
|
||||||
pairs they can make a transition or production step to. This graph
|
pairs they can make a transition or production step to. This graph
|
||||||
is used to search for paths that represent counterexamples of some
|
is used to search for paths that represent counterexamples of some
|
||||||
conflict.
|
conflict.
|
||||||
|
|
||||||
state_items is an array of state state-item pairs ordered by state.
|
state_items is an array of state state-item pairs ordered by state.
|
||||||
state_item_map maps state numbers to the first item which
|
state_item_map maps state numbers to the first item which
|
||||||
corresponds to it in the array. A state's portion in state_items
|
corresponds to it in the array. A state's portion in state_items
|
||||||
begins with its items in the same order as it was in the
|
begins with its items in the same order as it was in the state.
|
||||||
state. This is then followed by productions from the closure of the
|
This is then followed by productions from the closure of the state
|
||||||
state in order by rule.
|
in order by rule.
|
||||||
|
|
||||||
There are two type of edges in this graph transitions and
|
There are two type of edges in this graph transitions and
|
||||||
productions. Transitions are the same as transitions from the
|
productions. Transitions are the same as transitions from the
|
||||||
@@ -53,9 +53,9 @@
|
|||||||
production edges, and all others will have reverse transition
|
production edges, and all others will have reverse transition
|
||||||
edges. */
|
edges. */
|
||||||
|
|
||||||
# define SI_DISABLED(sin) (state_items[sin].trans == -2)
|
# define SI_DISABLED(Sin) (state_items[Sin].trans == -2)
|
||||||
# define SI_PRODUCTION(si) ((si) == state_items || *((si)->item - 1) < 0)
|
# define SI_PRODUCTION(Si) ((Si) == state_items || *((Si)->item - 1) < 0)
|
||||||
# define SI_TRANSITION(si) ((si) != state_items && *((si)->item - 1) >= 0)
|
# define SI_TRANSITION(Si) ((Si) != state_items && *((Si)->item - 1) >= 0)
|
||||||
|
|
||||||
typedef int state_item_number;
|
typedef int state_item_number;
|
||||||
|
|
||||||
@@ -69,6 +69,9 @@ typedef struct
|
|||||||
bitset lookahead;
|
bitset lookahead;
|
||||||
} state_item;
|
} state_item;
|
||||||
|
|
||||||
|
// A path of state-items.
|
||||||
|
typedef gl_list_t state_item_list;
|
||||||
|
|
||||||
extern bitsetv firsts;
|
extern bitsetv firsts;
|
||||||
# define FIRSTS(sym) firsts[(sym) - ntokens]
|
# define FIRSTS(sym) firsts[(sym) - ntokens]
|
||||||
|
|
||||||
@@ -87,11 +90,13 @@ state_item_index_lookup (state_number s, state_item_number off)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void state_items_init (void);
|
void state_items_init (void);
|
||||||
void print_state_item (const state_item *si, FILE *out, const char *prefix);
|
|
||||||
void state_items_free (void);
|
void state_items_free (void);
|
||||||
|
|
||||||
|
void state_item_print (const state_item *si, FILE *out, const char *prefix);
|
||||||
|
|
||||||
bool production_allowed (const state_item *si, const state_item *next);
|
bool production_allowed (const state_item *si, const state_item *next);
|
||||||
|
|
||||||
|
// Iterating on a state_item_list.
|
||||||
static inline bool
|
static inline bool
|
||||||
state_item_list_next (gl_list_iterator_t *it, state_item **si)
|
state_item_list_next (gl_list_iterator_t *it, state_item **si)
|
||||||
{
|
{
|
||||||
|
|||||||
+7
-7
@@ -101,7 +101,7 @@ reductions_new (int num, rule **reds)
|
|||||||
size_t rules_size = num * sizeof *reds;
|
size_t rules_size = num * sizeof *reds;
|
||||||
reductions *res = xmalloc (offsetof (reductions, rules) + rules_size);
|
reductions *res = xmalloc (offsetof (reductions, rules) + rules_size);
|
||||||
res->num = num;
|
res->num = num;
|
||||||
res->lookahead_tokens = NULL;
|
res->lookaheads = NULL;
|
||||||
memcpy (res->rules, reds, rules_size);
|
memcpy (res->rules, reds, rules_size);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -260,20 +260,20 @@ state_errs_set (state *s, int num, symbol **tokens)
|
|||||||
`--------------------------------------------------*/
|
`--------------------------------------------------*/
|
||||||
|
|
||||||
void
|
void
|
||||||
state_rule_lookahead_tokens_print (state const *s, rule const *r, FILE *out)
|
state_rule_lookaheads_print (state const *s, rule const *r, FILE *out)
|
||||||
{
|
{
|
||||||
/* Find the reduction we are handling. */
|
/* Find the reduction we are handling. */
|
||||||
reductions *reds = s->reductions;
|
reductions *reds = s->reductions;
|
||||||
int red = state_reduction_find (s, r);
|
int red = state_reduction_find (s, r);
|
||||||
|
|
||||||
/* Print them if there are. */
|
/* Print them if there are. */
|
||||||
if (reds->lookahead_tokens && red != -1)
|
if (reds->lookaheads && red != -1)
|
||||||
{
|
{
|
||||||
bitset_iterator biter;
|
bitset_iterator biter;
|
||||||
int k;
|
int k;
|
||||||
char const *sep = "";
|
char const *sep = "";
|
||||||
fprintf (out, " [");
|
fprintf (out, " [");
|
||||||
BITSET_FOR_EACH (biter, reds->lookahead_tokens[red], k, 0)
|
BITSET_FOR_EACH (biter, reds->lookaheads[red], k, 0)
|
||||||
{
|
{
|
||||||
fprintf (out, "%s%s", sep, symbols[k]->tag);
|
fprintf (out, "%s%s", sep, symbols[k]->tag);
|
||||||
sep = ", ";
|
sep = ", ";
|
||||||
@@ -283,7 +283,7 @@ state_rule_lookahead_tokens_print (state const *s, rule const *r, FILE *out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
state_rule_lookahead_tokens_print_xml (state const *s, rule const *r,
|
state_rule_lookaheads_print_xml (state const *s, rule const *r,
|
||||||
FILE *out, int level)
|
FILE *out, int level)
|
||||||
{
|
{
|
||||||
/* Find the reduction we are handling. */
|
/* Find the reduction we are handling. */
|
||||||
@@ -291,12 +291,12 @@ state_rule_lookahead_tokens_print_xml (state const *s, rule const *r,
|
|||||||
int red = state_reduction_find (s, r);
|
int red = state_reduction_find (s, r);
|
||||||
|
|
||||||
/* Print them if there are. */
|
/* Print them if there are. */
|
||||||
if (reds->lookahead_tokens && red != -1)
|
if (reds->lookaheads && red != -1)
|
||||||
{
|
{
|
||||||
bitset_iterator biter;
|
bitset_iterator biter;
|
||||||
int k;
|
int k;
|
||||||
xml_puts (out, level, "<lookaheads>");
|
xml_puts (out, level, "<lookaheads>");
|
||||||
BITSET_FOR_EACH (biter, reds->lookahead_tokens[red], k, 0)
|
BITSET_FOR_EACH (biter, reds->lookaheads[red], k, 0)
|
||||||
{
|
{
|
||||||
xml_printf (out, level + 1, "<symbol>%s</symbol>",
|
xml_printf (out, level + 1, "<symbol>%s</symbol>",
|
||||||
xml_escape (symbols[k]->tag));
|
xml_escape (symbols[k]->tag));
|
||||||
|
|||||||
+5
-5
@@ -62,7 +62,7 @@
|
|||||||
|
|
||||||
Each reductions structure describes the possible reductions at the
|
Each reductions structure describes the possible reductions at the
|
||||||
state whose number is in the number field. rules is an array of
|
state whose number is in the number field. rules is an array of
|
||||||
num rules. lookahead_tokens is an array of bitsets, one per rule.
|
num rules. lookaheads is an array of bitsets, one per rule.
|
||||||
|
|
||||||
Conflict resolution can decide that certain tokens in certain
|
Conflict resolution can decide that certain tokens in certain
|
||||||
states should explicitly be errors (for implementing %nonassoc).
|
states should explicitly be errors (for implementing %nonassoc).
|
||||||
@@ -187,7 +187,7 @@ errs *errs_new (int num, symbol **tokens);
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int num;
|
int num;
|
||||||
bitset *lookahead_tokens;
|
bitset *lookaheads;
|
||||||
/* Sorted ascendingly on rule number. */
|
/* Sorted ascendingly on rule number. */
|
||||||
rule *rules[1];
|
rule *rules[1];
|
||||||
} reductions;
|
} reductions;
|
||||||
@@ -254,9 +254,9 @@ void state_errs_set (state *s, int num, symbol **errors);
|
|||||||
|
|
||||||
/* Print on OUT all the lookahead tokens such that this STATE wants to
|
/* Print on OUT all the lookahead tokens such that this STATE wants to
|
||||||
reduce R. */
|
reduce R. */
|
||||||
void state_rule_lookahead_tokens_print (state const *s, rule const *r, FILE *out);
|
void state_rule_lookaheads_print (state const *s, rule const *r, FILE *out);
|
||||||
void state_rule_lookahead_tokens_print_xml (state const *s, rule const *r,
|
void state_rule_lookaheads_print_xml (state const *s, rule const *r,
|
||||||
FILE *out, int level);
|
FILE *out, int level);
|
||||||
|
|
||||||
/* Create/destroy the states hash table. */
|
/* Create/destroy the states hash table. */
|
||||||
void state_hash_new (void);
|
void state_hash_new (void);
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
/* Convert version string to int.
|
||||||
|
|
||||||
|
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of Bison, the GNU Compiler Compiler.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include "system.h"
|
||||||
|
|
||||||
|
#include "strversion.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <intprops.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
strversion_to_int (char const *version)
|
||||||
|
{
|
||||||
|
IGNORE_TYPE_LIMITS_BEGIN
|
||||||
|
int res = 0;
|
||||||
|
errno = 0;
|
||||||
|
char *cp = NULL;
|
||||||
|
|
||||||
|
{
|
||||||
|
long major = strtol (version, &cp, 10);
|
||||||
|
if (errno || cp == version || *cp != '.' || major < 0
|
||||||
|
|| INT_MULTIPLY_WRAPV (major, 10000, &res))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
++cp;
|
||||||
|
char *prev = cp;
|
||||||
|
long minor = strtol (cp, &cp, 10);
|
||||||
|
if (errno || cp == prev || (*cp != '\0' && *cp != '.')
|
||||||
|
|| ! (0 <= minor && minor < 100)
|
||||||
|
|| INT_MULTIPLY_WRAPV (minor, 100, &minor)
|
||||||
|
|| INT_ADD_WRAPV (minor, res, &res))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*cp == '.')
|
||||||
|
{
|
||||||
|
++cp;
|
||||||
|
char *prev = cp;
|
||||||
|
long micro = strtol (cp, &cp, 10);
|
||||||
|
if (errno || cp == prev || (*cp != '\0' && *cp != '.')
|
||||||
|
|| ! (0 <= micro && micro < 100)
|
||||||
|
|| INT_ADD_WRAPV (micro, res, &res))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
IGNORE_TYPE_LIMITS_END
|
||||||
|
return res;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/* Convert version string to int.
|
||||||
|
|
||||||
|
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of Bison, the GNU Compiler Compiler.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef STRVERSION_H_
|
||||||
|
# define STRVERSION_H_
|
||||||
|
|
||||||
|
/* Convert VERSION into an int (MAJOR * 10000 + MINOR * 100 + MICRO).
|
||||||
|
E.g., "3.7.4" => 30704, "3.8" => 30800.
|
||||||
|
Return -1 on errors. */
|
||||||
|
int strversion_to_int (char const *version);
|
||||||
|
|
||||||
|
#endif
|
||||||
+2
-2
@@ -83,10 +83,10 @@ symbol_list_type_new (uniqstr type_name, location loc)
|
|||||||
|
|
||||||
|
|
||||||
symbol_list *
|
symbol_list *
|
||||||
symbol_list_type_set (symbol_list *syms, uniqstr type_name, location loc)
|
symbol_list_type_set (symbol_list *syms, uniqstr type_name)
|
||||||
{
|
{
|
||||||
for (symbol_list *l = syms; l; l = l->next)
|
for (symbol_list *l = syms; l; l = l->next)
|
||||||
symbol_type_set (l->content.sym, type_name, loc);
|
symbol_type_set (l->content.sym, type_name, l->sym_loc);
|
||||||
return syms;
|
return syms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -110,8 +110,7 @@ symbol_list *symbol_list_type_new (uniqstr type_name, location loc);
|
|||||||
|
|
||||||
/** Assign the type \c type_name to all the members of \c syms.
|
/** Assign the type \c type_name to all the members of \c syms.
|
||||||
** \returns \c syms */
|
** \returns \c syms */
|
||||||
symbol_list *symbol_list_type_set (symbol_list *syms,
|
symbol_list *symbol_list_type_set (symbol_list *syms, uniqstr type_name);
|
||||||
uniqstr type_name, location loc);
|
|
||||||
|
|
||||||
/** Print this list.
|
/** Print this list.
|
||||||
|
|
||||||
|
|||||||
+33
-36
@@ -59,7 +59,7 @@ static semantic_type **semantic_types_sorted = NULL;
|
|||||||
symbol *errtoken = NULL;
|
symbol *errtoken = NULL;
|
||||||
symbol *undeftoken = NULL;
|
symbol *undeftoken = NULL;
|
||||||
symbol *eoftoken = NULL;
|
symbol *eoftoken = NULL;
|
||||||
symbol *accept = NULL;
|
symbol *acceptsymbol = NULL;
|
||||||
symbol *startsymbol = NULL;
|
symbol *startsymbol = NULL;
|
||||||
location startsymbol_loc;
|
location startsymbol_loc;
|
||||||
|
|
||||||
@@ -137,11 +137,6 @@ symbol_new (uniqstr tag, location loc)
|
|||||||
res->alias = NULL;
|
res->alias = NULL;
|
||||||
res->content = sym_content_new (res);
|
res->content = sym_content_new (res);
|
||||||
res->is_alias = false;
|
res->is_alias = false;
|
||||||
|
|
||||||
if (nsyms == SYMBOL_NUMBER_MAXIMUM)
|
|
||||||
complain (NULL, fatal, _("too many symbols in input grammar (limit is %d)"),
|
|
||||||
SYMBOL_NUMBER_MAXIMUM);
|
|
||||||
nsyms++;
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,11 +177,11 @@ symbol_free (void *ptr)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
symbols_sort (symbol **first, symbol **second)
|
symbols_sort (const symbol **first, const symbol **second)
|
||||||
{
|
{
|
||||||
if (0 < location_cmp ((*first)->location, (*second)->location))
|
if (0 < location_cmp ((*first)->location, (*second)->location))
|
||||||
{
|
{
|
||||||
symbol* tmp = *first;
|
const symbol* tmp = *first;
|
||||||
*first = *second;
|
*first = *second;
|
||||||
*second = tmp;
|
*second = tmp;
|
||||||
}
|
}
|
||||||
@@ -243,7 +238,11 @@ semantic_type_new (uniqstr tag, const location *loc)
|
|||||||
| Print a symbol. |
|
| Print a symbol. |
|
||||||
`-----------------*/
|
`-----------------*/
|
||||||
|
|
||||||
#define SYMBOL_ATTR_PRINT(Attr) \
|
#define SYMBOL_INT_ATTR_PRINT(Attr) \
|
||||||
|
if (s->content) \
|
||||||
|
fprintf (f, " %s = %d", #Attr, s->content->Attr)
|
||||||
|
|
||||||
|
#define SYMBOL_STR_ATTR_PRINT(Attr) \
|
||||||
if (s->content && s->content->Attr) \
|
if (s->content && s->content->Attr) \
|
||||||
fprintf (f, " %s { %s }", #Attr, s->content->Attr)
|
fprintf (f, " %s { %s }", #Attr, s->content->Attr)
|
||||||
|
|
||||||
@@ -264,7 +263,11 @@ symbol_print (symbol const *s, FILE *f)
|
|||||||
: c == nterm_sym ? "nterm"
|
: c == nterm_sym ? "nterm"
|
||||||
: NULL, /* abort. */
|
: NULL, /* abort. */
|
||||||
s->tag);
|
s->tag);
|
||||||
SYMBOL_ATTR_PRINT (type_name);
|
putc (' ', f);
|
||||||
|
location_print (s->location, f);
|
||||||
|
SYMBOL_INT_ATTR_PRINT (code);
|
||||||
|
SYMBOL_INT_ATTR_PRINT (number);
|
||||||
|
SYMBOL_STR_ATTR_PRINT (type_name);
|
||||||
SYMBOL_CODE_PRINT (destructor);
|
SYMBOL_CODE_PRINT (destructor);
|
||||||
SYMBOL_CODE_PRINT (printer);
|
SYMBOL_CODE_PRINT (printer);
|
||||||
}
|
}
|
||||||
@@ -371,7 +374,7 @@ symbol_from_uniqstr_fuzzy (const uniqstr key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
complain_symbol_undeclared (symbol *sym)
|
complain_symbol_undeclared (const symbol *sym)
|
||||||
{
|
{
|
||||||
assert (sym->content->status != declared);
|
assert (sym->content->status != declared);
|
||||||
const symbol *best = symbol_from_uniqstr_fuzzy (sym->tag);
|
const symbol *best = symbol_from_uniqstr_fuzzy (sym->tag);
|
||||||
@@ -398,7 +401,10 @@ void
|
|||||||
symbol_location_as_lhs_set (symbol *sym, location loc)
|
symbol_location_as_lhs_set (symbol *sym, location loc)
|
||||||
{
|
{
|
||||||
if (!sym->location_of_lhs)
|
if (!sym->location_of_lhs)
|
||||||
sym->location = loc;
|
{
|
||||||
|
sym->location = loc;
|
||||||
|
sym->location_of_lhs = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -548,10 +554,6 @@ symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring)
|
|||||||
if (class == token_sym && s->class == pct_type_sym)
|
if (class == token_sym && s->class == pct_type_sym)
|
||||||
complain_pct_type_on_token (&sym->location);
|
complain_pct_type_on_token (&sym->location);
|
||||||
|
|
||||||
if (class == nterm_sym && s->class != nterm_sym)
|
|
||||||
s->number = nnterms++;
|
|
||||||
else if (class == token_sym && s->number == NUMBER_UNDEFINED)
|
|
||||||
s->number = ntokens++;
|
|
||||||
s->class = class;
|
s->class = class;
|
||||||
|
|
||||||
if (declaring)
|
if (declaring)
|
||||||
@@ -573,9 +575,9 @@ symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------.
|
/*----------------------------.
|
||||||
| Set the USER_TOKEN_NUMBER associated with SYM. |
|
| Set the token code of SYM. |
|
||||||
`------------------------------------------------*/
|
`----------------------------*/
|
||||||
|
|
||||||
void
|
void
|
||||||
symbol_code_set (symbol *sym, int code, location loc)
|
symbol_code_set (symbol *sym, int code, location loc)
|
||||||
@@ -598,10 +600,6 @@ symbol_code_set (symbol *sym, int code, location loc)
|
|||||||
if (code == 0 && !eoftoken)
|
if (code == 0 && !eoftoken)
|
||||||
{
|
{
|
||||||
eoftoken = sym->content->symbol;
|
eoftoken = sym->content->symbol;
|
||||||
/* It is always mapped to 0, so it was already counted in
|
|
||||||
NTOKENS. */
|
|
||||||
if (eoftoken->content->number != NUMBER_UNDEFINED)
|
|
||||||
--ntokens;
|
|
||||||
eoftoken->content->number = 0;
|
eoftoken->content->number = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -621,9 +619,11 @@ symbol_check_defined (symbol *sym)
|
|||||||
{
|
{
|
||||||
complain_symbol_undeclared (sym);
|
complain_symbol_undeclared (sym);
|
||||||
s->class = nterm_sym;
|
s->class = nterm_sym;
|
||||||
s->number = nnterms++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s->number == NUMBER_UNDEFINED)
|
||||||
|
s->number = s->class == token_sym ? ntokens++ : nnterms++;
|
||||||
|
|
||||||
if (s->class == token_sym
|
if (s->class == token_sym
|
||||||
&& sym->tag[0] == '"'
|
&& sym->tag[0] == '"'
|
||||||
&& !sym->is_alias)
|
&& !sym->is_alias)
|
||||||
@@ -742,7 +742,7 @@ symbol_pack (symbol *sym)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
complain_code_redeclared (int num, symbol *first, symbol *second)
|
complain_code_redeclared (int num, const symbol *first, const symbol *second)
|
||||||
{
|
{
|
||||||
symbols_sort (&first, &second);
|
symbols_sort (&first, &second);
|
||||||
complain (&second->location, complaint,
|
complain (&second->location, complaint,
|
||||||
@@ -758,13 +758,11 @@ complain_code_redeclared (int num, symbol *first, symbol *second)
|
|||||||
`-------------------------------------------------*/
|
`-------------------------------------------------*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
symbol_translation (symbol *sym)
|
symbol_translation (const symbol *sym)
|
||||||
{
|
{
|
||||||
/* Nonterminal? */
|
if (sym->content->class == token_sym && !sym->is_alias)
|
||||||
if (sym->content->class == token_sym
|
|
||||||
&& !sym->is_alias)
|
|
||||||
{
|
{
|
||||||
/* A token which translation has already been set?*/
|
/* A token whose translation has already been set? */
|
||||||
if (token_translations[sym->content->code]
|
if (token_translations[sym->content->code]
|
||||||
!= undeftoken->content->number)
|
!= undeftoken->content->number)
|
||||||
complain_code_redeclared
|
complain_code_redeclared
|
||||||
@@ -849,10 +847,10 @@ symbols_new (void)
|
|||||||
hash_symbol_comparator,
|
hash_symbol_comparator,
|
||||||
symbol_free);
|
symbol_free);
|
||||||
|
|
||||||
/* Construct the accept symbol. */
|
/* Construct the acceptsymbol symbol. */
|
||||||
accept = symbol_get ("$accept", empty_loc);
|
acceptsymbol = symbol_get ("$accept", empty_loc);
|
||||||
accept->content->class = nterm_sym;
|
acceptsymbol->content->class = nterm_sym;
|
||||||
accept->content->number = nnterms++;
|
acceptsymbol->content->number = nnterms++;
|
||||||
|
|
||||||
/* Construct the YYerror/"error" token */
|
/* Construct the YYerror/"error" token */
|
||||||
errtoken = symbol_get ("YYerror", empty_loc);
|
errtoken = symbol_get ("YYerror", empty_loc);
|
||||||
@@ -969,7 +967,6 @@ dummy_symbol_get (location loc)
|
|||||||
assure (len < sizeof buf);
|
assure (len < sizeof buf);
|
||||||
symbol *sym = symbol_get (buf, loc);
|
symbol *sym = symbol_get (buf, loc);
|
||||||
sym->content->class = nterm_sym;
|
sym->content->class = nterm_sym;
|
||||||
sym->content->number = nnterms++;
|
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1002,7 +999,7 @@ symbol_cmp (void const *a, void const *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Store in *SORTED an array of pointers to the symbols contained in
|
/* Store in *SORTED an array of pointers to the symbols contained in
|
||||||
TABLE, sorted (alphabetically) by tag. */
|
TABLE, sorted by order of appearance (i.e., by location). */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
table_sort (struct hash_table *table, symbol ***sorted)
|
table_sort (struct hash_table *table, symbol ***sorted)
|
||||||
|
|||||||
+2
-2
@@ -227,7 +227,7 @@ void symbol_precedence_set (symbol *sym, int prec, assoc a, location loc);
|
|||||||
void symbol_class_set (symbol *sym, symbol_class class, location loc,
|
void symbol_class_set (symbol *sym, symbol_class class, location loc,
|
||||||
bool declaring);
|
bool declaring);
|
||||||
|
|
||||||
/** Set the \c code associated with \c sym. */
|
/** Set the token \c code of \c sym, specified by the user at \c loc. */
|
||||||
void symbol_code_set (symbol *sym, int code, location loc);
|
void symbol_code_set (symbol *sym, int code, location loc);
|
||||||
|
|
||||||
|
|
||||||
@@ -245,7 +245,7 @@ extern symbol *eoftoken;
|
|||||||
/** The genuine start symbol.
|
/** The genuine start symbol.
|
||||||
|
|
||||||
$accept: start-symbol $end */
|
$accept: start-symbol $end */
|
||||||
extern symbol *accept;
|
extern symbol *acceptsymbol;
|
||||||
|
|
||||||
/** The user start symbol. */
|
/** The user start symbol. */
|
||||||
extern symbol *startsymbol;
|
extern symbol *startsymbol;
|
||||||
|
|||||||
@@ -131,6 +131,22 @@ typedef size_t uintptr_t;
|
|||||||
# include <stdbool.h>
|
# include <stdbool.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------.
|
||||||
|
| Integers. |
|
||||||
|
`-----------*/
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
min_int (int a, int b)
|
||||||
|
{
|
||||||
|
return a < b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
max_int (int a, int b)
|
||||||
|
{
|
||||||
|
return a >= b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------.
|
/*-------------.
|
||||||
| Assertions. |
|
| Assertions. |
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user