mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-08-09 10:45:15 +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 |
+1
-1
@@ -1 +1 @@
|
||||
3.6.93
|
||||
3.7.3
|
||||
|
||||
+4
-1
@@ -50,6 +50,7 @@ jobs:
|
||||
- make -j2 dist-xz
|
||||
# Can help understanding why we get "dirty" tarballs.
|
||||
- git status
|
||||
- git diff
|
||||
- dist=$(echo bison*.xz)
|
||||
|
||||
# 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++'
|
||||
- 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"
|
||||
stage: check
|
||||
os: linux
|
||||
@@ -127,7 +130,7 @@ jobs:
|
||||
- CC=icc
|
||||
- CXX=icpc
|
||||
install:
|
||||
- source /opt/intel/inteloneapi/compiler/latest/env/vars.sh
|
||||
- source /opt/intel/oneapi/compiler/latest/env/vars.sh
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
|
||||
@@ -1,5 +1,83 @@
|
||||
GNU Bison NEWS
|
||||
|
||||
* 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
|
||||
@@ -537,7 +615,8 @@ GNU Bison NEWS
|
||||
\005) with incorrect styling. Fixes for similar issues with unexpectedly
|
||||
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]
|
||||
|
||||
@@ -27,7 +27,7 @@ Bison from the git repo. Roughly, run:
|
||||
then proceed with the usual `configure && make` steps.
|
||||
|
||||
## Build from tarball
|
||||
See the [INSTALL file](INSTALL] for generic compilation and installation
|
||||
See the [INSTALL file](INSTALL) for generic compilation and installation
|
||||
instructions.
|
||||
|
||||
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
|
||||
`--color` and `--style` options.
|
||||
|
||||
To use them, install the libtextstyle library before configuring Bison. It
|
||||
is available from https://alpha.gnu.org/gnu/gettext/, for instance
|
||||
https://alpha.gnu.org/pub/gnu/gettext/libtextstyle-0.20.5.tar.gz.
|
||||
To use them, install the libtextstyle library, 0.20.5 or newer, before
|
||||
configuring Bison. It is available from https://alpha.gnu.org/gnu/gettext/,
|
||||
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:
|
||||
- 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`
|
||||
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
|
||||
If you pass `--enable-relocatable` to `configure`, Bison is relocatable.
|
||||
|
||||
|
||||
@@ -106,9 +106,11 @@ Keith Browne [email protected]
|
||||
Ken Moffat [email protected]
|
||||
Kiyoshi Kanazawa [email protected]
|
||||
Lars Maier [email protected]
|
||||
Lars Wendler [email protected]
|
||||
László Várady [email protected]
|
||||
Laurent Mascherpa [email protected]
|
||||
Lie Yan [email protected]
|
||||
Maarten De Braekeleer [email protected]
|
||||
Magnus Fromreide [email protected]
|
||||
Marc Autret [email protected]
|
||||
Marc Mendiola [email protected]
|
||||
@@ -185,6 +187,7 @@ Simon Sobisch [email protected]
|
||||
Stefano Lattarini [email protected]
|
||||
Stephen Cameron [email protected]
|
||||
Steve Murphy [email protected]
|
||||
Suhwan Song [email protected]
|
||||
Sum Wu [email protected]
|
||||
Théophile Ranquet [email protected]
|
||||
Thiru Ramakrishnan [email protected]
|
||||
|
||||
@@ -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
|
||||
*** Improve gnulib
|
||||
Don't do this (counterexample.c):
|
||||
@@ -48,13 +56,6 @@ Unless we play it dumb (little structure).
|
||||
|
||||
- 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
|
||||
https://git.savannah.gnu.org/gitweb/?p=gettext.git;a=blob;f=gettext-runtime/intl/plural.y;h=a712255af4f2f739c93336d4ff6556d932a426a5;hb=HEAD
|
||||
|
||||
@@ -67,7 +68,7 @@ Stop hard-coding "Calc". Adjust local.at (look for FIXME).
|
||||
|
||||
** A dev warning for b4_
|
||||
Maybe we should check for m4_ and b4_ leaking out of the m4 processing, as
|
||||
Autoconf does. It would have caught overquotation issues.
|
||||
Autoconf does. It would have caught over-quotation issues.
|
||||
|
||||
** doc
|
||||
I feel it's ugly to use the GNU style to declare functions in the doc. It
|
||||
@@ -88,7 +89,7 @@ push parsers on top of pull parser. Which is currently not relevant, since
|
||||
push parsers are measurably slower.
|
||||
|
||||
** %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
|
||||
providing the message formats? Currently in bistro, it reads:
|
||||
|
||||
@@ -202,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
|
||||
"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.
|
||||
|
||||
*** complain.*
|
||||
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.
|
||||
|
||||
*** ritem
|
||||
states/nstates, rules/nrules, ..., ritem/nritems
|
||||
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
|
||||
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
|
||||
@@ -231,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.
|
||||
|
||||
* Completion
|
||||
Several features are not available in all the backends.
|
||||
Several features are not available in all the back-ends.
|
||||
|
||||
- lac: D, Java (easy)
|
||||
- push parsers: glr.c, glr.cc, lalr1.cc (not very difficult)
|
||||
@@ -301,7 +566,7 @@ opposite side we have some use of \l, which is graphviz-specific, in what
|
||||
should be generic code.
|
||||
|
||||
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.
|
||||
|
||||
Since graphviz dies on medium-to-big grammars, maybe consider an other tool?
|
||||
@@ -579,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.
|
||||
|
||||
|
||||
-----
|
||||
|
||||
# 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:
|
||||
mode: outline
|
||||
coding: utf-8
|
||||
fill-column: 76
|
||||
ispell-dictionary: "american"
|
||||
End:
|
||||
|
||||
-----
|
||||
|
||||
Copyright (C) 2001-2004, 2006, 2008-2015, 2018-2020 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
|
||||
@@ -45,6 +45,8 @@ gnulib_modules='
|
||||
relocatable-prog relocatable-script
|
||||
rename
|
||||
spawn-pipe stdbool stpcpy stpncpy strdup-posix strerror strverscmp
|
||||
sys_ioctl
|
||||
termios
|
||||
timevar
|
||||
unicodeio unistd unistd-safer unlink unlocked-io
|
||||
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 = \
|
||||
(^ *\#|(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.
|
||||
sc_space_before_open_paren:
|
||||
@if $(VC_LIST_EXCEPT) | grep -l '\.[ch]$$' > /dev/null; then \
|
||||
@@ -156,6 +156,7 @@ exclude = \
|
||||
$(call exclude, \
|
||||
bindtextdomain=^lib/main.c$$ \
|
||||
cast_of_argument_to_free=^src/muscle-tab.c$$ \
|
||||
error_message_uppercase=etc/bench.pl.in$$ \
|
||||
po_check=^tests|(^po/POTFILES.in|.md)$$ \
|
||||
preprocessor_indentation=^data/|^lib/|^src/parse-gram.[ch]$$ \
|
||||
program_name=^lib/main.c$$ \
|
||||
|
||||
@@ -60,6 +60,9 @@ AC_PROG_CXX
|
||||
# Gnulib (early checks).
|
||||
gl_EARLY
|
||||
|
||||
# We want ostream_printf and hyperlink support.
|
||||
gl_LIBTEXTSTYLE_OPTIONAL([0.20.5])
|
||||
|
||||
# Gnulib uses '#pragma GCC diagnostic push' to silence some
|
||||
# warnings, but older gcc doesn't support this.
|
||||
AC_CACHE_CHECK([whether pragma GCC diagnostic push works],
|
||||
|
||||
@@ -49,7 +49,7 @@ m4_define([m4_shift4], [m4_shift(m4_shift(m4_shift(m4_shift($@))))])
|
||||
# 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])
|
||||
@@ -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.
|
||||
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.
|
||||
basic_symbol (const basic_symbol& that);]b4_variant_if([[
|
||||
|
||||
/// Constructor for valueless symbols, and symbols from each type.
|
||||
]b4_type_foreach([b4_basic_symbol_constructor_define])], [[
|
||||
/// Constructors for typed symbols.
|
||||
]b4_type_foreach([b4_basic_symbol_constructor_define], [
|
||||
])], [[
|
||||
/// Constructor for valueless symbols.
|
||||
basic_symbol (typename Base::kind_type t]b4_locations_if([,
|
||||
YY_MOVE_REF (location_type) l])[);
|
||||
|
||||
+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
|
||||
# api.push-pull.
|
||||
m4_define([b4_identification],
|
||||
[[/* Identify Bison output. */
|
||||
#define YYBISON 1
|
||||
[[/* Identify Bison output, and Bison version. */
|
||||
#define YYBISON ]b4_version[
|
||||
|
||||
/* Bison version. */
|
||||
#define YYBISON_VERSION "]b4_version["
|
||||
/* Bison version string. */
|
||||
#define YYBISON_VERSION "]b4_version_string["
|
||||
|
||||
/* Skeleton name. */
|
||||
#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.
|
||||
m4_define([b4_token_defines],
|
||||
[b4_any_token_visible_if([/* Token kinds. */
|
||||
m4_join([
|
||||
[[/* Token kinds. */
|
||||
#define ]b4_symbol([-2], [id])[ -2
|
||||
]m4_join([
|
||||
], b4_symbol_map([b4_token_define]))
|
||||
])])
|
||||
])
|
||||
|
||||
|
||||
# b4_token_enum(TOKEN-NUM)
|
||||
|
||||
+4
-4
@@ -103,12 +103,12 @@ m4_define([b4_location_type_if],
|
||||
# b4_identification
|
||||
# -----------------
|
||||
m4_define([b4_identification],
|
||||
[/** Version number for the Bison executable that generated this parser. */
|
||||
public static immutable string yy_bison_version = "b4_version";
|
||||
[[/** Version number for the Bison executable that generated this parser. */
|
||||
public static immutable string yy_bison_version = "]b4_version_string[";
|
||||
|
||||
/** 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[;
|
||||
]])
|
||||
|
||||
|
||||
## ------------ ##
|
||||
|
||||
@@ -172,7 +172,7 @@ m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
|
||||
const location_type* yylocationp]])[) const
|
||||
{
|
||||
*yycdebug_ << (yykind < YYNTOKENS ? "token" : "nterm")
|
||||
<< ' ' << yytname[yykind] << " ("]b4_locations_if([[
|
||||
<< ' ' << yysymbol_name (yykind) << " ("]b4_locations_if([[
|
||||
<< *yylocationp << ": "]])[;
|
||||
yy_symbol_value_print_ (yykind, yyvaluep]b4_locations_if([[, yylocationp]])[);
|
||||
*yycdebug_ << ')';
|
||||
|
||||
@@ -71,12 +71,12 @@ m4_define([b4_lexer_if],
|
||||
# b4_identification
|
||||
# -----------------
|
||||
m4_define([b4_identification],
|
||||
[ /** Version number for the Bison executable that generated this parser. */
|
||||
public static final String bisonVersion = "b4_version";
|
||||
[[ /** Version number for the Bison executable that generated this parser. */
|
||||
public static final String bisonVersion = "]b4_version_string[";
|
||||
|
||||
/** Name of the skeleton that generated this parser. */
|
||||
public static final String bisonSkeleton = b4_skeleton;
|
||||
])
|
||||
public static final String bisonSkeleton = ]b4_skeleton[;
|
||||
]])
|
||||
|
||||
|
||||
## ------------ ##
|
||||
|
||||
@@ -22,7 +22,7 @@ m4_pushdef([b4_copyright_years],
|
||||
# b4_position_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])])])])
|
||||
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
# b4_stack_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])])])
|
||||
|
||||
|
||||
|
||||
+101
-41
@@ -20,6 +20,13 @@
|
||||
## variant. ##
|
||||
## --------- ##
|
||||
|
||||
# b4_assert
|
||||
# ---------
|
||||
# The name of YY_ASSERT.
|
||||
m4_define([b4_assert],
|
||||
[b4_api_PREFIX[]_ASSERT])
|
||||
|
||||
|
||||
# b4_symbol_variant(YYTYPE, YYVAL, ACTION, [ARGS])
|
||||
# ------------------------------------------------
|
||||
# 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.
|
||||
m4_define([b4_variant_includes],
|
||||
[b4_parse_assert_if([[#include <typeinfo>]])[
|
||||
#ifndef YY_ASSERT
|
||||
[b4_parse_assert_if([[#include <typeinfo>
|
||||
#ifndef ]b4_assert[
|
||||
# include <cassert>
|
||||
# define YY_ASSERT assert
|
||||
# define ]b4_assert[ assert
|
||||
#endif
|
||||
]])
|
||||
]])])
|
||||
|
||||
|
||||
|
||||
@@ -110,8 +117,8 @@ m4_define([b4_value_type_declare],
|
||||
template <typename T>
|
||||
semantic_type (YY_RVREF (T) t)]b4_parse_assert_if([
|
||||
: yytypeid_ (&typeid (T))])[
|
||||
{
|
||||
YY_ASSERT (sizeof (T) <= size);
|
||||
{]b4_parse_assert_if([[
|
||||
]b4_assert[ (sizeof (T) <= size);]])[
|
||||
new (yyas_<T> ()) T (YY_MOVE (t));
|
||||
}
|
||||
|
||||
@@ -125,7 +132,7 @@ m4_define([b4_value_type_declare],
|
||||
/// Destruction, allowed only if empty.
|
||||
~semantic_type () YY_NOEXCEPT
|
||||
{]b4_parse_assert_if([
|
||||
YY_ASSERT (!yytypeid_);
|
||||
]b4_assert[ (!yytypeid_);
|
||||
])[}
|
||||
|
||||
# if 201103L <= YY_CPLUSPLUS
|
||||
@@ -133,10 +140,10 @@ m4_define([b4_value_type_declare],
|
||||
template <typename T, typename... U>
|
||||
T&
|
||||
emplace (U&&... u)
|
||||
{]b4_parse_assert_if([
|
||||
YY_ASSERT (!yytypeid_);
|
||||
YY_ASSERT (sizeof (T) <= size);
|
||||
yytypeid_ = & typeid (T);])[
|
||||
{]b4_parse_assert_if([[
|
||||
]b4_assert[ (!yytypeid_);
|
||||
]b4_assert[ (sizeof (T) <= size);
|
||||
yytypeid_ = & typeid (T);]])[
|
||||
return *new (yyas_<T> ()) T (std::forward <U>(u)...);
|
||||
}
|
||||
# else
|
||||
@@ -144,10 +151,10 @@ m4_define([b4_value_type_declare],
|
||||
template <typename T>
|
||||
T&
|
||||
emplace ()
|
||||
{]b4_parse_assert_if([
|
||||
YY_ASSERT (!yytypeid_);
|
||||
YY_ASSERT (sizeof (T) <= size);
|
||||
yytypeid_ = & typeid (T);])[
|
||||
{]b4_parse_assert_if([[
|
||||
]b4_assert[ (!yytypeid_);
|
||||
]b4_assert[ (sizeof (T) <= size);
|
||||
yytypeid_ = & typeid (T);]])[
|
||||
return *new (yyas_<T> ()) T ();
|
||||
}
|
||||
|
||||
@@ -155,10 +162,10 @@ m4_define([b4_value_type_declare],
|
||||
template <typename T>
|
||||
T&
|
||||
emplace (const T& t)
|
||||
{]b4_parse_assert_if([
|
||||
YY_ASSERT (!yytypeid_);
|
||||
YY_ASSERT (sizeof (T) <= size);
|
||||
yytypeid_ = & typeid (T);])[
|
||||
{]b4_parse_assert_if([[
|
||||
]b4_assert[ (!yytypeid_);
|
||||
]b4_assert[ (sizeof (T) <= size);
|
||||
yytypeid_ = & typeid (T);]])[
|
||||
return *new (yyas_<T> ()) T (t);
|
||||
}
|
||||
# endif
|
||||
@@ -185,10 +192,10 @@ m4_define([b4_value_type_declare],
|
||||
template <typename T>
|
||||
T&
|
||||
as () YY_NOEXCEPT
|
||||
{]b4_parse_assert_if([
|
||||
YY_ASSERT (yytypeid_);
|
||||
YY_ASSERT (*yytypeid_ == typeid (T));
|
||||
YY_ASSERT (sizeof (T) <= size);])[
|
||||
{]b4_parse_assert_if([[
|
||||
]b4_assert[ (yytypeid_);
|
||||
]b4_assert[ (*yytypeid_ == typeid (T));
|
||||
]b4_assert[ (sizeof (T) <= size);]])[
|
||||
return *yyas_<T> ();
|
||||
}
|
||||
|
||||
@@ -196,10 +203,10 @@ m4_define([b4_value_type_declare],
|
||||
template <typename T>
|
||||
const T&
|
||||
as () const YY_NOEXCEPT
|
||||
{]b4_parse_assert_if([
|
||||
YY_ASSERT (yytypeid_);
|
||||
YY_ASSERT (*yytypeid_ == typeid (T));
|
||||
YY_ASSERT (sizeof (T) <= size);])[
|
||||
{]b4_parse_assert_if([[
|
||||
]b4_assert[ (yytypeid_);
|
||||
]b4_assert[ (*yytypeid_ == typeid (T));
|
||||
]b4_assert[ (sizeof (T) <= size);]])[
|
||||
return *yyas_<T> ();
|
||||
}
|
||||
|
||||
@@ -214,9 +221,9 @@ m4_define([b4_value_type_declare],
|
||||
template <typename T>
|
||||
void
|
||||
swap (self_type& that) YY_NOEXCEPT
|
||||
{]b4_parse_assert_if([
|
||||
YY_ASSERT (yytypeid_);
|
||||
YY_ASSERT (*yytypeid_ == *that.yytypeid_);])[
|
||||
{]b4_parse_assert_if([[
|
||||
]b4_assert[ (yytypeid_);
|
||||
]b4_assert[ (*yytypeid_ == *that.yytypeid_);]])[
|
||||
std::swap (as<T> (), that.as<T> ());
|
||||
}
|
||||
|
||||
@@ -388,11 +395,67 @@ m4_define([_b4_token_maker_define],
|
||||
])])
|
||||
|
||||
|
||||
m4_define([_b4_type_clause],
|
||||
[b4_symbol_if([$1], [is_token],
|
||||
[b4_symbol_if([$1], [has_id],
|
||||
[tok == token::b4_symbol([$1], [id])],
|
||||
[tok == b4_symbol([$1], [code])])])])
|
||||
# b4_token_kind(SYMBOL-NUM)
|
||||
# -------------------------
|
||||
# Some tokens don't have an ID.
|
||||
m4_define([b4_token_kind],
|
||||
[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...)
|
||||
@@ -410,9 +473,6 @@ m4_define([_b4_token_constructor_define],
|
||||
: super_type(]b4_join([token_type (tok)],
|
||||
b4_symbol_if([$1], [has_type], [std::move (v)]),
|
||||
b4_locations_if([std::move (l)]))[)
|
||||
{
|
||||
YY_ASSERT (]m4_join([ || ], m4_map_sep([_b4_type_clause], [, ], [$@]))[);
|
||||
}
|
||||
#else
|
||||
symbol_type (]b4_join(
|
||||
[int tok],
|
||||
@@ -422,10 +482,10 @@ m4_define([_b4_token_constructor_define],
|
||||
: super_type(]b4_join([token_type (tok)],
|
||||
b4_symbol_if([$1], [has_type], [v]),
|
||||
b4_locations_if([l]))[)
|
||||
{
|
||||
YY_ASSERT (]m4_join([ || ], m4_map_sep([_b4_type_clause], [, ], [$@]))[);
|
||||
}
|
||||
#endif
|
||||
{]b4_parse_assert_if([[
|
||||
]b4_assert[ (]b4_tok_in($@)[);
|
||||
]])[}
|
||||
]])])
|
||||
|
||||
|
||||
|
||||
@@ -1486,7 +1486,7 @@ yypstate_new (void)
|
||||
yypstate *yyps;]b4_pure_if([], [[
|
||||
if (yypstate_allocated)
|
||||
return YY_NULLPTR;]])[
|
||||
yyps = YY_CAST (yypstate *, malloc (sizeof *yyps));
|
||||
yyps = YY_CAST (yypstate *, YYMALLOC (sizeof *yyps));
|
||||
if (!yyps)
|
||||
return YY_NULLPTR;]b4_pure_if([], [[
|
||||
yypstate_allocated = 1;]])[
|
||||
@@ -1515,7 +1515,7 @@ yypstate_delete (yypstate *yyps)
|
||||
#endif]b4_lac_if([[
|
||||
if (yyes != yyesa)
|
||||
YYSTACK_FREE (yyes);]])[
|
||||
free (yyps);]b4_pure_if([], [[
|
||||
YYFREE (yyps);]b4_pure_if([], [[
|
||||
yypstate_allocated = 0;]])[
|
||||
}
|
||||
}
|
||||
|
||||
+121
-88
@@ -57,44 +57,57 @@
|
||||
\gdef\colorPurple{%
|
||||
\setcolor{\rgbPurple}%
|
||||
}
|
||||
\gdef\colorOff{%
|
||||
\setcolor{\maincolor}%
|
||||
}
|
||||
|
||||
\gdef\rgbError{0.80 0 0}
|
||||
\gdef\colorError{%
|
||||
\gdef\diagError{%
|
||||
\setcolor{\rgbError}%
|
||||
}
|
||||
\gdef\rgbNotice{0 0 0.80}
|
||||
\gdef\colorNotice{%
|
||||
\gdef\diagNotice{%
|
||||
\setcolor{\rgbNotice}%
|
||||
}
|
||||
\gdef\colorOff{%
|
||||
\gdef\rgbWarning{0.50 0 0.50}
|
||||
\gdef\diagWarning{%
|
||||
\setcolor{\rgbWarning}%
|
||||
}
|
||||
\gdef\diagOff{%
|
||||
\setcolor{\maincolor}%
|
||||
}
|
||||
@end tex
|
||||
|
||||
@ifnottex
|
||||
@macro colorGreen
|
||||
@inlineraw{html, <b style="color:green">}
|
||||
@inlineraw{html, <span style="color:green">}
|
||||
@end macro
|
||||
@macro colorYellow
|
||||
@inlineraw{html, <b style="color:#ff8000">}
|
||||
@inlineraw{html, <span style="color:#ff8000">}
|
||||
@end macro
|
||||
@macro colorRed
|
||||
@inlineraw{html, <b style="color:red">}
|
||||
@inlineraw{html, <span style="color:red">}
|
||||
@end macro
|
||||
@macro colorBlue
|
||||
@inlineraw{html, <b style="color:blue">}
|
||||
@inlineraw{html, <span style="color:blue">}
|
||||
@end macro
|
||||
@macro colorPurple
|
||||
@inlineraw{html, <b style="color:darkviolet">}
|
||||
@end macro
|
||||
|
||||
@macro colorError
|
||||
@inlineraw{html, <b style="color:red">}
|
||||
@end macro
|
||||
@macro colorNotice
|
||||
@inlineraw{html, <b style="color:darkcyan">}
|
||||
@inlineraw{html, <span style="color:darkviolet">}
|
||||
@end macro
|
||||
@macro colorOff
|
||||
@inlineraw{html, </span>}
|
||||
@end macro
|
||||
|
||||
@macro diagError
|
||||
@inlineraw{html, <b style="color:red">}
|
||||
@end macro
|
||||
@macro diagNotice
|
||||
@inlineraw{html, <b style="color:darkcyan">}
|
||||
@end macro
|
||||
@macro diagWarning
|
||||
@inlineraw{html, <b style="color:darkviolet">}
|
||||
@end macro
|
||||
@macro diagOff
|
||||
@inlineraw{html, </b>}
|
||||
@end macro
|
||||
@end ifnottex
|
||||
@@ -120,15 +133,15 @@
|
||||
@end macro
|
||||
|
||||
@macro dwarning{text}
|
||||
@purple{\text\}
|
||||
@diagWarning{}\text\@diagOff{}
|
||||
@end macro
|
||||
|
||||
@macro derror{text}
|
||||
@colorError{}\text\@colorOff{}
|
||||
@diagError{}\text\@diagOff{}
|
||||
@end macro
|
||||
|
||||
@macro dnotice{text}
|
||||
@colorNotice{}\text\@colorOff{}
|
||||
@diagNotice{}\text\@diagOff{}
|
||||
@end macro
|
||||
|
||||
@finalout
|
||||
@@ -290,7 +303,7 @@ Grammar Rules for @code{rpcalc}
|
||||
|
||||
* Rpcalc Input:: Explanation of the @code{input} nonterminal
|
||||
* Rpcalc Line:: Explanation of the @code{line} nonterminal
|
||||
* Rpcalc Expr:: Explanation of the @code{expr} nonterminal
|
||||
* Rpcalc Exp:: Explanation of the @code{exp} nonterminal
|
||||
|
||||
Location Tracking Calculator: @code{ltcalc}
|
||||
|
||||
@@ -1775,7 +1788,7 @@ rule are referred to as @code{$1}, @code{$2}, and so on.
|
||||
@menu
|
||||
* Rpcalc Input:: Explanation of the @code{input} nonterminal
|
||||
* Rpcalc Line:: Explanation of the @code{line} nonterminal
|
||||
* Rpcalc Expr:: Explanation of the @code{expr} nonterminal
|
||||
* Rpcalc Exp:: Explanation of the @code{exp} nonterminal
|
||||
@end menu
|
||||
|
||||
@node Rpcalc Input
|
||||
@@ -1840,8 +1853,8 @@ uninitialized (its value will be unpredictable). This would be a bug if
|
||||
that value were ever used, but we don't use it: once rpcalc has printed the
|
||||
value of the user's input line, that value is no longer needed.
|
||||
|
||||
@node Rpcalc Expr
|
||||
@subsubsection Explanation of @code{expr}
|
||||
@node Rpcalc Exp
|
||||
@subsubsection Explanation of @code{exp}
|
||||
|
||||
The @code{exp} grouping has several rules, one for each kind of expression.
|
||||
The first rule handles the simplest expressions: those that are just
|
||||
@@ -6283,7 +6296,10 @@ Introduced in Bison 3.3 to replace @code{parser_class_name}.
|
||||
|
||||
@item Default Value: @code{YY} for Java, @code{yy} otherwise.
|
||||
|
||||
@item History: introduced in Bison 2.6
|
||||
@item History:
|
||||
introduced in Bison 2.6, with its argument in double quotes. Uses braces
|
||||
since Bison 3.0 (double quotes are still supported for backward
|
||||
compatibility).
|
||||
@end itemize
|
||||
@end deffn
|
||||
|
||||
@@ -8302,7 +8318,53 @@ write an unambiguous grammar, but that is very hard to do in this case.)
|
||||
This particular ambiguity was first encountered in the specifications of
|
||||
Algol 60 and is called the ``dangling @code{else}'' ambiguity.
|
||||
|
||||
To avoid warnings from Bison about predictable, legitimate shift/reduce
|
||||
To assist the grammar author in understanding the nature of each conflict,
|
||||
Bison can be asked to generate ``counterexamples''. In the present case it
|
||||
actually even proves that the grammar is ambiguous by exhibiting a string
|
||||
with two different parses:
|
||||
|
||||
@macro danglingElseCex
|
||||
@group
|
||||
@ifnottex
|
||||
Example: @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @blue{"else" stmt}
|
||||
Shift derivation
|
||||
@yellow{if_stmt}
|
||||
@yellow{↳ "if" expr "then"} @green{stmt}
|
||||
@green{↳} @blue{if_stmt}
|
||||
@blue{↳ "if" expr "then" stmt} @red{•} @blue{"else" stmt}
|
||||
Example: @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @yellow{"else" stmt}
|
||||
Reduce derivation
|
||||
@yellow{if_stmt}
|
||||
@yellow{↳ "if" expr "then"} @green{stmt} @yellow{"else" stmt}
|
||||
@green{↳} @blue{if_stmt}
|
||||
@blue{↳ "if" expr "then" stmt} @red{•}
|
||||
@end ifnottex
|
||||
@iftex
|
||||
Example: @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @blue{"else" stmt}
|
||||
Shift derivation
|
||||
@yellow{if_stmt}
|
||||
@yellow{@arrow{} "if" expr "then"} @green{stmt}
|
||||
@green{@arrow{}} @blue{if_stmt}
|
||||
@blue{@arrow{} "if" expr "then" stmt} @red{•} @blue{"else" stmt}
|
||||
Example: @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @yellow{"else" stmt}
|
||||
Reduce derivation
|
||||
@yellow{if_stmt}
|
||||
@yellow{@arrow{} "if" expr "then"} @green{stmt} @yellow{"else" stmt}
|
||||
@green{@arrow{}} @blue{if_stmt}
|
||||
@blue{@arrow{} "if" expr "then" stmt} @red{•}
|
||||
@end iftex
|
||||
@end group
|
||||
@end macro
|
||||
@example
|
||||
@danglingElseCex
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
@xref{Counterexamples}, for more details.
|
||||
|
||||
@sp 1
|
||||
|
||||
To avoid warnings from Bison about predictable, @emph{legitimate} shift/reduce
|
||||
conflicts, you can use the @code{%expect @var{n}} declaration.
|
||||
There will be no warning as long as the number of shift/reduce conflicts
|
||||
is exactly @var{n}, and Bison will report an error if there is a
|
||||
@@ -8693,7 +8755,8 @@ maybeword:
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
The error is an ambiguity: there is more than one way to parse a single
|
||||
The error is an ambiguity: as counterexample generation would demonstrate
|
||||
(@pxref{Counterexamples}), there is more than one way to parse a single
|
||||
@code{word} into a @code{sequence}. It could be reduced to a
|
||||
@code{maybeword} and then into a @code{sequence} via the second rule.
|
||||
Alternatively, nothing-at-all could be reduced into a @code{sequence}
|
||||
@@ -8890,12 +8953,14 @@ name_list:
|
||||
It would seem that this grammar can be parsed with only a single token of
|
||||
lookahead: when a @code{param_spec} is being read, an @code{"id"} is a
|
||||
@code{name} if a comma or colon follows, or a @code{type} if another
|
||||
@code{"id"} follows. In other words, this grammar is LR(1).
|
||||
@code{"id"} follows. In other words, this grammar is LR(1). Yet Bison
|
||||
finds one reduce/reduce conflict, for which counterexample generation
|
||||
(@pxref{Counterexamples}) would find a @emph{nonunifying} example.
|
||||
|
||||
@cindex LR
|
||||
@cindex LALR
|
||||
However, for historical reasons, Bison cannot by default handle all
|
||||
LR(1) grammars.
|
||||
This is because Bison does not handle all LR(1) grammars @emph{by default},
|
||||
for historical reasons.
|
||||
In this grammar, two contexts, that after an @code{"id"} at the beginning
|
||||
of a @code{param_spec} and likewise at the beginning of a
|
||||
@code{return_spec}, are similar enough that Bison assumes they are the
|
||||
@@ -9870,6 +9935,9 @@ and understand the parser run-time traces (@pxref{Tracing}).
|
||||
|
||||
@node Counterexamples
|
||||
@section Generation of Counterexamples
|
||||
@cindex cex
|
||||
@cindex counterexamples
|
||||
@cindex conflict counterexamples
|
||||
|
||||
Solving conflicts is probably the most delicate part of the design of an LR
|
||||
parser, as demonstrated by the number of sections devoted to them in this
|
||||
@@ -9877,17 +9945,18 @@ very documentation. To solve a conflict, one must understand it: when does
|
||||
it occur? Is it because of a flaw in the grammar? Is it rather because
|
||||
LR(1) cannot cope with this grammar?
|
||||
|
||||
On difficulty is that conflicts occur in the @emph{automaton}, and it can be
|
||||
tricky to related them to issues in the @emph{grammar} itself. With
|
||||
experience and patience, analysis the detailed description of the automaton
|
||||
(@pxref{Understanding}) allows to find example strings that reach these conflicts.
|
||||
One difficulty is that conflicts occur in the @emph{automaton}, and it can
|
||||
be tricky to relate them to issues in the @emph{grammar} itself. With
|
||||
experience and patience, analysis of the detailed description of the
|
||||
automaton (@pxref{Understanding}) allows one to find example strings that
|
||||
reach these conflicts.
|
||||
|
||||
That task is made much easier thanks to the generation of counterexamples,
|
||||
initially developed by Chinawat Isradisaikul and Andrew Myers
|
||||
@pcite{Isradisaikul 2015}.
|
||||
|
||||
As a first example, see the example grammar of @ref{Shift/Reduce}, which
|
||||
features on shift/reduce conflict:
|
||||
As a first example, see the grammar of @ref{Shift/Reduce}, which features
|
||||
one shift/reduce conflict:
|
||||
|
||||
@c see doc/if-then-else.y
|
||||
@example
|
||||
@@ -9901,49 +9970,14 @@ Let's rerun @command{bison} with the option
|
||||
@option{-Wcex}/@option{-Wcounterexamples}@inlinefmt{info, (the following
|
||||
output is actually in color)}:
|
||||
|
||||
@ifnottex
|
||||
@example
|
||||
if-then-else.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
|
||||
if-then-else.y: @dwarning{warning}: shift/reduce conflict on token "else" [@dwarning{-Wcounterexamples}]
|
||||
@group
|
||||
Example: @yellow{"if" expr "then"} "if" expr "then" stmt • "else" stmt
|
||||
Shift derivation
|
||||
@yellow{if_stmt}
|
||||
@yellow{↳ "if" expr "then"} @green{stmt}
|
||||
@green{↳} @blue{if_stmt}
|
||||
@blue{↳ "if" expr "then" stmt} @red{•} @blue{"else" stmt}
|
||||
Example: @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @yellow{"else" stmt}
|
||||
Reduce derivation
|
||||
@yellow{if_stmt}
|
||||
@yellow{↳ "if" expr "then"} @green{stmt} @yellow{"else" stmt}
|
||||
@green{↳} @blue{if_stmt}
|
||||
@blue{↳ "if" expr "then" stmt} @red{•}
|
||||
@end group
|
||||
@danglingElseCex
|
||||
@end example
|
||||
@end ifnottex
|
||||
@iftex
|
||||
@example
|
||||
if-then-else.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
|
||||
if-then-else.y: @dwarning{warning}: shift/reduce conflict on token "else" [@dwarning{-Wcounterexamples}]
|
||||
@group
|
||||
Example: @yellow{"if" expr "then"} "if" expr "then" stmt • "else" stmt
|
||||
Shift derivation
|
||||
@yellow{if_stmt}
|
||||
@yellow{@arrow{} "if" expr "then"} @green{stmt}
|
||||
@green{@arrow{}} @blue{if_stmt}
|
||||
@blue{@arrow{} "if" expr "then" stmt} @red{•} @blue{"else" stmt}
|
||||
Example: @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @yellow{"else" stmt}
|
||||
Reduce derivation
|
||||
@yellow{if_stmt}
|
||||
@yellow{@arrow{} "if" expr "then"} @green{stmt} @yellow{"else" stmt}
|
||||
@green{@arrow{}} @blue{if_stmt}
|
||||
@blue{@arrow{} "if" expr "then" stmt} @red{•}
|
||||
@end group
|
||||
@end example
|
||||
@end iftex
|
||||
|
||||
This shows two different derivations for one single expression. That
|
||||
demonstrates that the grammar is ambiguous.
|
||||
This shows two different derivations for one single expression, which proves
|
||||
that the grammar is ambiguous.
|
||||
|
||||
@sp 1
|
||||
|
||||
@@ -9966,13 +10000,13 @@ maybeword:
|
||||
|
||||
Bison generates the following counterexamples:
|
||||
|
||||
@ifnottex
|
||||
@example
|
||||
@group
|
||||
$ @kbd{bison -Wcex sequence.y}
|
||||
sequence.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
|
||||
sequence.y: @dwarning{warning}: 2 reduce/reduce conflicts [@dwarning{-Wconflicts-rr}]
|
||||
@end group
|
||||
@ifnottex
|
||||
@group
|
||||
sequence.y: @dwarning{warning}: shift/reduce conflict on token "word" [@dwarning{-Wcounterexamples}]
|
||||
Example: @red{•} @green{"word"}
|
||||
@@ -10017,15 +10051,8 @@ sequence.y:8.3-45: @dwarning{warning}: rule useless in parser due to conflicts [
|
||||
8 | @dwarning{%empty @{ printf ("empty maybeword\n"); @}}
|
||||
| @dwarning{^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
||||
@end group
|
||||
@end example
|
||||
@end ifnottex
|
||||
@iftex
|
||||
@example
|
||||
@group
|
||||
$ @kbd{bison -Wcex sequence.y}
|
||||
sequence.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
|
||||
sequence.y: @dwarning{warning}: 2 reduce/reduce conflicts [@dwarning{-Wconflicts-rr}]
|
||||
@end group
|
||||
@group
|
||||
sequence.y: @dwarning{warning}: shift/reduce conflict on token "word" [@dwarning{-Wcounterexamples}]
|
||||
Example: @red{•} @green{"word"}
|
||||
@@ -10070,12 +10097,12 @@ sequence.y:8.3-45: @dwarning{warning}: rule useless in parser due to conflicts [
|
||||
8 | @dwarning{%empty @{ printf ("empty maybeword\n"); @}}
|
||||
| @dwarning{^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
|
||||
@end group
|
||||
@end example
|
||||
@end iftex
|
||||
@end example
|
||||
|
||||
Each of these three conflicts, again, prove that the grammar is ambiguous.
|
||||
For instance, the second conflict (the reduce/reduce one) shows that the
|
||||
grammar accept the empty input in two different ways.
|
||||
grammar accepts the empty input in two different ways.
|
||||
|
||||
@sp 1
|
||||
|
||||
@@ -10096,10 +10123,10 @@ expr: %empty | expr ID ','
|
||||
|
||||
@command{bison} reports:
|
||||
|
||||
@ifnottex
|
||||
@example
|
||||
ids.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
|
||||
ids.y: @dwarning{warning}: shift/reduce conflict on token ID [@dwarning{-Wcounterexamples}]
|
||||
@ifnottex
|
||||
@group
|
||||
First example: @purple{expr} @red{•} @purple{ID ','} @green{ID} @yellow{$end}
|
||||
Shift derivation
|
||||
@@ -10120,12 +10147,8 @@ ids.y:4.4-7: @dwarning{warning}: rule useless in parser due to conflicts [@dwarn
|
||||
4 | a: expr
|
||||
| ^~~~
|
||||
@end group
|
||||
@end example
|
||||
@end ifnottex
|
||||
@iftex
|
||||
@example
|
||||
ids.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
|
||||
ids.y: @dwarning{warning}: shift/reduce conflict on token ID [@dwarning{-Wcounterexamples}]
|
||||
@group
|
||||
First example: @purple{expr} @red{•} @purple{ID ','} @green{ID} @yellow{$end}
|
||||
Shift derivation
|
||||
@@ -10146,8 +10169,8 @@ ids.y:4.4-7: @dwarning{warning}: rule useless in parser due to conflicts [@dwarn
|
||||
4 | a: expr
|
||||
| ^~~~
|
||||
@end group
|
||||
@end example
|
||||
@end iftex
|
||||
@end example
|
||||
|
||||
This conflict is caused by the parser not having enough information to know
|
||||
the difference between these two examples. The parser would need an
|
||||
@@ -15411,6 +15434,12 @@ Macro to discard a value from the parser stack and fake a lookahead
|
||||
token. @xref{Action Features}.
|
||||
@end deffn
|
||||
|
||||
@deffn {Macro} YYBISON
|
||||
The version of Bison as an integer, for instance 30704 for version 3.7.4.
|
||||
Defined in @file{yacc.c} only. Before version 3.7.4, @code{YYBISON} was
|
||||
defined to 1.
|
||||
@end deffn
|
||||
|
||||
@deffn {Variable} yychar
|
||||
External integer variable that contains the integer value of the
|
||||
lookahead token. (In a pure parser, it is a local variable within
|
||||
@@ -15631,6 +15660,10 @@ permitted. @xref{Language and Grammar}.
|
||||
A sequence of tokens and/or nonterminals, with one dot, that demonstrates a
|
||||
conflict. The dot marks the place where the conflict occurs.
|
||||
|
||||
@cindex unifying counterexample
|
||||
@cindex counterexample, unifying
|
||||
@cindex nonunifying counterexample
|
||||
@cindex counterexample, nonunifying
|
||||
A @emph{unifying} counterexample is a single string that has two different
|
||||
parses; its existence proves that the grammar is ambiguous. When a unifying
|
||||
counterexample cannot be found in reasonable time, a @emph{nonunifying}
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ MAINTAINERCLEANFILES = $(CROSS_OPTIONS_TEXI)
|
||||
|
||||
# Fix Info's @code in @deftype
|
||||
# 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
|
||||
$(AM_V_GEN) $(PERL) -pi.bak -0777 \
|
||||
-e 's{(^ --.*\n(?: {10}.*\n)*)}' \
|
||||
|
||||
+41
-29
@@ -185,13 +185,13 @@ my $verbose = 1;
|
||||
|
||||
=over 4
|
||||
|
||||
=item C<verbose($level, $message)>
|
||||
=item C<verbose ($level, $message)>
|
||||
|
||||
Report the C<$message> is C<$level> E<lt>= C<$verbose>.
|
||||
|
||||
=cut
|
||||
|
||||
sub verbose($$)
|
||||
sub verbose ($$)
|
||||
{
|
||||
my ($level, $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>.
|
||||
|
||||
=cut
|
||||
|
||||
sub directives($@)
|
||||
sub directives ($@)
|
||||
{
|
||||
my ($bench, @directive) = @_;
|
||||
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)>
|
||||
|
||||
Create a large triangular grammar which looks like :
|
||||
@@ -389,18 +410,14 @@ sub generate_grammar_calc ($$@)
|
||||
%define api.value.type union
|
||||
$directives
|
||||
|
||||
%{
|
||||
%code provides {
|
||||
static int power (int base, int exponent);
|
||||
/* yyerror receives the location if:
|
||||
- %location & %pure & %glr
|
||||
- %location & %pure & %yacc & %parse-param. */
|
||||
static void yyerror (const char *s);
|
||||
#if YYPURE
|
||||
static int yylex (YYSTYPE* yylvalp);
|
||||
#else
|
||||
static int yylex (void);
|
||||
#endif
|
||||
%}
|
||||
static int yylex (@{[is_pure (@directive) ? "YYSTYPE *yylvalp" : "void"]});
|
||||
}
|
||||
|
||||
/* Bison Declarations */
|
||||
%token
|
||||
@@ -467,12 +484,7 @@ yyerror (const char *s)
|
||||
}
|
||||
|
||||
static int
|
||||
#if YYPURE
|
||||
# define yylval (*yylvalp)
|
||||
yylex (YYSTYPE* yylvalp)
|
||||
#else
|
||||
yylex (void)
|
||||
#endif
|
||||
yylex (@{[is_pure (@directive) ? "YYSTYPE *yylvalp" : "void"]})
|
||||
{
|
||||
int c;
|
||||
|
||||
@@ -498,7 +510,7 @@ yylex (void)
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
{
|
||||
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);
|
||||
input += nchars - 1;
|
||||
return NUM;
|
||||
@@ -506,7 +518,7 @@ yylex (void)
|
||||
|
||||
default:
|
||||
yyerror ("error: invalid character");
|
||||
return yylex ();
|
||||
return yylex (@{[is_pure (@directive) ? "yylvalp" : ""]});
|
||||
}
|
||||
}
|
||||
EOF
|
||||
@@ -592,10 +604,10 @@ $directives
|
||||
// Prototype of the yylex function providing subsequent tokens.
|
||||
static
|
||||
#if USE_TOKEN_CTOR
|
||||
yy::parser::symbol_type yylex();
|
||||
yy::parser::symbol_type yylex ();
|
||||
#else
|
||||
yy::parser::token_type yylex(yy::parser::semantic_type* yylvalp,
|
||||
yy::parser::location_type* yyllocp);
|
||||
yy::parser::token_type yylex (yy::parser::semantic_type *yylvalp,
|
||||
yy::parser::location_type *yyllocp);
|
||||
#endif
|
||||
|
||||
// Conversion to string.
|
||||
@@ -618,8 +630,8 @@ EOF
|
||||
print $out <<'EOF';
|
||||
%token <std::string> TEXT
|
||||
%token <int> NUMBER
|
||||
%printer { std::cerr << "Number: " << $$; } <int>
|
||||
%printer { std::cerr << "Text: " << $$; } <std::string>
|
||||
%printer { yyo << "Number: " << $$; } <int>
|
||||
%printer { yyo << "Text: " << $$; } <std::string>
|
||||
%type <std::string> text result
|
||||
|
||||
%%
|
||||
@@ -641,8 +653,8 @@ EOF
|
||||
%union {int ival; std::string* sval;}
|
||||
%token <sval> TEXT
|
||||
%token <ival> NUMBER
|
||||
%printer { std::cerr << "Number: " << $$; } <ival>
|
||||
%printer { std::cerr << "Text: " << *$$; } <sval>
|
||||
%printer { yyo << "Number: " << $$; } <ival>
|
||||
%printer { yyo << "Text: " << *$$; } <sval>
|
||||
%type <sval> text result
|
||||
|
||||
%%
|
||||
@@ -664,10 +676,10 @@ EOF
|
||||
|
||||
static
|
||||
#if USE_TOKEN_CTOR
|
||||
yy::parser::symbol_type yylex()
|
||||
yy::parser::symbol_type yylex ()
|
||||
#else
|
||||
yy::parser::token_type yylex(yy::parser::semantic_type* yylvalp,
|
||||
yy::parser::location_type* yyllocp)
|
||||
yy::parser::token_type yylex (yy::parser::semantic_type *yylvalp,
|
||||
yy::parser::location_type *yyllocp)
|
||||
#endif
|
||||
{
|
||||
typedef yy::parser::location_type location_type;
|
||||
|
||||
@@ -251,29 +251,29 @@ err: Next token is token ) (1.4: )
|
||||
err: Shifting token ) (1.4: )
|
||||
err: Entering state 20
|
||||
err: Stack now 0 2 10 20
|
||||
err: Reducing stack by rule 15 (line 151):
|
||||
err: Reducing stack by rule XX (line XXX):
|
||||
err: $1 = token ( (1.1: )
|
||||
err: $2 = token error (1.2-3: )
|
||||
err: $3 = token ) (1.4: )
|
||||
err: -> $$ = nterm exp (1.1-4: 666)
|
||||
err: Entering state 7
|
||||
err: Stack now 0 7
|
||||
err: Entering state 8
|
||||
err: Stack now 0 8
|
||||
err: Return for a new token:
|
||||
err: Reading a token
|
||||
err: Now at end of input.
|
||||
err: LAC: initial context established for end of file
|
||||
err: LAC: checking lookahead end of file: R2 G8 S19
|
||||
err: Reducing stack by rule 2 (line 126):
|
||||
err: LAC: checking lookahead end of file: R2 G7 S14
|
||||
err: Reducing stack by rule XX (line XXX):
|
||||
err: $1 = nterm exp (1.1-4: 666)
|
||||
err: -> $$ = nterm input (1.1-4: )
|
||||
err: Entering state 8
|
||||
err: Stack now 0 8
|
||||
err: Entering state 7
|
||||
err: Stack now 0 7
|
||||
err: Now at end of input.
|
||||
err: Shifting token end of file (1.5: )
|
||||
err: LAC: initial context discarded due to shift
|
||||
err: Entering state 19
|
||||
err: Stack now 0 8 19
|
||||
err: Stack now 0 8 19
|
||||
err: Entering state 14
|
||||
err: Stack now 0 7 14
|
||||
err: Stack now 0 7 14
|
||||
err: Cleanup: popping token end of file (1.5: )
|
||||
err: Cleanup: popping nterm input (1.1-4: )' -p
|
||||
|
||||
|
||||
@@ -31,6 +31,13 @@ endif FLEX_WORKS
|
||||
|
||||
%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
|
||||
dist_lexcalc_DATA = %D%/parse.y %D%/scan.l %D%/Makefile %D%/README.md
|
||||
CLEANFILES += %D%/parse.[ch] %D%/scan.c %D%/parse.output
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ EXTRA_DIST += %D%/calc.test
|
||||
|
||||
%D%/calc.d: %D%/calc.y $(dependencies)
|
||||
$(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
|
||||
$(AM_V_GEN) $(DC) $(DCFLAGS) -of$@ %D%/calc.d
|
||||
|
||||
@@ -27,7 +27,7 @@ EXTRA_DIST += %D%/Calc.test
|
||||
|
||||
%D%/Calc.java: %D%/Calc.y $(dependencies)
|
||||
$(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
|
||||
$(AM_V_GEN) $(SHELL) $(top_builddir)/javacomp.sh %D%/Calc.java
|
||||
|
||||
@@ -27,7 +27,7 @@ EXTRA_DIST += %D%/Calc.test
|
||||
|
||||
%D%/Calc.java: %D%/Calc.y $(dependencies)
|
||||
$(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
|
||||
$(AM_V_GEN) $(SHELL) $(top_builddir)/javacomp.sh %D%/Calc.java
|
||||
|
||||
+1
-1
Submodule gnulib updated: ac34618e85...839ed059f4
+3
-2
@@ -192,8 +192,6 @@
|
||||
/localcharset.h
|
||||
/locale.h
|
||||
/locale.in.h
|
||||
/localtime-buffer.c
|
||||
/localtime-buffer.h
|
||||
/lstat.c
|
||||
/malloc.c
|
||||
/malloca.c
|
||||
@@ -338,8 +336,11 @@
|
||||
/sys_types.in.h
|
||||
/sys_wait.in.h
|
||||
/sysexits.in.h
|
||||
/termios.h
|
||||
/termios.in.h
|
||||
/textstyle.h
|
||||
/textstyle.in.h
|
||||
/thread-optim.h
|
||||
/time.h
|
||||
/time.in.h
|
||||
/timespec.c
|
||||
|
||||
+4
-1
@@ -97,7 +97,6 @@
|
||||
/locale-ja.m4
|
||||
/locale-zh.m4
|
||||
/locale_h.m4
|
||||
/localtime-buffer.m4
|
||||
/lock.m4
|
||||
/longlong.m4
|
||||
/lstat.m4
|
||||
@@ -117,6 +116,7 @@
|
||||
/msvc-inval.m4
|
||||
/msvc-nothrow.m4
|
||||
/multiarch.m4
|
||||
/musl.m4
|
||||
/nls.m4
|
||||
/nocrash.m4
|
||||
/non-recursive-gnulib-prefix-hack.m4
|
||||
@@ -128,6 +128,7 @@
|
||||
/open.m4
|
||||
/pathmax.m4
|
||||
/perror.m4
|
||||
/pid_t.m4
|
||||
/pipe2.m4
|
||||
/po.m4
|
||||
/posix_spawn.m4
|
||||
@@ -184,6 +185,7 @@
|
||||
/strndup.m4
|
||||
/strnlen.m4
|
||||
/strverscmp.m4
|
||||
/sys_ioctl_h.m4
|
||||
/sys_resource_h.m4
|
||||
/sys_socket_h.m4
|
||||
/sys_stat_h.m4
|
||||
@@ -191,6 +193,7 @@
|
||||
/sys_times_h.m4
|
||||
/sys_types_h.m4
|
||||
/sys_wait_h.m4
|
||||
/termios_h.m4
|
||||
/threadlib.m4
|
||||
/time_h.m4
|
||||
/timespec.m4
|
||||
|
||||
+12
-17
@@ -113,13 +113,8 @@ free_counterexample (counterexample *cex)
|
||||
free (cex);
|
||||
}
|
||||
|
||||
static int max (int a, int b)
|
||||
{
|
||||
return a < b ? b : a;
|
||||
}
|
||||
|
||||
static void
|
||||
print_counterexample (const counterexample *cex, FILE *out, const char *prefix)
|
||||
counterexample_print (const counterexample *cex, FILE *out, const char *prefix)
|
||||
{
|
||||
const bool flat = getenv ("YYFLAT");
|
||||
const char *example1_label
|
||||
@@ -131,8 +126,8 @@ print_counterexample (const counterexample *cex, FILE *out, const char *prefix)
|
||||
const char *deriv2_label
|
||||
= cex->shift_reduce ? _("Reduce derivation") : _("Second reduce derivation");
|
||||
const int width =
|
||||
max (max (mbswidth (example1_label, 0), mbswidth (example2_label, 0)),
|
||||
max (mbswidth (deriv1_label, 0), mbswidth (deriv2_label, 0)));
|
||||
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), "");
|
||||
@@ -526,7 +521,7 @@ nonunifying_shift_path (state_item_list reduce_path, state_item *shift_conflict)
|
||||
for (gl_list_iterator_t it = gl_list_iterator (result);
|
||||
state_item_list_next (&it, &sip);
|
||||
)
|
||||
print_state_item (sip, stderr, "");
|
||||
state_item_print (sip, stderr, "");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -717,10 +712,10 @@ ssb_equals (const search_state_bundle *s1, const search_state_bundle *s2)
|
||||
typedef gl_list_t ssb_list;
|
||||
|
||||
static size_t
|
||||
visited_hasher (const search_state *ss, size_t maximum)
|
||||
visited_hasher (const search_state *ss, size_t max)
|
||||
{
|
||||
return (parse_state_hasher (ss->states[0], maximum)
|
||||
+ parse_state_hasher (ss->states[1], maximum)) % maximum;
|
||||
return (parse_state_hasher (ss->states[0], max)
|
||||
+ parse_state_hasher (ss->states[1], max)) % max;
|
||||
}
|
||||
|
||||
static bool
|
||||
@@ -1267,7 +1262,7 @@ counterexample_report (state_item_number itm1, state_item_number itm2,
|
||||
: example_from_path (shift_reduce, itm2, shortest_path, next_sym);
|
||||
|
||||
gl_list_free (shortest_path);
|
||||
print_counterexample (cex, out, prefix);
|
||||
counterexample_print (cex, out, prefix);
|
||||
free_counterexample (cex);
|
||||
}
|
||||
|
||||
@@ -1290,8 +1285,8 @@ counterexample_report_shift_reduce (state_item_number itm1, state_item_number it
|
||||
// In the report, print the items.
|
||||
if (out != stderr || trace_flag & trace_cex)
|
||||
{
|
||||
print_state_item (&state_items[itm1], out, prefix);
|
||||
print_state_item (&state_items[itm2], out, prefix);
|
||||
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);
|
||||
}
|
||||
@@ -1334,8 +1329,8 @@ counterexample_report_reduce_reduce (state_item_number itm1, state_item_number i
|
||||
// In the report, print the items.
|
||||
if (out != stderr || trace_flag & trace_cex)
|
||||
{
|
||||
print_state_item (&state_items[itm1], out, prefix);
|
||||
print_state_item (&state_items[itm2], out, prefix);
|
||||
state_item_print (&state_items[itm1], out, prefix);
|
||||
state_item_print (&state_items[itm2], out, prefix);
|
||||
}
|
||||
counterexample_report (itm1, itm2, bitset_first (conflict_syms),
|
||||
false, out, prefix);
|
||||
|
||||
+8
-14
@@ -76,12 +76,12 @@ void derivation_list_free (derivation_list dl)
|
||||
derivation *
|
||||
derivation_new (symbol_number sym, derivation_list children)
|
||||
{
|
||||
derivation *deriv = xmalloc (sizeof (derivation));
|
||||
deriv->sym = sym;
|
||||
deriv->children = children;
|
||||
deriv->reference_count = 0;
|
||||
deriv->color = -1;
|
||||
return deriv;
|
||||
derivation *res = xmalloc (sizeof *res);
|
||||
res->sym = sym;
|
||||
res->children = children;
|
||||
res->reference_count = 0;
|
||||
res->color = -1;
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -135,12 +135,6 @@ derivation_size (const derivation *deriv)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
max (int a, int b)
|
||||
{
|
||||
return a < b ? b : a;
|
||||
}
|
||||
|
||||
// Longest distance from root to leaf.
|
||||
static int
|
||||
derivation_depth (const derivation *deriv)
|
||||
@@ -154,7 +148,7 @@ derivation_depth (const derivation *deriv)
|
||||
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
|
||||
derivation_list_next (&it, &child);
|
||||
)
|
||||
res = max (res, derivation_depth (child));
|
||||
res = max_int (res, derivation_depth (child));
|
||||
return res + 1;
|
||||
}
|
||||
else
|
||||
@@ -237,7 +231,7 @@ derivation_width (const derivation *deriv)
|
||||
// No separator at the beginning.
|
||||
children_width -= derivation_separator_width;
|
||||
}
|
||||
return max (self_width, children_width);
|
||||
return max_int (self_width, children_width);
|
||||
}
|
||||
else if (deriv == &d_dot)
|
||||
{
|
||||
|
||||
+9
-1
@@ -112,7 +112,15 @@ static struct obstack obstack_for_string;
|
||||
# define STRING_1GROW(Char) \
|
||||
obstack_1grow (&obstack_for_string, Char)
|
||||
|
||||
# define STRING_FREE() \
|
||||
# ifdef NDEBUG
|
||||
# define STRING_FREE() \
|
||||
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
|
||||
|
||||
+1
-1
@@ -423,7 +423,7 @@ ielr_item_has_lookahead (state *s, symbol_number lhs, size_t item,
|
||||
check all predecessors' goto follows for the LHS. */
|
||||
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];
|
||||
*predecessor;
|
||||
++predecessor)
|
||||
|
||||
+2
-1
@@ -103,6 +103,8 @@ src_bison_SOURCES = \
|
||||
src/state.h \
|
||||
src/state-item.c \
|
||||
src/state-item.h \
|
||||
src/strversion.c \
|
||||
src/strversion.h \
|
||||
src/symlist.c \
|
||||
src/symlist.h \
|
||||
src/symtab.c \
|
||||
@@ -143,7 +145,6 @@ src_bison_LDADD = \
|
||||
$(LIB_SETLOCALE_NULL) \
|
||||
$(LIBICONV) \
|
||||
$(LIBINTL) \
|
||||
$(LIBREADLINE) \
|
||||
$(LIBTEXTSTYLE)
|
||||
|
||||
|
||||
|
||||
+3
-13
@@ -40,18 +40,6 @@
|
||||
|
||||
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. */
|
||||
static int
|
||||
columns (void)
|
||||
@@ -167,7 +155,9 @@ int
|
||||
location_print (location loc, FILE *out)
|
||||
{
|
||||
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 += fprintf (out, "-");
|
||||
|
||||
+1
-1
@@ -256,7 +256,7 @@ shortest_path_from_start (state_item_number target, symbol_number next_sym)
|
||||
gl_list_iterator_t it = gl_list_iterator (res);
|
||||
const void *sip;
|
||||
while (gl_list_iterator_next (&it, &sip, NULL))
|
||||
print_state_item ((state_item *) sip, stdout, "");
|
||||
state_item_print ((state_item *) sip, stdout, "");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -127,9 +127,6 @@ muscle_init (void)
|
||||
|
||||
muscle_table = hash_xinitialize (HT_INITIAL_CAPACITY, NULL, hash_muscle,
|
||||
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 "symtab.h"
|
||||
#include "tables.h"
|
||||
#include "strversion.h"
|
||||
|
||||
static struct obstack format_obstack;
|
||||
|
||||
@@ -249,7 +250,7 @@ prepare_symbol_names (char const *muscle_name)
|
||||
if (i)
|
||||
obstack_1grow (&format_obstack, ' ');
|
||||
if (translatable)
|
||||
obstack_sgrow (&format_obstack, "]b4_symbol_translate([");
|
||||
obstack_sgrow (&format_obstack, "]b4_symbol_translate""([");
|
||||
obstack_escape (&format_obstack, cp);
|
||||
if (translatable)
|
||||
obstack_sgrow (&format_obstack, "])[");
|
||||
@@ -554,7 +555,7 @@ prepare_symbol_definitions (void)
|
||||
/* Map "orig NUM" to new numbers. See data/README. */
|
||||
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);
|
||||
MUSCLE_INSERT_INT (key, nterm_map ? nterm_map[i - ntokens] : i);
|
||||
}
|
||||
@@ -565,12 +566,12 @@ prepare_symbol_definitions (void)
|
||||
const char *key;
|
||||
|
||||
#define SET_KEY(Entry) \
|
||||
obstack_printf (&format_obstack, "symbol(%d, %s)", \
|
||||
obstack_printf (&format_obstack, "symbol""(%d, %s)", \
|
||||
i, Entry); \
|
||||
key = obstack_finish0 (&format_obstack);
|
||||
|
||||
#define SET_KEY2(Entry, Suffix) \
|
||||
obstack_printf (&format_obstack, "symbol(%d, %s_%s)", \
|
||||
obstack_printf (&format_obstack, "symbol""(%d, %s_%s)", \
|
||||
i, Entry, Suffix); \
|
||||
key = obstack_finish0 (&format_obstack);
|
||||
|
||||
@@ -807,6 +808,9 @@ prepare (void)
|
||||
char const *cp = getenv ("BISON_USE_PUSH_FOR_PULL");
|
||||
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);
|
||||
|
||||
/* Flags. */
|
||||
|
||||
+38
-70
@@ -1,4 +1,4 @@
|
||||
/* A Bison parser, made by GNU Bison 3.6.90. */
|
||||
/* A Bison parser, made by GNU Bison 3.7.3.7-d831b. */
|
||||
|
||||
/* Bison implementation for Yacc-like parsers in C
|
||||
|
||||
@@ -46,10 +46,10 @@
|
||||
USER NAME SPACE" below. */
|
||||
|
||||
/* Identify Bison output. */
|
||||
#define YYBISON 1
|
||||
#define YYBISON 30703
|
||||
|
||||
/* Bison version. */
|
||||
#define YYBISON_VERSION "3.6.90"
|
||||
#define YYBISON_VERSION "3.7.3.7-d831b"
|
||||
|
||||
/* Skeleton name. */
|
||||
#define YYSKELETON_NAME "yacc.c"
|
||||
@@ -149,7 +149,7 @@ enum yysymbol_kind_t
|
||||
YYSYMBOL_BRACED_CODE = 41, /* "{...}" */
|
||||
YYSYMBOL_BRACED_PREDICATE = 42, /* "%?{...}" */
|
||||
YYSYMBOL_BRACKETED_ID = 43, /* "[identifier]" */
|
||||
YYSYMBOL_CHAR = 44, /* "character literal" */
|
||||
YYSYMBOL_CHAR_LITERAL = 44, /* "character literal" */
|
||||
YYSYMBOL_COLON = 45, /* ":" */
|
||||
YYSYMBOL_EPILOGUE = 46, /* "epilogue" */
|
||||
YYSYMBOL_EQUAL = 47, /* "=" */
|
||||
@@ -162,7 +162,7 @@ enum yysymbol_kind_t
|
||||
YYSYMBOL_TAG = 54, /* "<tag>" */
|
||||
YYSYMBOL_TAG_ANY = 55, /* "<*>" */
|
||||
YYSYMBOL_TAG_NONE = 56, /* "<>" */
|
||||
YYSYMBOL_INT = 57, /* "integer literal" */
|
||||
YYSYMBOL_INT_LITERAL = 57, /* "integer literal" */
|
||||
YYSYMBOL_PERCENT_PARAM = 58, /* "%param" */
|
||||
YYSYMBOL_PERCENT_UNION = 59, /* "%union" */
|
||||
YYSYMBOL_PERCENT_EMPTY = 60, /* "%empty" */
|
||||
@@ -218,8 +218,6 @@ typedef enum yysymbol_kind_t yysymbol_kind_t;
|
||||
#include "system.h"
|
||||
|
||||
#include <c-ctype.h>
|
||||
#include <errno.h>
|
||||
#include <intprops.h>
|
||||
#include <quotearg.h>
|
||||
#include <vasnprintf.h>
|
||||
#include <xmemdup0.h>
|
||||
@@ -233,6 +231,7 @@ typedef enum yysymbol_kind_t yysymbol_kind_t;
|
||||
#include "reader.h"
|
||||
#include "scan-code.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. */
|
||||
@@ -639,19 +638,19 @@ union yyalloc
|
||||
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
|
||||
static const yytype_int16 yyrline[] =
|
||||
{
|
||||
0, 312, 312, 321, 322, 326, 327, 333, 337, 342,
|
||||
343, 344, 345, 346, 347, 348, 353, 358, 359, 360,
|
||||
361, 362, 363, 363, 364, 365, 366, 367, 368, 369,
|
||||
370, 371, 375, 376, 385, 386, 390, 401, 405, 409,
|
||||
417, 427, 428, 438, 439, 445, 458, 458, 463, 463,
|
||||
468, 472, 482, 483, 484, 485, 489, 490, 495, 496,
|
||||
500, 501, 505, 506, 507, 520, 529, 533, 537, 545,
|
||||
546, 550, 563, 564, 569, 570, 571, 589, 593, 597,
|
||||
605, 607, 612, 619, 629, 633, 637, 645, 650, 662,
|
||||
663, 669, 670, 671, 678, 678, 686, 687, 688, 693,
|
||||
696, 698, 700, 702, 704, 706, 708, 710, 712, 717,
|
||||
718, 727, 751, 752, 753, 754, 766, 768, 792, 797,
|
||||
798, 803, 811, 812
|
||||
0, 311, 311, 320, 321, 325, 326, 332, 336, 341,
|
||||
342, 343, 344, 345, 346, 347, 352, 357, 358, 359,
|
||||
360, 361, 362, 362, 363, 364, 365, 366, 367, 368,
|
||||
369, 370, 374, 375, 384, 385, 389, 400, 404, 408,
|
||||
416, 426, 427, 437, 438, 444, 457, 457, 462, 462,
|
||||
467, 471, 481, 482, 483, 484, 488, 489, 494, 495,
|
||||
499, 500, 504, 505, 506, 519, 528, 532, 536, 544,
|
||||
545, 549, 562, 563, 568, 569, 570, 588, 592, 596,
|
||||
604, 606, 611, 618, 628, 632, 636, 644, 649, 661,
|
||||
662, 668, 669, 670, 677, 677, 685, 686, 687, 692,
|
||||
695, 697, 699, 701, 703, 705, 707, 709, 711, 716,
|
||||
717, 726, 750, 751, 752, 753, 765, 767, 791, 796,
|
||||
797, 802, 810, 811
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -1115,8 +1114,8 @@ tron (yyo);
|
||||
{ fprintf (yyo, "[%s]", ((*yyvaluep).BRACKETED_ID)); }
|
||||
break;
|
||||
|
||||
case YYSYMBOL_CHAR: /* "character literal" */
|
||||
{ fputs (char_name (((*yyvaluep).CHAR)), yyo); }
|
||||
case YYSYMBOL_CHAR_LITERAL: /* "character literal" */
|
||||
{ fputs (char_name (((*yyvaluep).CHAR_LITERAL)), yyo); }
|
||||
break;
|
||||
|
||||
case YYSYMBOL_EPILOGUE: /* "epilogue" */
|
||||
@@ -1139,8 +1138,8 @@ tron (yyo);
|
||||
{ fprintf (yyo, "<%s>", ((*yyvaluep).TAG)); }
|
||||
break;
|
||||
|
||||
case YYSYMBOL_INT: /* "integer literal" */
|
||||
{ fprintf (yyo, "%d", ((*yyvaluep).INT)); }
|
||||
case YYSYMBOL_INT_LITERAL: /* "integer literal" */
|
||||
{ fprintf (yyo, "%d", ((*yyvaluep).INT_LITERAL)); }
|
||||
break;
|
||||
|
||||
case YYSYMBOL_PERCENT_PARAM: /* "%param" */
|
||||
@@ -2087,11 +2086,11 @@ yyreduce:
|
||||
break;
|
||||
|
||||
case 12: /* prologue_declaration: "%expect" "integer literal" */
|
||||
{ expected_sr_conflicts = (yyvsp[0].INT); }
|
||||
{ expected_sr_conflicts = (yyvsp[0].INT_LITERAL); }
|
||||
break;
|
||||
|
||||
case 13: /* prologue_declaration: "%expect-rr" "integer literal" */
|
||||
{ expected_rr_conflicts = (yyvsp[0].INT); }
|
||||
{ expected_rr_conflicts = (yyvsp[0].INT_LITERAL); }
|
||||
break;
|
||||
|
||||
case 14: /* prologue_declaration: "%file-prefix" "string" */
|
||||
@@ -2339,13 +2338,13 @@ yyreduce:
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
@@ -2396,13 +2395,13 @@ yyreduce:
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
@@ -2431,13 +2430,13 @@ yyreduce:
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
@@ -2506,7 +2505,7 @@ yyreduce:
|
||||
break;
|
||||
|
||||
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;
|
||||
|
||||
case 106: /* rhs: rhs "%merge" "<tag>" */
|
||||
@@ -2514,11 +2513,11 @@ yyreduce:
|
||||
break;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
case 109: /* named_ref.opt: %empty */
|
||||
@@ -2566,9 +2565,9 @@ yyreduce:
|
||||
location loc = muscle_percent_define_get_loc (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_code_set ((yyval.id), (yyvsp[0].CHAR), (yylsp[0]));
|
||||
symbol_code_set ((yyval.id), (yyvsp[0].CHAR_LITERAL), (yylsp[0]));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3032,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
|
||||
handle_require (location const *loc, char const *version_quoted)
|
||||
{
|
||||
char *version = unquote (version_quoted);
|
||||
required_version = str_to_version (version);
|
||||
required_version = strversion_to_int (version);
|
||||
if (required_version == -1)
|
||||
{
|
||||
complain (loc, complaint, _("invalid version requirement: %s"),
|
||||
@@ -3147,8 +3116,7 @@ char_name (char c)
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
static void
|
||||
current_lhs (symbol *sym, location loc, named_ref *ref)
|
||||
{
|
||||
current_lhs_symbol = sym;
|
||||
|
||||
+5
-5
@@ -1,4 +1,4 @@
|
||||
/* A Bison parser, made by GNU Bison 3.6.90. */
|
||||
/* A Bison parser, made by GNU Bison 3.7.3.7-d831b. */
|
||||
|
||||
/* Bison interface for Yacc-like parsers in C
|
||||
|
||||
@@ -123,7 +123,7 @@ extern int gram_debug;
|
||||
BRACED_CODE = 41, /* "{...}" */
|
||||
BRACED_PREDICATE = 42, /* "%?{...}" */
|
||||
BRACKETED_ID = 43, /* "[identifier]" */
|
||||
CHAR = 44, /* "character literal" */
|
||||
CHAR_LITERAL = 44, /* "character literal" */
|
||||
COLON = 45, /* ":" */
|
||||
EPILOGUE = 46, /* "epilogue" */
|
||||
EQUAL = 47, /* "=" */
|
||||
@@ -136,7 +136,7 @@ extern int gram_debug;
|
||||
TAG = 54, /* "<tag>" */
|
||||
TAG_ANY = 55, /* "<*>" */
|
||||
TAG_NONE = 56, /* "<>" */
|
||||
INT = 57, /* "integer literal" */
|
||||
INT_LITERAL = 57, /* "integer literal" */
|
||||
PERCENT_PARAM = 58, /* "%param" */
|
||||
PERCENT_UNION = 59, /* "%union" */
|
||||
PERCENT_EMPTY = 60 /* "%empty" */
|
||||
@@ -156,7 +156,7 @@ union GRAM_STYPE
|
||||
char* EPILOGUE; /* "epilogue" */
|
||||
char* PROLOGUE; /* "%{...%}" */
|
||||
code_props_type code_props_type; /* code_props_type */
|
||||
int INT; /* "integer literal" */
|
||||
int INT_LITERAL; /* "integer literal" */
|
||||
int yykind_82; /* int.opt */
|
||||
named_ref* yykind_95; /* named_ref.opt */
|
||||
param_type PERCENT_PARAM; /* "%param" */
|
||||
@@ -188,7 +188,7 @@ union GRAM_STYPE
|
||||
uniqstr yykind_74; /* tag.opt */
|
||||
uniqstr tag; /* tag */
|
||||
uniqstr variable; /* variable */
|
||||
unsigned char CHAR; /* "character literal" */
|
||||
unsigned char CHAR_LITERAL; /* "character literal" */
|
||||
value_type value; /* value */
|
||||
|
||||
|
||||
|
||||
+19
-51
@@ -42,8 +42,6 @@
|
||||
#include "system.h"
|
||||
|
||||
#include <c-ctype.h>
|
||||
#include <errno.h>
|
||||
#include <intprops.h>
|
||||
#include <quotearg.h>
|
||||
#include <vasnprintf.h>
|
||||
#include <xmemdup0.h>
|
||||
@@ -57,6 +55,7 @@
|
||||
#include "reader.h"
|
||||
#include "scan-code.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. */
|
||||
@@ -214,7 +213,7 @@
|
||||
BRACED_CODE "{...}"
|
||||
BRACED_PREDICATE "%?{...}"
|
||||
BRACKETED_ID _("[identifier]")
|
||||
CHAR _("character literal")
|
||||
CHAR_LITERAL _("character literal")
|
||||
COLON ":"
|
||||
EPILOGUE _("epilogue")
|
||||
EQUAL "="
|
||||
@@ -232,7 +231,7 @@
|
||||
%code pre-printer {tron (yyo);}
|
||||
%code post-printer {troff (yyo);}
|
||||
|
||||
%type <unsigned char> CHAR
|
||||
%type <unsigned char> CHAR_LITERAL
|
||||
%printer { fputs (char_name ($$), yyo); } <unsigned char>
|
||||
|
||||
%type <char*> "{...}" "%?{...}" "%{...%}" EPILOGUE STRING TSTRING
|
||||
@@ -249,7 +248,7 @@
|
||||
%printer { fprintf (yyo, "%%%s", $$); } PERCENT_FLAG
|
||||
%printer { fprintf (yyo, "<%s>", $$); } TAG tag
|
||||
|
||||
%token <int> INT _("integer literal")
|
||||
%token <int> INT_LITERAL _("integer literal")
|
||||
%printer { fprintf (yyo, "%d", $$); } <int>
|
||||
|
||||
%type <symbol*> id id_colon string_as_id symbol token_decl token_decl_for_prec
|
||||
@@ -342,8 +341,8 @@ prologue_declaration:
|
||||
| "%defines" { defines_flag = true; }
|
||||
| "%defines" STRING { handle_defines ($2); }
|
||||
| "%error-verbose" { handle_error_verbose (&@$, $1); }
|
||||
| "%expect" INT { expected_sr_conflicts = $2; }
|
||||
| "%expect-rr" INT { expected_rr_conflicts = $2; }
|
||||
| "%expect" INT_LITERAL { expected_sr_conflicts = $2; }
|
||||
| "%expect-rr" INT_LITERAL { expected_rr_conflicts = $2; }
|
||||
| "%file-prefix" STRING { handle_file_prefix (&@$, &@1, $1, $2); }
|
||||
| "%glr-parser"
|
||||
{
|
||||
@@ -532,11 +531,11 @@ token_decls:
|
||||
}
|
||||
| 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]
|
||||
{
|
||||
$$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG, @TAG));
|
||||
$$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG));
|
||||
}
|
||||
;
|
||||
|
||||
@@ -561,7 +560,7 @@ token_decl:
|
||||
%type <int> int.opt;
|
||||
int.opt:
|
||||
%empty { $$ = -1; }
|
||||
| INT
|
||||
| INT_LITERAL
|
||||
;
|
||||
|
||||
%type <symbol*> alias;
|
||||
@@ -592,11 +591,11 @@ token_decls_for_prec:
|
||||
}
|
||||
| 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]
|
||||
{
|
||||
$$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG, @TAG));
|
||||
$$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG));
|
||||
}
|
||||
;
|
||||
|
||||
@@ -632,11 +631,11 @@ symbol_decls:
|
||||
}
|
||||
| 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_list_append ($1, symbol_list_type_set ($syms, $TAG, @TAG));
|
||||
$$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG));
|
||||
}
|
||||
;
|
||||
|
||||
@@ -703,13 +702,13 @@ rhs:
|
||||
{ grammar_current_rule_empty_set (@2); }
|
||||
| rhs "%prec" symbol
|
||||
{ grammar_current_rule_prec_set ($3, @3); }
|
||||
| rhs "%dprec" INT
|
||||
| rhs "%dprec" INT_LITERAL
|
||||
{ grammar_current_rule_dprec_set ($3, @3); }
|
||||
| rhs "%merge" TAG
|
||||
{ grammar_current_rule_merge_set ($3, @3); }
|
||||
| rhs "%expect" INT
|
||||
| rhs "%expect" INT_LITERAL
|
||||
{ grammar_current_rule_expect_sr ($3, @3); }
|
||||
| rhs "%expect-rr" INT
|
||||
| rhs "%expect-rr" INT_LITERAL
|
||||
{ grammar_current_rule_expect_rr ($3, @3); }
|
||||
;
|
||||
|
||||
@@ -765,7 +764,7 @@ value:
|
||||
id:
|
||||
ID
|
||||
{ $$ = symbol_from_uniqstr ($1, @1); }
|
||||
| CHAR
|
||||
| CHAR_LITERAL
|
||||
{
|
||||
const char *var = "api.token.raw";
|
||||
if (current_class == nterm_sym)
|
||||
@@ -1043,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
|
||||
handle_require (location const *loc, char const *version_quoted)
|
||||
{
|
||||
char *version = unquote (version_quoted);
|
||||
required_version = str_to_version (version);
|
||||
required_version = strversion_to_int (version);
|
||||
if (required_version == -1)
|
||||
{
|
||||
complain (loc, complaint, _("invalid version requirement: %s"),
|
||||
@@ -1158,8 +1127,7 @@ char_name (char c)
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
static void
|
||||
current_lhs (symbol *sym, location loc, named_ref *ref)
|
||||
{
|
||||
current_lhs_symbol = sym;
|
||||
|
||||
+15
-19
@@ -28,19 +28,19 @@
|
||||
#include "lssi.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
|
||||
{
|
||||
// elements newly added in this chunk
|
||||
// Elements newly added in this chunk.
|
||||
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 *tail_elt;
|
||||
size_t total_size;
|
||||
} state_items;
|
||||
// list of derivations of the symbols
|
||||
// List of derivations of the symbols.
|
||||
struct deriv_chunk
|
||||
{
|
||||
derivation_list contents;
|
||||
@@ -50,18 +50,15 @@ typedef struct parse_state
|
||||
} derivs;
|
||||
struct parse_state *parent;
|
||||
int reference_count;
|
||||
// incremented during productions,
|
||||
// decremented during reductions
|
||||
// Incremented during productions, decremented during reductions.
|
||||
int depth;
|
||||
// whether the contents of the chunks should be
|
||||
// prepended or appended to the list the chunks
|
||||
// represent
|
||||
// Whether the contents of the chunks should be prepended or
|
||||
// appended to the list the chunks represent.
|
||||
bool prepend;
|
||||
// causes chunk contents to be freed when the
|
||||
// reference count is one. Used when only the chunk metadata
|
||||
// will be needed.
|
||||
// Causes chunk contents to be freed when the reference count is
|
||||
// one. Used when only the chunk metadata will be needed.
|
||||
bool free_contents_early;
|
||||
} parse_state;
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
@@ -438,9 +435,8 @@ simulate_transition (parse_state *ps)
|
||||
// symbols into account.
|
||||
parse_state_list result = parse_state_list_new ();
|
||||
state_item_number si_next = si->trans;
|
||||
// check for disabled transition, shouldn't happen
|
||||
// as any state_items that lead to these should be
|
||||
// disabled.
|
||||
// Check for disabled transition, shouldn't happen as any
|
||||
// state_items that lead to these should be disabled.
|
||||
if (si_next < 0)
|
||||
return result;
|
||||
parse_state *next_ps = copy_parse_state (false, ps);
|
||||
@@ -594,8 +590,8 @@ print_parse_state (parse_state *ps)
|
||||
FILE *out = stderr;
|
||||
fprintf (out, "(size %zu depth %d rc %d)\n",
|
||||
ps->state_items.total_size, ps->depth, ps->reference_count);
|
||||
print_state_item (ps->state_items.head_elt, out, "");
|
||||
print_state_item (ps->state_items.tail_elt, out, "");
|
||||
state_item_print (ps->state_items.head_elt, out, "");
|
||||
state_item_print (ps->state_items.tail_elt, out, "");
|
||||
if (ps->derivs.total_size > 0)
|
||||
derivation_print (ps->derivs.head_elt, out, "");
|
||||
putc ('\n', out);
|
||||
|
||||
+8
-5
@@ -406,8 +406,8 @@ grammar_midrule_action (void)
|
||||
action. Create the MIDRULE. */
|
||||
location dummy_loc = current_rule->action_props.location;
|
||||
symbol *dummy = dummy_symbol_get (dummy_loc);
|
||||
symbol_type_set(dummy,
|
||||
current_rule->action_props.type, current_rule->action_props.location);
|
||||
symbol_type_set (dummy,
|
||||
current_rule->action_props.type, current_rule->action_props.location);
|
||||
symbol_list *midrule = symbol_list_sym_new (dummy, dummy_loc);
|
||||
|
||||
/* Remember named_ref of previous action. */
|
||||
@@ -804,7 +804,7 @@ check_and_convert_grammar (void)
|
||||
|
||||
$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->next = symbol_list_sym_new (startsymbol, empty_loc);
|
||||
p->next->next = symbol_list_sym_new (eoftoken, empty_loc);
|
||||
@@ -815,8 +815,11 @@ check_and_convert_grammar (void)
|
||||
grammar = p;
|
||||
}
|
||||
|
||||
aver (nsyms <= SYMBOL_NUMBER_MAXIMUM);
|
||||
aver (nsyms == ntokens + nnterms);
|
||||
if (SYMBOL_NUMBER_MAXIMUM - nnterms < ntokens)
|
||||
complain (NULL, fatal, "too many symbols in input grammar (limit is %d)",
|
||||
SYMBOL_NUMBER_MAXIMUM);
|
||||
|
||||
nsyms = ntokens + nnterms;
|
||||
|
||||
/* Assign the symbols their symbol numbers. */
|
||||
symbols_pack ();
|
||||
|
||||
+4
-4
@@ -160,9 +160,9 @@ inaccessable_symbols (void)
|
||||
bitset Pp = bitset_create (nrules, BITSET_FIXED);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
@@ -301,7 +301,7 @@ nonterminals_reduce (void)
|
||||
for (item_number *rhsp = rules[r].rhs; 0 <= *rhsp; ++rhsp)
|
||||
if (ISVAR (*rhsp))
|
||||
*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;
|
||||
@@ -381,7 +381,7 @@ reduce_grammar (void)
|
||||
{
|
||||
reduce_print ();
|
||||
|
||||
if (!bitset_test (N, accept->content->number - ntokens))
|
||||
if (!bitset_test (N, acceptsymbol->content->number - ntokens))
|
||||
complain (&startsymbol_loc, fatal,
|
||||
_("start symbol %s does not derive any sentence"),
|
||||
startsymbol->tag);
|
||||
|
||||
+21
-12
@@ -322,8 +322,8 @@ eqopt ({sp}=)?
|
||||
BEGIN SC_AFTER_IDENTIFIER;
|
||||
}
|
||||
|
||||
{int} RETURN_VALUE (INT, scan_integer (yytext, 10, *loc));
|
||||
{xint} RETURN_VALUE (INT, scan_integer (yytext, 16, *loc));
|
||||
{int} RETURN_VALUE (INT_LITERAL, scan_integer (yytext, 10, *loc));
|
||||
{xint} RETURN_VALUE (INT_LITERAL, scan_integer (yytext, 16, *loc));
|
||||
|
||||
/* Identifiers may not start with a digit. Yet, don't silently
|
||||
accept "1FOO" as "1 FOO". */
|
||||
@@ -403,6 +403,7 @@ eqopt ({sp}=)?
|
||||
{
|
||||
\0 {
|
||||
complain (loc, complaint, _("invalid null character"));
|
||||
STRING_FINISH ();
|
||||
STRING_FREE ();
|
||||
return GRAM_error;
|
||||
}
|
||||
@@ -566,6 +567,8 @@ eqopt ({sp}=)?
|
||||
_("POSIX Yacc does not support string literals"));
|
||||
RETURN_VALUE (STRING, last_string);
|
||||
}
|
||||
<<EOF>> unexpected_eof (token_start, "\"");
|
||||
"\n" unexpected_newline (token_start, "\"");
|
||||
}
|
||||
|
||||
<SC_ESCAPED_TSTRING>
|
||||
@@ -579,13 +582,10 @@ eqopt ({sp}=)?
|
||||
_("POSIX Yacc does not support string literals"));
|
||||
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 ();
|
||||
BEGIN INITIAL;
|
||||
loc->start = token_start;
|
||||
val->CHAR = last_string[0];
|
||||
|
||||
if (last_string[0] == '\0')
|
||||
{
|
||||
@@ -615,8 +614,9 @@ eqopt ({sp}=)?
|
||||
}
|
||||
else
|
||||
{
|
||||
val->CHAR_LITERAL = last_string[0];
|
||||
STRING_FREE ();
|
||||
return CHAR;
|
||||
return CHAR_LITERAL;
|
||||
}
|
||||
}
|
||||
{eol} unexpected_newline (token_start, "'");
|
||||
@@ -691,6 +691,15 @@ eqopt ({sp}=)?
|
||||
p);
|
||||
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
|
||||
handle_syncline (char *args, location loc)
|
||||
|
||||
+3
-3
@@ -475,7 +475,7 @@ prune_disabled_paths (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);
|
||||
item_print (si->item, NULL, out);
|
||||
@@ -506,7 +506,7 @@ state_items_report (void)
|
||||
if (si->trans >= 0)
|
||||
{
|
||||
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 };
|
||||
@@ -521,7 +521,7 @@ state_items_report (void)
|
||||
BITSET_FOR_EACH (biter, b, sin, 0)
|
||||
{
|
||||
fputs (txt[seti], stdout);
|
||||
print_state_item (&state_items[sin], stdout, "");
|
||||
state_item_print (&state_items[sin], stdout, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -90,9 +90,10 @@ state_item_index_lookup (state_number s, state_item_number off)
|
||||
}
|
||||
|
||||
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_item_print (const state_item *si, FILE *out, const char *prefix);
|
||||
|
||||
bool production_allowed (const state_item *si, const state_item *next);
|
||||
|
||||
// Iterating on a state_item_list.
|
||||
|
||||
@@ -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_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)
|
||||
symbol_type_set (l->content.sym, type_name, loc);
|
||||
symbol_type_set (l->content.sym, type_name, l->sym_loc);
|
||||
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.
|
||||
** \returns \c syms */
|
||||
symbol_list *symbol_list_type_set (symbol_list *syms,
|
||||
uniqstr type_name, location loc);
|
||||
symbol_list *symbol_list_type_set (symbol_list *syms, uniqstr type_name);
|
||||
|
||||
/** Print this list.
|
||||
|
||||
|
||||
+33
-36
@@ -59,7 +59,7 @@ static semantic_type **semantic_types_sorted = NULL;
|
||||
symbol *errtoken = NULL;
|
||||
symbol *undeftoken = NULL;
|
||||
symbol *eoftoken = NULL;
|
||||
symbol *accept = NULL;
|
||||
symbol *acceptsymbol = NULL;
|
||||
symbol *startsymbol = NULL;
|
||||
location startsymbol_loc;
|
||||
|
||||
@@ -137,11 +137,6 @@ symbol_new (uniqstr tag, location loc)
|
||||
res->alias = NULL;
|
||||
res->content = sym_content_new (res);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -182,11 +177,11 @@ symbol_free (void *ptr)
|
||||
*/
|
||||
|
||||
static void
|
||||
symbols_sort (symbol **first, symbol **second)
|
||||
symbols_sort (const symbol **first, const symbol **second)
|
||||
{
|
||||
if (0 < location_cmp ((*first)->location, (*second)->location))
|
||||
{
|
||||
symbol* tmp = *first;
|
||||
const symbol* tmp = *first;
|
||||
*first = *second;
|
||||
*second = tmp;
|
||||
}
|
||||
@@ -243,7 +238,11 @@ semantic_type_new (uniqstr tag, const location *loc)
|
||||
| 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) \
|
||||
fprintf (f, " %s { %s }", #Attr, s->content->Attr)
|
||||
|
||||
@@ -264,7 +263,11 @@ symbol_print (symbol const *s, FILE *f)
|
||||
: c == nterm_sym ? "nterm"
|
||||
: NULL, /* abort. */
|
||||
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 (printer);
|
||||
}
|
||||
@@ -371,7 +374,7 @@ symbol_from_uniqstr_fuzzy (const uniqstr key)
|
||||
}
|
||||
|
||||
static void
|
||||
complain_symbol_undeclared (symbol *sym)
|
||||
complain_symbol_undeclared (const symbol *sym)
|
||||
{
|
||||
assert (sym->content->status != declared);
|
||||
const symbol *best = symbol_from_uniqstr_fuzzy (sym->tag);
|
||||
@@ -398,7 +401,10 @@ void
|
||||
symbol_location_as_lhs_set (symbol *sym, location loc)
|
||||
{
|
||||
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)
|
||||
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;
|
||||
|
||||
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
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -621,9 +619,11 @@ symbol_check_defined (symbol *sym)
|
||||
{
|
||||
complain_symbol_undeclared (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
|
||||
&& sym->tag[0] == '"'
|
||||
&& !sym->is_alias)
|
||||
@@ -742,7 +742,7 @@ symbol_pack (symbol *sym)
|
||||
}
|
||||
|
||||
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);
|
||||
complain (&second->location, complaint,
|
||||
@@ -758,13 +758,11 @@ complain_code_redeclared (int num, symbol *first, symbol *second)
|
||||
`-------------------------------------------------*/
|
||||
|
||||
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]
|
||||
!= undeftoken->content->number)
|
||||
complain_code_redeclared
|
||||
@@ -849,10 +847,10 @@ symbols_new (void)
|
||||
hash_symbol_comparator,
|
||||
symbol_free);
|
||||
|
||||
/* Construct the accept symbol. */
|
||||
accept = symbol_get ("$accept", empty_loc);
|
||||
accept->content->class = nterm_sym;
|
||||
accept->content->number = nnterms++;
|
||||
/* Construct the acceptsymbol symbol. */
|
||||
acceptsymbol = symbol_get ("$accept", empty_loc);
|
||||
acceptsymbol->content->class = nterm_sym;
|
||||
acceptsymbol->content->number = nnterms++;
|
||||
|
||||
/* Construct the YYerror/"error" token */
|
||||
errtoken = symbol_get ("YYerror", empty_loc);
|
||||
@@ -969,7 +967,6 @@ dummy_symbol_get (location loc)
|
||||
assure (len < sizeof buf);
|
||||
symbol *sym = symbol_get (buf, loc);
|
||||
sym->content->class = nterm_sym;
|
||||
sym->content->number = nnterms++;
|
||||
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
|
||||
TABLE, sorted (alphabetically) by tag. */
|
||||
TABLE, sorted by order of appearance (i.e., by location). */
|
||||
|
||||
static void
|
||||
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,
|
||||
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);
|
||||
|
||||
|
||||
@@ -245,7 +245,7 @@ extern symbol *eoftoken;
|
||||
/** The genuine start symbol.
|
||||
|
||||
$accept: start-symbol $end */
|
||||
extern symbol *accept;
|
||||
extern symbol *acceptsymbol;
|
||||
|
||||
/** The user start symbol. */
|
||||
extern symbol *startsymbol;
|
||||
|
||||
@@ -131,6 +131,22 @@ typedef size_t uintptr_t;
|
||||
# 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. |
|
||||
|
||||
@@ -915,6 +915,12 @@ AT_BISON_OPTION_PUSHDEFS([$1])
|
||||
|
||||
AT_DATA_CALC_Y([$1])
|
||||
AT_FULL_COMPILE(AT_JAVA_IF([[Calc]], [[calc]]), AT_DEFINES_IF([[lex], [main]], [[], []]), [$2], [-Wno-deprecated])
|
||||
|
||||
AT_YACC_IF(
|
||||
[# No direct calls to malloc/free.
|
||||
AT_CHECK([[$EGREP '(malloc|free) *\(' calc.[ch] | $EGREP -v 'INFRINGES ON USER NAME SPACE']],
|
||||
[1])])
|
||||
|
||||
AT_PUSH_IF([AT_JAVA_IF(
|
||||
[# Verify that this is a push parser.
|
||||
AT_CHECK_JAVA_GREP([[Calc.java]],
|
||||
|
||||
+27
-9
@@ -204,17 +204,20 @@ AT_SETUP([Several parsers])
|
||||
# Generate and compile to *.o. Make sure there is no (allowed) YY*
|
||||
# nor yy* identifiers in the header after applying api.prefix. Check
|
||||
# that headers can be compiled by a C++ compiler.
|
||||
#
|
||||
# They should all use parse.assert to make sure that we don't even
|
||||
# conflict of YY_ASSERT.
|
||||
m4_pushdef([AT_TEST],
|
||||
[AT_BISON_OPTION_PUSHDEFS([%define api.prefix {$1_} $2])
|
||||
[AT_BISON_OPTION_PUSHDEFS([%define api.prefix {$1_} %define parse.assert $2])
|
||||
AT_DATA_GRAMMAR([$1.y],
|
||||
[[%define api.prefix {$1_}
|
||||
%define parse.assert
|
||||
$2
|
||||
%define parse.error verbose
|
||||
%union
|
||||
{
|
||||
int integer;
|
||||
}
|
||||
%{
|
||||
]AT_VARIANT_IF([],
|
||||
[%union {int integer;}])[
|
||||
|
||||
%code {
|
||||
#include <stdio.h> /* printf. */
|
||||
]AT_PUSH_IF([[
|
||||
#if defined __GNUC__ && (7 == __GNUC__ || 9 == __GNUC__)
|
||||
@@ -223,8 +226,10 @@ $2
|
||||
]])[
|
||||
]AT_YYERROR_DECLARE[
|
||||
]AT_YYLEX_DECLARE[
|
||||
%}
|
||||
}
|
||||
|
||||
%%
|
||||
|
||||
exp:
|
||||
'x' '1' { printf ("x1\n"); }
|
||||
| 'x' '2' { printf ("x2\n"); }
|
||||
@@ -235,9 +240,12 @@ exp:
|
||||
| 'x' '7' { printf ("x7\n"); }
|
||||
| 'x' '8' { printf ("x8\n"); }
|
||||
| 'x' '9' { printf ("x9\n"); }
|
||||
| 'x' 'a' { printf ("xa\n"); }
|
||||
| 'x' 'b' { printf ("xb\n"); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
]AT_YYERROR_DEFINE[
|
||||
]AT_YYLEX_DEFINE(["$1"])[
|
||||
]])
|
||||
@@ -270,6 +278,8 @@ extern "C"
|
||||
#endif
|
||||
#include "x5.hh"
|
||||
#include "x9.hh"
|
||||
#include "xa.hh"
|
||||
#include "xb.hh"
|
||||
|
||||
#define RUN(S) \
|
||||
do { \
|
||||
@@ -292,6 +302,10 @@ main (void)
|
||||
RUN(x8_parse());
|
||||
x9_::parser p9;
|
||||
RUN(p9.parse());
|
||||
xa_::parser pa;
|
||||
RUN(pa.parse());
|
||||
xb_::parser pb;
|
||||
RUN(pb.parse());
|
||||
return 0;
|
||||
}
|
||||
]])# main.cc
|
||||
@@ -304,7 +318,9 @@ AT_TEST([x5], [%locations %debug %language "c++"])
|
||||
AT_TEST([x6], [%define api.pure])
|
||||
AT_TEST([x7], [%define api.push-pull both])
|
||||
AT_TEST([x8], [%define api.pure %define api.push-pull both])
|
||||
AT_TEST([x9], [%locations %code requires {#include "location.hh"} %define api.location.type {x5_::location} %debug %language "c++"])
|
||||
AT_TEST([x9], [%locations %code requires {#include "location.hh"} %define api.location.type {::x5_::location} %debug %language "c++"])
|
||||
AT_TEST([xa], [%locations %code requires {#include "location.hh"} %define api.location.type {::x5_::location} %language "c++" %define api.value.type variant])
|
||||
AT_TEST([xb], [%locations %define api.location.file none %language "c++" %define api.value.type variant])
|
||||
#AT_TEST([x5], [%locations %language "c++" %glr-parser])
|
||||
|
||||
# Check that api.prefix works properly:
|
||||
@@ -340,6 +356,8 @@ AT_PERL_CHECK([[-n -0777 -e '
|
||||
|YY_NULLPTR
|
||||
|YY_RVREF
|
||||
|YY_\w+_INCLUDED
|
||||
|FILE\ \*yyo # Function argument.
|
||||
|const\ yylocp # Function argument.
|
||||
)\b}{}gx;
|
||||
while (/^(.*YY.*)$/gm)
|
||||
{
|
||||
@@ -357,7 +375,7 @@ AT_PERL_CHECK([[-n -0777 -e '
|
||||
# Do this late, so that other checks have been performed.
|
||||
AT_SKIP_IF_CANNOT_LINK_C_AND_CXX
|
||||
|
||||
AT_COMPILE_CXX([parser], [[x[1-9].o -DCC_IS_CXX=$CC_IS_CXX main.cc]])
|
||||
AT_COMPILE_CXX([parser], [[x[1-9a-b].o -DCC_IS_CXX=$CC_IS_CXX main.cc]])
|
||||
AT_PARSER_CHECK([parser], [0], [[expout]])
|
||||
|
||||
m4_popdef([AT_TEST])
|
||||
|
||||
+166
-19
@@ -1,4 +1,4 @@
|
||||
# Checking the Bison scanner. -*- Autotest -*-
|
||||
# Checking the Bison reader. -*- Autotest -*-
|
||||
|
||||
# Copyright (C) 2002-2015, 2018-2020 Free Software Foundation, Inc.
|
||||
|
||||
@@ -78,10 +78,13 @@ AT_CLEANUP
|
||||
## Invalid inputs. ##
|
||||
## ---------------- ##
|
||||
|
||||
# The truly bad guys no human would write, but easily uncovered by
|
||||
# fuzzers.
|
||||
AT_SETUP([Invalid inputs])
|
||||
|
||||
AT_DATA([input.y],
|
||||
[[\000\001\002\377?
|
||||
"\000"
|
||||
%%
|
||||
?
|
||||
default: 'a' }
|
||||
@@ -92,21 +95,50 @@ default: 'a' }
|
||||
]])
|
||||
AT_PERL_REQUIRE([[-pi -e 's/\\(\d{3})/chr(oct($1))/ge' input.y]])
|
||||
|
||||
AT_BISON_CHECK([input.y], [1], [],
|
||||
AT_BISON_CHECK([-fcaret input.y], [1], [], [stderr])
|
||||
|
||||
# Autotest's diffing, when there are NUL bytes, just reports "binary
|
||||
# files differ". So don't leave NUL bytes.
|
||||
AT_PERL_CHECK([[-p -e 's{([\0\377])}{sprintf "\\x%02x", ord($1)}ge' stderr]], [],
|
||||
[[input.y:1.1-2: error: invalid characters: '\0\001\002\377?'
|
||||
input.y:3.1: error: invalid character: '?'
|
||||
input.y:4.14: error: invalid character: '}'
|
||||
input.y:5.1: error: invalid character: '%'
|
||||
input.y:5.2: error: invalid character: '&'
|
||||
input.y:6.1-17: error: invalid directive: '%a-does-not-exist'
|
||||
input.y:7.1: error: invalid character: '%'
|
||||
input.y:7.2: error: invalid character: '-'
|
||||
input.y:8.1-9.0: error: missing '%}' at end of file
|
||||
1 | \x00\xff?
|
||||
| ^~
|
||||
input.y:2.2: error: invalid null character
|
||||
2 | "\x00"
|
||||
| ^
|
||||
input.y:4.1: error: invalid character: '?'
|
||||
4 | ?
|
||||
| ^
|
||||
input.y:5.14: error: invalid character: '}'
|
||||
5 | default: 'a' }
|
||||
| ^
|
||||
input.y:6.1: error: invalid character: '%'
|
||||
6 | %&
|
||||
| ^
|
||||
input.y:6.2: error: invalid character: '&'
|
||||
6 | %&
|
||||
| ^
|
||||
input.y:7.1-17: error: invalid directive: '%a-does-not-exist'
|
||||
7 | %a-does-not-exist
|
||||
| ^~~~~~~~~~~~~~~~~
|
||||
input.y:8.1: error: invalid character: '%'
|
||||
8 | %-
|
||||
| ^
|
||||
input.y:8.2: error: invalid character: '-'
|
||||
8 | %-
|
||||
| ^
|
||||
input.y:9.1-10.0: error: missing '%}' at end of file
|
||||
9 | %{
|
||||
| ^~
|
||||
]])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
## ------------------------ ##
|
||||
## Invalid inputs with {}. ##
|
||||
## ------------------------ ##
|
||||
|
||||
AT_SETUP([Invalid inputs with {}])
|
||||
|
||||
# We used to SEGV here. See
|
||||
@@ -788,6 +820,33 @@ input.y:3.8-10: note: previous declaration
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
## ---------------- ##
|
||||
## EOF redeclared. ##
|
||||
## ---------------- ##
|
||||
|
||||
AT_SETUP([EOF redeclared])
|
||||
|
||||
# We used to crash when redefining a token after having defined EOF.
|
||||
# See https://lists.gnu.org/r/bug-bison/2020-08/msg00008.html.
|
||||
|
||||
AT_DATA([[input.y]],
|
||||
[[%token FOO BAR FOO 0
|
||||
%%
|
||||
input: %empty
|
||||
]])
|
||||
|
||||
AT_BISON_CHECK([-fcaret input.y], [0], [],
|
||||
[[input.y:1.16-18: warning: symbol FOO redeclared [-Wother]
|
||||
1 | %token FOO BAR FOO 0
|
||||
| ^~~
|
||||
input.y:1.8-10: note: previous declaration
|
||||
1 | %token FOO BAR FOO 0
|
||||
| ^~~
|
||||
]])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
## --------------------------- ##
|
||||
## Symbol class redefinition. ##
|
||||
## --------------------------- ##
|
||||
@@ -1224,12 +1283,12 @@ AT_TEST([[%token foo "foo"
|
||||
%%
|
||||
exp: foo;
|
||||
]],
|
||||
[[input.y:3.7-11: error: %type redeclaration for foo
|
||||
[[input.y:3.13-15: error: %type redeclaration for foo
|
||||
3 | %type <baz> foo
|
||||
| ^~~~~
|
||||
input.y:2.7-11: note: previous declaration
|
||||
| ^~~
|
||||
input.y:2.13-17: note: previous declaration
|
||||
2 | %type <bar> "foo"
|
||||
| ^~~~~
|
||||
| ^~~~~
|
||||
]])
|
||||
|
||||
AT_TEST([[%token foo "foo"
|
||||
@@ -1336,11 +1395,6 @@ AT_CLEANUP
|
||||
AT_SETUP([Torturing the Scanner])
|
||||
|
||||
AT_BISON_OPTION_PUSHDEFS
|
||||
AT_DATA([input.y], [])
|
||||
AT_BISON_CHECK([input.y], [1], [],
|
||||
[[input.y:1.1: error: unexpected end of file
|
||||
]])
|
||||
|
||||
|
||||
AT_DATA([input.y],
|
||||
[{}
|
||||
@@ -2447,6 +2501,99 @@ input.y:5.19: error: invalid character after \-escape: \001
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
## ------------------------ ##
|
||||
## Unexpected end of file. ##
|
||||
## ------------------------ ##
|
||||
|
||||
AT_SETUP([[Unexpected end of file]])
|
||||
|
||||
|
||||
AT_DATA([input.y], [])
|
||||
AT_BISON_CHECK([-fcaret input.y], [1], [],
|
||||
[[input.y:1.1: error: unexpected end of file
|
||||
]])
|
||||
|
||||
|
||||
AT_DATA_NO_FINAL_EOL([char.y],
|
||||
[[%token FOO ']])
|
||||
|
||||
AT_BISON_CHECK([-fcaret char.y], [1], [],
|
||||
[[char.y:1.12: error: missing "'" at end of file
|
||||
1 | %token FOO '
|
||||
| ^
|
||||
char.y:1.12: error: empty character literal
|
||||
1 | %token FOO '
|
||||
| ^
|
||||
]])
|
||||
|
||||
|
||||
AT_DATA_NO_FINAL_EOL([escape-in-char.y],
|
||||
[[%token FOO '\]])
|
||||
|
||||
AT_BISON_CHECK([-fcaret escape-in-char.y], [1], [],
|
||||
[[escape-in-char.y:1.12-13: error: missing '?\'' at end of file
|
||||
1 | %token FOO '\
|
||||
| ^~
|
||||
escape-in-char.y:1.14: error: unexpected end of file
|
||||
1 | %token FOO '\
|
||||
| ^
|
||||
]])
|
||||
|
||||
|
||||
AT_DATA_NO_FINAL_EOL([string.y],
|
||||
[[%token FOO "]])
|
||||
|
||||
AT_BISON_CHECK([-fcaret string.y], [1], [],
|
||||
[[string.y:1.12: error: missing '"' at end of file
|
||||
1 | %token FOO "
|
||||
| ^
|
||||
string.y:1.13: error: unexpected end of file
|
||||
1 | %token FOO "
|
||||
| ^
|
||||
]])
|
||||
|
||||
|
||||
AT_DATA_NO_FINAL_EOL([escape-in-string.y],
|
||||
[[%token FOO "\]])
|
||||
|
||||
AT_BISON_CHECK([-fcaret escape-in-string.y], [1], [],
|
||||
[[escape-in-string.y:1.12-13: error: missing '?"' at end of file
|
||||
1 | %token FOO "\
|
||||
| ^~
|
||||
escape-in-string.y:1.14: error: unexpected end of file
|
||||
1 | %token FOO "\
|
||||
| ^
|
||||
]])
|
||||
|
||||
|
||||
AT_DATA_NO_FINAL_EOL([tstring.y],
|
||||
[[%token FOO _("]])
|
||||
|
||||
AT_BISON_CHECK([-fcaret tstring.y], [1], [],
|
||||
[[tstring.y:1.12-14: error: missing '")' at end of file
|
||||
1 | %token FOO _("
|
||||
| ^~~
|
||||
tstring.y:1.15: error: unexpected end of file
|
||||
1 | %token FOO _("
|
||||
| ^
|
||||
]])
|
||||
|
||||
|
||||
AT_DATA_NO_FINAL_EOL([escape-in-tstring.y],
|
||||
[[%token FOO _("\]])
|
||||
|
||||
AT_BISON_CHECK([-fcaret escape-in-tstring.y], [1], [],
|
||||
[[escape-in-tstring.y:1.12-15: error: missing '?")' at end of file
|
||||
1 | %token FOO _("\
|
||||
| ^~~~
|
||||
escape-in-tstring.y:1.16: error: unexpected end of file
|
||||
1 | %token FOO _("\
|
||||
| ^
|
||||
]])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
## ------------------------- ##
|
||||
## LAC: Errors for %define. ##
|
||||
## ------------------------- ##
|
||||
|
||||
+2
-1
@@ -351,7 +351,7 @@ AT_TOKEN_CTOR_IF(
|
||||
[m4_pushdef([AT_LOC], [[(]AT_NAME_PREFIX[lloc)]])
|
||||
m4_pushdef([AT_VAL], [[(]AT_NAME_PREFIX[lval)]])
|
||||
m4_pushdef([AT_YYLEX_FORMALS], [])
|
||||
m4_pushdef([AT_YYLEX_RETURN], [yy::parser::symbol_type])
|
||||
m4_pushdef([AT_YYLEX_RETURN], [AT_NAMESPACE::parser::symbol_type])
|
||||
m4_pushdef([AT_YYLEX_ARGS], [])
|
||||
m4_pushdef([AT_USE_LEX_ARGS], [])
|
||||
m4_pushdef([AT_YYLEX_PRE_FORMALS], [])
|
||||
@@ -390,6 +390,7 @@ AT_LOCATION_TYPE_SPAN_IF(
|
||||
|
||||
|
||||
AT_GLR_IF([AT_KEYWORDS([glr])])
|
||||
AT_PUSH_IF([AT_KEYWORDS([push])])
|
||||
])# _AT_BISON_OPTION_PUSHDEFS
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -759,7 +759,7 @@ AT_TEST([x1],
|
||||
])
|
||||
|
||||
# Check the CPP guard and Doxyen comments.
|
||||
AT_CHECK([sed -ne 's/#line [0-9]\+ "/#line "/p;/INCLUDED/p;/\\file/{p;n;p;}' out/include/ast/loc.hh], [],
|
||||
AT_CHECK([[sed -ne 's/#line [0-9][0-9]* "/#line "/p;/INCLUDED/p;/\\file/{p;n;p;}' out/include/ast/loc.hh]], [],
|
||||
[[ ** \file bar/include/ast/loc.hh
|
||||
** Define the x1::location class.
|
||||
#ifndef YY_YY_BAR_INCLUDE_AST_LOC_HH_INCLUDED
|
||||
@@ -771,7 +771,7 @@ AT_CHECK([sed -ne 's/#line [0-9]\+ "/#line "/p;/INCLUDED/p;/\\file/{p;n;p;}' out
|
||||
#endif // !YY_YY_BAR_INCLUDE_AST_LOC_HH_INCLUDED
|
||||
]])
|
||||
|
||||
AT_CHECK([sed -ne 's/^#line [0-9]\+ "/#line "/p;/INCLUDED/p;/\\file/{p;n;p;}' out/x1.hh], [],
|
||||
AT_CHECK([[sed -ne 's/^#line [0-9][0-9]* "/#line "/p;/INCLUDED/p;/\\file/{p;n;p;}' out/x1.hh]], [],
|
||||
[[ ** \file bar/x1.hh
|
||||
** Define the x1::parser class.
|
||||
#ifndef YY_YY_BAR_X1_HH_INCLUDED
|
||||
|
||||
Reference in New Issue
Block a user