Compare commits

...
21 Commits
Author SHA1 Message Date
Akim Demaille 71579c7219 version 3.7.1
* NEWS: Record release date.
2020-08-02 09:10:02 +02:00
Akim Demaille 2f8a874215 portability: we use termios.h and sys/ioctl.h
Reported by Maarten De Braekeleer.
https://lists.gnu.org/r/bison-patches/2020-07/msg00079.html

* bootstrap.conf (gnulib_modules): Add termios and sys_ioctl.
2020-08-02 08:36:49 +02:00
Maarten De BraekeleerandAkim Demaille ad6f600bb1 portability: rename accept to acceptsymbol because of MSVC
MSVC already defines this symbol.

* src/symtab.h, src/symtab.c (accept): Rename as...
(acceptsymbol): this.
Adjust dependencies.
2020-08-02 08:32:57 +02:00
Akim Demaille de4f41eab7 regen 2020-08-02 08:32:57 +02:00
Maarten De BraekeleerandAkim Demaille e73f086b0d portability: use CHAR_LITERAL instead of CHAR because MSVC defines CHAR
* src/parse-gram.y, src/scan-gram.l: here.
2020-08-02 08:32:57 +02:00
Maarten De BraekeleerandAkim Demaille 8cf098415e portability: use INT_LITERAL instead of INT because MSVC defines INT
It is defined as a typedef, not a macro.
https://lists.gnu.org/r/bison-patches/2020-08/msg00001.html

* src/parse-gram.y, src/scan-gram.l: here.
2020-08-02 08:32:30 +02:00
Akim Demaille 977e19840d portability: beware of max () with MSVC
Reported by Maarten De Braekeleer.
https://lists.gnu.org/r/bison-patches/2020-07/msg00080.html

We don't want to use gnulib's min and max macros, since we use
function calls in min/max arguments.

* src/location.c (max_int, min_int): Move to...
* src/system.h: here.
* src/counterexample.c, src/derivation.c: Use max_int instead of max.
2020-08-02 08:19:35 +02:00
Akim Demaille d975c2f76e libtextstyle: be sure to have ostream_printf and hyperlink support
Older versions of libtextstyle do not support them, rule them out.

Reported by Lars Wendler
https://lists.gnu.org/r/bug-bison/2020-07/msg00030.html

and by Arnold Robbins
https://lists.gnu.org/r/bug-bison/2020-07/msg00041.html and
https://lists.gnu.org/mailman/private/gawk-devel/2020-July/003988.html

and by Nelson H. F. Beebe
https://lists.gnu.org/mailman/private/gawk-devel/2020-July/003993.html

With support from Bruno Haible in gnulib
https://lists.gnu.org/r/bug-gnulib/2020-08/msg00000.html
thread starting at
https://lists.gnu.org/r/bug-gnulib/2020-07/msg00148.html

* configure.ac: Require libtextstyle 0.20.5.
* gnulib: Update.
2020-08-02 08:19:35 +02:00
Akim Demaille 0676801b8c CI: comment changes 2020-08-01 10:02:44 +02:00
Akim Demaille 82aa96e9b1 regen 2020-08-01 08:54:46 +02:00
Akim Demaille cb65553449 diagnostics: better location for type redeclarations
From

    foo.y:1.7-11: error: %type redeclaration for bar
        1 | %type <foo> bar bar
          |       ^~~~~
    foo.y:1.7-11: note: previous declaration
        1 | %type <foo> bar bar
          |       ^~~~~

to

    foo.y:1.17-19: error: %type redeclaration for bar
        1 | %type <foo> bar bar
          |                 ^~~
    foo.y:1.13-15: note: previous declaration
        1 | %type <foo> bar bar
          |             ^~~

* src/symlist.h, src/symlist.c (symbol_list_type_set): There's no need
for the tag's location, use that of the symbol.
* src/parse-gram.y: Adjust.
* tests/input.at: Adjust.
2020-08-01 08:54:46 +02:00
Akim Demaille f47a1bd622 todo: updates for D 2020-07-30 07:14:57 +02:00
Akim Demaille 205d372c68 cex: style: comment changes
* src/parse-simulation.c: here.
2020-07-29 20:00:59 +02:00
Akim Demaille 07a1243b40 cex: style: prefer "res" for the returned value
* src/derivation.c (derivation_new): here.
2020-07-29 20:00:59 +02:00
Akim Demaille ece343d2c2 cex: style: prefer FOO_print to print_FOO
* src/state-item.h, src/state-item.c (print_state_item): Rename as...
(state_item_print): this.
* src/counterexample.c (print_counterexample): Rename as...
(counterexample_print): this.
2020-07-29 20:00:27 +02:00
Akim Demaille be95a4fe29 scanner: don't crash on strings containing a NUL byte
We crash if the input contains a string containing a NUL byte.
Reported by Suhwan Song.
https://lists.gnu.org/r/bug-bison/2020-07/msg00051.html

* src/flex-scanner.h (STRING_FREE): Avoid accidental use of
last_string.
* src/scan-gram.l: Don't call STRING_FREE without calling
STRING_FINISH first.
* tests/input.at (Invalid inputs): Check that case.
2020-07-28 19:01:48 +02:00
Akim Demaille 6accee7716 doc: refer to cex from sections dealing with conflicts
The documentation about -Wcex should be put forward.

* doc/bison.texi: Refer to -Wcex from the sections about conflicts.
2020-07-28 07:45:07 +02:00
Akim Demaille e63f22703e doc: factor ifnottex/iftex examples
* doc/bison.texi: Factor the common bits out of ifnottex/iftex.
2020-07-28 07:45:07 +02:00
Akim Demaille fa390dc311 doc: fix colors
The original Texinfo macros introducing colors were made for
diagnostics, which are printed in bold.  So by copy-paste accident the
styles we introduced for counterexamples were also in bold.  They
should not.

* doc/bison.texi: Separate the styling of diagnostics from the styling
for counterexamples.
Don't use bold in the latter case.
2020-07-28 07:45:07 +02:00
Akim Demaille 17fdf5eca2 doc: fixes
* doc/bison.texi: Fix spello.
Fix missing colors, and factor.
2020-07-28 07:45:07 +02:00
Akim Demaille 72b3c1a673 maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2020-07-23 20:15:38 +02:00
33 changed files with 611 additions and 244 deletions
+1 -1
View File
@@ -1 +1 @@
3.6.93 3.7
+2
View File
@@ -119,6 +119,8 @@ jobs:
- CXX='clang++-10 -fsanitize=address -stdlib=libc++' - CXX='clang++-10 -fsanitize=address -stdlib=libc++'
- PART=2 - PART=2
# See https://github.com/simd-everywhere/simde/blob/master/.travis.yml
# and https://software.intel.com/content/www/us/en/develop/documentation/get-started-with-intel-oneapi-render-linux/top/configure-your-system.html.
- name: "ICC" - name: "ICC"
stage: check stage: check
os: linux os: linux
+17
View File
@@ -1,5 +1,22 @@
GNU Bison NEWS GNU Bison NEWS
* 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] * Noteworthy changes in release 3.7 (2020-07-23) [stable]
** Deprecated features ** Deprecated features
+12 -3
View File
@@ -42,9 +42,11 @@ installing it. In that case, do not use `src/bison`: it would use the
As an experimental feature, diagnostics are now colored, controlled by the As an experimental feature, diagnostics are now colored, controlled by the
`--color` and `--style` options. `--color` and `--style` options.
To use them, install the libtextstyle library before configuring Bison. It To use them, install the libtextstyle library, 0.20.5 or newer, before
is available from https://alpha.gnu.org/gnu/gettext/, for instance configuring Bison. It is available from https://alpha.gnu.org/gnu/gettext/,
https://alpha.gnu.org/pub/gnu/gettext/libtextstyle-0.20.5.tar.gz. for instance https://alpha.gnu.org/gnu/gettext/libtextstyle-0.20.5.tar.gz,
or as part of Gettext 0.21 or newer, for instance
https://ftp.gnu.org/gnu/gettext/gettext-0.21.tar.gz.
The option --color supports the following arguments: The option --color supports the following arguments:
- always, yes: Enable colors. - always, yes: Enable colors.
@@ -61,6 +63,13 @@ To customize the styles, create a CSS file, say `bison-bw.css`, similar to
then invoke bison with `--style=bison-bw.css`, or set the `BISON_STYLE` then invoke bison with `--style=bison-bw.css`, or set the `BISON_STYLE`
environment variable to `bison-bw.css`. environment variable to `bison-bw.css`.
In some diagnostics, bison uses libtextstyle to emit special escapes to
generate clickable hyperlinks. The environment variable
`NO_TERM_HYPERLINKS` can be used to suppress them. This may be useful for
terminal emulators which produce garbage output when they receive the escape
sequence for a hyperlink. Currently (as of 2020), this affects some versions
of emacs, guake, konsole, lxterminal, rxvt, yakuake.
## Relocatability ## Relocatability
If you pass `--enable-relocatable` to `configure`, Bison is relocatable. If you pass `--enable-relocatable` to `configure`, Bison is relocatable.
+3
View File
@@ -106,9 +106,11 @@ Keith Browne [email protected]
Ken Moffat [email protected] Ken Moffat [email protected]
Kiyoshi Kanazawa [email protected] Kiyoshi Kanazawa [email protected]
Lars Maier [email protected] Lars Maier [email protected]
Lars Wendler [email protected]
László Várady [email protected] László Várady [email protected]
Laurent Mascherpa [email protected] Laurent Mascherpa [email protected]
Lie Yan [email protected] Lie Yan [email protected]
Maarten De Braekeleer [email protected]
Magnus Fromreide [email protected] Magnus Fromreide [email protected]
Marc Autret [email protected] Marc Autret [email protected]
Marc Mendiola [email protected] Marc Mendiola [email protected]
@@ -185,6 +187,7 @@ Simon Sobisch [email protected]
Stefano Lattarini [email protected] Stefano Lattarini [email protected]
Stephen Cameron [email protected] Stephen Cameron [email protected]
Steve Murphy [email protected] Steve Murphy [email protected]
Suhwan Song [email protected]
Sum Wu [email protected] Sum Wu [email protected]
Théophile Ranquet [email protected] Théophile Ranquet [email protected]
Thiru Ramakrishnan [email protected] Thiru Ramakrishnan [email protected]
+297 -15
View File
@@ -48,13 +48,6 @@ Unless we play it dumb (little structure).
- promote YYEOF rather than EOF. - promote YYEOF rather than EOF.
*** D
- is there a way to attach yysymbol_name to the enum itself? As we did
in Java.
- It would be better to have TokenKind as return value. Can we use
reflection to support both output types?
** YYerror ** YYerror
https://git.savannah.gnu.org/gitweb/?p=gettext.git;a=blob;f=gettext-runtime/intl/plural.y;h=a712255af4f2f739c93336d4ff6556d932a426a5;hb=HEAD https://git.savannah.gnu.org/gitweb/?p=gettext.git;a=blob;f=gettext-runtime/intl/plural.y;h=a712255af4f2f739c93336d4ff6556d932a426a5;hb=HEAD
@@ -67,7 +60,7 @@ Stop hard-coding "Calc". Adjust local.at (look for FIXME).
** A dev warning for b4_ ** A dev warning for b4_
Maybe we should check for m4_ and b4_ leaking out of the m4 processing, as Maybe we should check for m4_ and b4_ leaking out of the m4 processing, as
Autoconf does. It would have caught overquotation issues. Autoconf does. It would have caught over-quotation issues.
** doc ** doc
I feel it's ugly to use the GNU style to declare functions in the doc. It I feel it's ugly to use the GNU style to declare functions in the doc. It
@@ -88,7 +81,7 @@ push parsers on top of pull parser. Which is currently not relevant, since
push parsers are measurably slower. push parsers are measurably slower.
** %define parse.error formatted ** %define parse.error formatted
How about pushing bistromathics' yyreport_syntax_error as another standard How about pushing Bistromathic's yyreport_syntax_error as another standard
way to generate the error message, and leave to the user the task of way to generate the error message, and leave to the user the task of
providing the message formats? Currently in bistro, it reads: providing the message formats? Currently in bistro, it reads:
@@ -202,18 +195,282 @@ The "automaton" and "set" categories are not so useful. We should probably
introduce lr(0) and lalr, just the way we have ielr categories. The introduce lr(0) and lalr, just the way we have ielr categories. The
"closure" function is too verbose, it should probably have its own category. "closure" function is too verbose, it should probably have its own category.
"set" can still be used for summariring the important sets. That would make "set" can still be used for summarizing the important sets. That would make
tests easy to maintain. tests easy to maintain.
*** complain.* *** complain.*
Rename these guys as "diagnostics.*" (or "diagnose.*"), since that's the Rename these guys as "diagnostics.*" (or "diagnose.*"), since that's the
name they have in gcc, clang, etc. Likewise for the complain_* series of name they have in GCC, clang, etc. Likewise for the complain_* series of
functions. functions.
*** ritem *** ritem
states/nstates, rules/nrules, ..., ritem/nritems states/nstates, rules/nrules, ..., ritem/nritems
Fix the latter. Fix the latter.
* D programming language
There's a number of features that are missing, here sorted in _suggested_
order of implementation.
When copying code from other skeletons, keep the comments exactly as they
are. Keep the same variable names. If you change the wording in one place,
do it in the others too. In other words: make sure to keep the
maintenance *simple* by avoiding any gratuitous difference.
** Rename the D example
Move the current content of examples/d into examples/d/simple.
** Create a second example
Duplicate examples/d/simple into examples/d/calc.
** Add location tracking to d/calc
Look at the examples in the other languages to see how to do that.
** yysymbol_name
The SymbolKind is an enum. For a given SymbolKind we want to get its string
representation. Currently it's a separate table in the parser that does
that:
/* Symbol kinds. */
public enum SymbolKind
{
S_YYEMPTY = -2, /* No symbol. */
S_YYEOF = 0, /* "end of file" */
S_YYerror = 1, /* error */
S_YYUNDEF = 2, /* "invalid token" */
S_EQ = 3, /* "=" */
...
S_input = 14, /* input */
S_line = 15, /* line */
S_exp = 16, /* exp */
};
...
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at \a yyntokens_, nonterminals. */
private static immutable string[] yytname_ =
[
"\"end of file\"", "error", "\"invalid token\"", "\"=\"", "\"+\"",
"\"-\"", "\"*\"", "\"/\"", "\"(\"", "\")\"", "\"end of line\"",
"\"number\"", "UNARY", "$accept", "input", "line", "exp", null
];
...
So to get a symbol kind, one runs `yytname_[yykind]`.
Is there a way to attach this conversion to string to SymbolKind? In Java
for instance, we have:
public enum SymbolKind
{
S_YYEOF(0), /* "end of file" */
S_YYerror(1), /* error */
S_YYUNDEF(2), /* "invalid token" */
...
S_input(16), /* input */
S_line(17), /* line */
S_exp(18); /* exp */
private final int yycode_;
SymbolKind (int n) {
this.yycode_ = n;
}
...
/* YYNAMES_[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at \a YYNTOKENS_, nonterminals. */
private static final String[] yynames_ = yynames_init();
private static final String[] yynames_init()
{
return new String[]
{
i18n("end of file"), i18n("error"), i18n("invalid token"), "!", "+", "-", "*",
"/", "^", "(", ")", "=", i18n("end of line"), i18n("number"), "NEG",
"$accept", "input", "line", "exp", null
};
}
/* The user-facing name of this symbol. */
public final String getName() {
return yynames_[yycode_];
}
};
which allows to write more naturally `yykind.getName()` rather than
`yytname_[yykind]`. Is there something comparable in (idiomatic) D?
** Change the return value of yylex
Historically people were allowed to return any int from the scanner (which
is convenient and allows `return '+'` from the scanner). Akim tends to see
this as an error, we should restrict the return values to TokenKind (not to
be confused with SymbolKind).
In the case of D, without the history, we have the choice to support or not
`int`. If we want to _keep_ `int`, is there a way, say via introspection,
to support both signatures of yylex? If we don't keep `int`, just move to
TokenKind.
** Documentation
Write documentation about D support in doc/bison.texi. Imitate the Java
documentation. You should be more succinct IMHO.
** Complete Symbols
The current interface from the scanner to the parser is somewhat clumsy: the
token kind is returned by yylex, but the value and location are stored in
the scanner. This reflects the fact that the implementation of the parser
uses three variables to deal with each parsed symbol: its kind, its value,
its location.
So today the scanner of examples/d/calc.d (no locations) looks like:
if (input.front.isNumber)
{
import std.conv : parse;
semanticVal_.ival = input.parse!int;
return TokenKind.NUM;
}
and the generated parser:
/* Read a lookahead token. */
if (yychar == TokenKind.YYEMPTY)
{
yychar = yylex ();
yylval = yylexer.semanticVal;
}
The parser class should feature a `Symbol` type which binds together kind,
value and location, and the scanner should be able to return an instance of
that type. Something like
if (input.front.isNumber)
{
import std.conv : parse;
return parser.Symbol (TokenKind.NUM, input.parse!int);
}
** Token Constructors
In the previous example it is possible to mix incorrectly kinds and values,
and for instance:
return parser.Symbol (TokenKind.NUM, "Hello, World!\n");
attaches a string value to NUM kind (wrong, of course). When
api.token.constructor is set, in C++, Bison generated "token constructors":
parser.make_NUM. parser.make_PLUS, parser.make_STRING, etc. The previous
example becomes
return parser.make_NUM ("Hello, World!\n");
which would easily be caught by the type checker.
** Lookahead Correction
Add support for LAC to the D skeleton. It should not be too hard: look how
this is done in lalr1.cc, and mock it.
** Push Parser
Add support for push parser. Do not start a nice skeleton, just enhance the
current one to support push parsers. This is going to be a tougher nut to
crack.
First, you need to understand well how the push parser is expected to work.
To this end:
- read the doc
- look at examples/c/pushcalc
- create an example of a Java push parser.
- have a look at the generated parser in Java, which has the advantage of
being already based on a parser object, instead of just a function.
The C case is harder to read, but it may help too. Keep in mind that
because there's no object to maintain state, the C push parser uses some
struct (yypstate) to preserve this state. We don't need this in D, the
parser object will suffice.
I think working directly on the skeleton to add push-parser support is not
the simplest path. I suggest that you (1) transform a generated parser into
a push parser by hand, and then (2) transform lalr1.d to generate such a
parser.
Use `git commit` frequently to make sure you keep track of your progress.
*** (1.a) Prepare pull parser by hand
Copy again one of the D examples into say examples/d/pushcalc. Also
check-in the generated parser to facilitate experimentation.
- find local variables of yyparse should become members of the parser object
(so that we preserve state from one call to the next).
- do it in your generated D parser. We don't need an equivalent for
yypstate, because we already have it: that the parser object itself.
- have your *pull*-parser (i.e., the good old yy::parser::parse()) work
properly this way. Write and run tests. That's one of the reasons I
suggest using examples/d/calc as a starting point: it already has tests,
you can/should add more.
At this point you have a pull-parser which you prepared to turn into a
push-parser.
*** (1.b) Turn pull parser into push parser by hand
- look again at how push parsers are implemented in Java/C to see what needs
to change in yyparse so that the control is inverted: parse() will
be *given* the tokens, instead of having to call yylex itself. When I say
"look at C", I think your best option are (i) yacc.c (look for b4_push_if)
and (ii) examples/c/pushcalc.
- rename parse() as push_parse(Symbol yyla) (or push_parse(TokenKind, Value,
Location)) that takes the symbol as argument. That's the push parser we
are looking for.
- define a new parse() function which has the same signature as the usual
pull-parser, that repeatedly calls the push_parse function. Something
like this:
int parse ()
{
int status = 0;
do {
status = this->push_parse (yylex());
} while (status == YYPUSH_MORE);
return status;
}
- show me that parser, so that we can validate the approach.
*** (2) Port that into the skeleton
- once we agree on the API of the push parser, implement it into lalr1.d.
You will probaby need help on this regard, but imitation, again, should
help.
- have example/d/pushcalc work properly and pass tests
- add tests in the "real" test suite. Do that in tests/calc.at. I can
help.
- document
** GLR Parser
This is very ambitious. That's the final boss. There are currently no
"clean" implementation to get inspiration from.
glr.c is very clean but:
- is low-level C
- is a different skeleton from yacc.c
glr.cc is (currently) an ugly hack: a C++ shell around glr.c. Valentin
Tolmer is currently rewriting glr.cc to be clean C++, but he is not
finished. There will be a lot a common code between lalr1.cc and glr.cc, so
eventually I would like them to be fused into a single skeleton, supporting
both deterministic and generalized parsing.
It would be great for D to also support this.
The basic ideas of GLR are explained here:
https://www.codeproject.com/Articles/5259825/GLR-Parsing-in-Csharp-How-to-Use-The-Most-Powerful
* Better error messages * Better error messages
The users are not provided with enough tools to forge their error messages. The users are not provided with enough tools to forge their error messages.
See for instance "Is there an option to change the message produced by See for instance "Is there an option to change the message produced by
@@ -231,7 +488,7 @@ and older C++ compilers. Currently the code defaults to defining it to
define it to the same type as the C ptrdiff_t type. define it to the same type as the C ptrdiff_t type.
* Completion * Completion
Several features are not available in all the backends. Several features are not available in all the back-ends.
- lac: D, Java (easy) - lac: D, Java (easy)
- push parsers: glr.c, glr.cc, lalr1.cc (not very difficult) - push parsers: glr.c, glr.cc, lalr1.cc (not very difficult)
@@ -301,7 +558,7 @@ opposite side we have some use of \l, which is graphviz-specific, in what
should be generic code. should be generic code.
Little effort seems to have been given to factoring these files and their Little effort seems to have been given to factoring these files and their
rint{,-xml} counterpart. We would very much like to re-use the pretty format print{,-xml} counterpart. We would very much like to re-use the pretty format
of states from .output for the graphs, etc. of states from .output for the graphs, etc.
Since graphviz dies on medium-to-big grammars, maybe consider an other tool? Since graphviz dies on medium-to-big grammars, maybe consider an other tool?
@@ -579,14 +836,39 @@ to bison. If you're interested, I'll work on a patch.
Equip the parser with a means to create the (visual) parse tree. Equip the parser with a means to create the (visual) parse tree.
-----
# LocalWords: Cex gnulib gl Bistromathic TokenKinds yylex enum YYEOF EOF
# LocalWords: YYerror gettext af hb YYERRCODE undef calc FIXME dev yyerror
# LocalWords: Autoconf YYUNDEFTOK lexemes parsers Bistromathic's yyreport
# LocalWords: const argc yacc yyclearin lookahead destructor Rici incluent
# LocalWords: yydestruct yydiscardin catégories d'avertissements sr activé
# LocalWords: conflits défaut rr l'alias chaîne n'est attaché un symbole
# LocalWords: obsolète règle vide midrule valeurs de intermédiaire ou avec
# LocalWords: définies inutilisées priorité associativité inutiles POSIX
# LocalWords: incompatibilités tous les autres avertissements sauf dans rp
# LocalWords: désactiver CATEGORIE traiter comme des erreurs glr Akim bool
# LocalWords: Demaille arith lalr goto struct pathlen nullable ntokens lr
# LocalWords: nterm bitsetv ielr ritem nstates nrules nritems yysymbol EQ
# LocalWords: SymbolKind YYEMPTY YYUNDEF YYTNAME NUM yyntokens yytname sed
# LocalWords: nonterminals yykind yycode YYNAMES yynames init getName conv
# LocalWords: TokenKind semanticVal ival yychar yylval yylexer Tolmer hoc
# LocalWords: Sobisch YYPTRDIFF ptrdiff Autotest YYPRINT toknum yytoknum
# LocalWords: sym Wother stderr FP fixits xgettext fdiagnostics Graphviz
# LocalWords: graphviz VCG bitset xml bw maint yytoken YYABORT deps
# LocalWords: YYACCEPT yytranslate nonnegative destructors yyerrlab repo
# LocalWords: backends stmt expr yy Mardle baz qux Vadim Maslow CPP cpp
# LocalWords: yydebug gcc UCHAR EBCDIC gung PDP NUL Pre Florian Krohm utf
# LocalWords: YYACT YYLLOC YYLSP yyval yyvsp yylen yyloc yylsp endif
# LocalWords: ispell american
Local Variables: Local Variables:
mode: outline mode: outline
coding: utf-8 coding: utf-8
fill-column: 76 fill-column: 76
ispell-dictionary: "american"
End: End:
-----
Copyright (C) 2001-2004, 2006, 2008-2015, 2018-2020 Free Software Copyright (C) 2001-2004, 2006, 2008-2015, 2018-2020 Free Software
Foundation, Inc. Foundation, Inc.
+2
View File
@@ -45,6 +45,8 @@ gnulib_modules='
relocatable-prog relocatable-script relocatable-prog relocatable-script
rename rename
spawn-pipe stdbool stpcpy stpncpy strdup-posix strerror strverscmp spawn-pipe stdbool stpcpy stpncpy strdup-posix strerror strverscmp
sys_ioctl
termios
timevar timevar
unicodeio unistd unistd-safer unlink unlocked-io unicodeio unistd unistd-safer unlink unlocked-io
update-copyright unsetenv verify update-copyright unsetenv verify
+3
View File
@@ -60,6 +60,9 @@ AC_PROG_CXX
# Gnulib (early checks). # Gnulib (early checks).
gl_EARLY gl_EARLY
# We want ostream_printf and hyperlink support.
gl_LIBTEXTSTYLE_OPTIONAL([0.20.5])
# Gnulib uses '#pragma GCC diagnostic push' to silence some # Gnulib uses '#pragma GCC diagnostic push' to silence some
# warnings, but older gcc doesn't support this. # warnings, but older gcc doesn't support this.
AC_CACHE_CHECK([whether pragma GCC diagnostic push works], AC_CACHE_CHECK([whether pragma GCC diagnostic push works],
+101 -78
View File
@@ -57,44 +57,57 @@
\gdef\colorPurple{% \gdef\colorPurple{%
\setcolor{\rgbPurple}% \setcolor{\rgbPurple}%
} }
\gdef\colorOff{%
\setcolor{\maincolor}%
}
\gdef\rgbError{0.80 0 0} \gdef\rgbError{0.80 0 0}
\gdef\colorError{% \gdef\diagError{%
\setcolor{\rgbError}% \setcolor{\rgbError}%
} }
\gdef\rgbNotice{0 0 0.80} \gdef\rgbNotice{0 0 0.80}
\gdef\colorNotice{% \gdef\diagNotice{%
\setcolor{\rgbNotice}% \setcolor{\rgbNotice}%
} }
\gdef\colorOff{% \gdef\rgbWarning{0.50 0 0.50}
\gdef\diagWarning{%
\setcolor{\rgbWarning}%
}
\gdef\diagOff{%
\setcolor{\maincolor}% \setcolor{\maincolor}%
} }
@end tex @end tex
@ifnottex @ifnottex
@macro colorGreen @macro colorGreen
@inlineraw{html, <b style="color:green">} @inlineraw{html, <span style="color:green">}
@end macro @end macro
@macro colorYellow @macro colorYellow
@inlineraw{html, <b style="color:#ff8000">} @inlineraw{html, <span style="color:#ff8000">}
@end macro @end macro
@macro colorRed @macro colorRed
@inlineraw{html, <b style="color:red">} @inlineraw{html, <span style="color:red">}
@end macro @end macro
@macro colorBlue @macro colorBlue
@inlineraw{html, <b style="color:blue">} @inlineraw{html, <span style="color:blue">}
@end macro @end macro
@macro colorPurple @macro colorPurple
@inlineraw{html, <b style="color:darkviolet">} @inlineraw{html, <span style="color:darkviolet">}
@end macro
@macro colorError
@inlineraw{html, <b style="color:red">}
@end macro
@macro colorNotice
@inlineraw{html, <b style="color:darkcyan">}
@end macro @end macro
@macro colorOff @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>} @inlineraw{html, </b>}
@end macro @end macro
@end ifnottex @end ifnottex
@@ -120,15 +133,15 @@
@end macro @end macro
@macro dwarning{text} @macro dwarning{text}
@purple{\text\} @diagWarning{}\text\@diagOff{}
@end macro @end macro
@macro derror{text} @macro derror{text}
@colorError{}\text\@colorOff{} @diagError{}\text\@diagOff{}
@end macro @end macro
@macro dnotice{text} @macro dnotice{text}
@colorNotice{}\text\@colorOff{} @diagNotice{}\text\@diagOff{}
@end macro @end macro
@finalout @finalout
@@ -8302,7 +8315,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 This particular ambiguity was first encountered in the specifications of
Algol 60 and is called the ``dangling @code{else}'' ambiguity. 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. conflicts, you can use the @code{%expect @var{n}} declaration.
There will be no warning as long as the number of shift/reduce conflicts 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 is exactly @var{n}, and Bison will report an error if there is a
@@ -8693,7 +8752,8 @@ maybeword:
@end example @end example
@noindent @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{word} into a @code{sequence}. It could be reduced to a
@code{maybeword} and then into a @code{sequence} via the second rule. @code{maybeword} and then into a @code{sequence} via the second rule.
Alternatively, nothing-at-all could be reduced into a @code{sequence} Alternatively, nothing-at-all could be reduced into a @code{sequence}
@@ -8890,12 +8950,14 @@ name_list:
It would seem that this grammar can be parsed with only a single token of 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 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{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 LR
@cindex LALR @cindex LALR
However, for historical reasons, Bison cannot by default handle all This is because Bison does not handle all LR(1) grammars @emph{by default},
LR(1) grammars. for historical reasons.
In this grammar, two contexts, that after an @code{"id"} at the beginning 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 of a @code{param_spec} and likewise at the beginning of a
@code{return_spec}, are similar enough that Bison assumes they are the @code{return_spec}, are similar enough that Bison assumes they are the
@@ -9870,6 +9932,9 @@ and understand the parser run-time traces (@pxref{Tracing}).
@node Counterexamples @node Counterexamples
@section Generation of 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 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 parser, as demonstrated by the number of sections devoted to them in this
@@ -9886,8 +9951,8 @@ That task is made much easier thanks to the generation of counterexamples,
initially developed by Chinawat Isradisaikul and Andrew Myers initially developed by Chinawat Isradisaikul and Andrew Myers
@pcite{Isradisaikul 2015}. @pcite{Isradisaikul 2015}.
As a first example, see the example grammar of @ref{Shift/Reduce}, which As a first example, see the grammar of @ref{Shift/Reduce}, which features
features on shift/reduce conflict: one shift/reduce conflict:
@c see doc/if-then-else.y @c see doc/if-then-else.y
@example @example
@@ -9901,49 +9966,14 @@ Let's rerun @command{bison} with the option
@option{-Wcex}/@option{-Wcounterexamples}@inlinefmt{info, (the following @option{-Wcex}/@option{-Wcounterexamples}@inlinefmt{info, (the following
output is actually in color)}: output is actually in color)}:
@ifnottex
@example @example
if-then-else.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}] 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}] if-then-else.y: @dwarning{warning}: shift/reduce conflict on token "else" [@dwarning{-Wcounterexamples}]
@group @danglingElseCex
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
@end example @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 This shows two different derivations for one single expression, which proves
demonstrates that the grammar is ambiguous. that the grammar is ambiguous.
@sp 1 @sp 1
@@ -9966,13 +9996,13 @@ maybeword:
Bison generates the following counterexamples: Bison generates the following counterexamples:
@ifnottex
@example @example
@group @group
$ @kbd{bison -Wcex sequence.y} $ @kbd{bison -Wcex sequence.y}
sequence.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}] sequence.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
sequence.y: @dwarning{warning}: 2 reduce/reduce conflicts [@dwarning{-Wconflicts-rr}] sequence.y: @dwarning{warning}: 2 reduce/reduce conflicts [@dwarning{-Wconflicts-rr}]
@end group @end group
@ifnottex
@group @group
sequence.y: @dwarning{warning}: shift/reduce conflict on token "word" [@dwarning{-Wcounterexamples}] sequence.y: @dwarning{warning}: shift/reduce conflict on token "word" [@dwarning{-Wcounterexamples}]
Example: @red{•} @green{"word"} Example: @red{•} @green{"word"}
@@ -10017,15 +10047,8 @@ sequence.y:8.3-45: @dwarning{warning}: rule useless in parser due to conflicts [
8 | @dwarning{%empty @{ printf ("empty maybeword\n"); @}} 8 | @dwarning{%empty @{ printf ("empty maybeword\n"); @}}
| @dwarning{^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~} | @dwarning{^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
@end group @end group
@end example
@end ifnottex @end ifnottex
@iftex @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 @group
sequence.y: @dwarning{warning}: shift/reduce conflict on token "word" [@dwarning{-Wcounterexamples}] sequence.y: @dwarning{warning}: shift/reduce conflict on token "word" [@dwarning{-Wcounterexamples}]
Example: @red{•} @green{"word"} Example: @red{•} @green{"word"}
@@ -10070,8 +10093,8 @@ sequence.y:8.3-45: @dwarning{warning}: rule useless in parser due to conflicts [
8 | @dwarning{%empty @{ printf ("empty maybeword\n"); @}} 8 | @dwarning{%empty @{ printf ("empty maybeword\n"); @}}
| @dwarning{^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~} | @dwarning{^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
@end group @end group
@end example
@end iftex @end iftex
@end example
Each of these three conflicts, again, prove that the grammar is ambiguous. Each of these three conflicts, again, prove that the grammar is ambiguous.
For instance, the second conflict (the reduce/reduce one) shows that the For instance, the second conflict (the reduce/reduce one) shows that the
@@ -10096,10 +10119,10 @@ expr: %empty | expr ID ','
@command{bison} reports: @command{bison} reports:
@ifnottex
@example @example
ids.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}] ids.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
ids.y: @dwarning{warning}: shift/reduce conflict on token ID [@dwarning{-Wcounterexamples}] ids.y: @dwarning{warning}: shift/reduce conflict on token ID [@dwarning{-Wcounterexamples}]
@ifnottex
@group @group
First example: @purple{expr} @red{•} @purple{ID ','} @green{ID} @yellow{$end} First example: @purple{expr} @red{•} @purple{ID ','} @green{ID} @yellow{$end}
Shift derivation Shift derivation
@@ -10120,12 +10143,8 @@ ids.y:4.4-7: @dwarning{warning}: rule useless in parser due to conflicts [@dwarn
4 | a: expr 4 | a: expr
| ^~~~ | ^~~~
@end group @end group
@end example
@end ifnottex @end ifnottex
@iftex @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 @group
First example: @purple{expr} @red{•} @purple{ID ','} @green{ID} @yellow{$end} First example: @purple{expr} @red{•} @purple{ID ','} @green{ID} @yellow{$end}
Shift derivation Shift derivation
@@ -10146,8 +10165,8 @@ ids.y:4.4-7: @dwarning{warning}: rule useless in parser due to conflicts [@dwarn
4 | a: expr 4 | a: expr
| ^~~~ | ^~~~
@end group @end group
@end example
@end iftex @end iftex
@end example
This conflict is caused by the parser not having enough information to know This conflict is caused by the parser not having enough information to know
the difference between these two examples. The parser would need an the difference between these two examples. The parser would need an
@@ -15631,6 +15650,10 @@ permitted. @xref{Language and Grammar}.
A sequence of tokens and/or nonterminals, with one dot, that demonstrates a A sequence of tokens and/or nonterminals, with one dot, that demonstrates a
conflict. The dot marks the place where the conflict occurs. 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 A @emph{unifying} counterexample is a single string that has two different
parses; its existence proves that the grammar is ambiguous. When a unifying parses; its existence proves that the grammar is ambiguous. When a unifying
counterexample cannot be found in reasonable time, a @emph{nonunifying} counterexample cannot be found in reasonable time, a @emph{nonunifying}
+1 -1
Submodule gnulib updated: ac34618e85...37b6f12946
+1 -2
View File
@@ -192,8 +192,6 @@
/localcharset.h /localcharset.h
/locale.h /locale.h
/locale.in.h /locale.in.h
/localtime-buffer.c
/localtime-buffer.h
/lstat.c /lstat.c
/malloc.c /malloc.c
/malloca.c /malloca.c
@@ -338,6 +336,7 @@
/sys_types.in.h /sys_types.in.h
/sys_wait.in.h /sys_wait.in.h
/sysexits.in.h /sysexits.in.h
/termios.in.h
/textstyle.h /textstyle.h
/textstyle.in.h /textstyle.in.h
/time.h /time.h
+3 -2
View File
@@ -67,7 +67,6 @@
/intlmacosx.m4 /intlmacosx.m4
/intmax.m4 /intmax.m4
/intmax_t.m4 /intmax_t.m4
/inttypes-pri.m4
/inttypes.m4 /inttypes.m4
/inttypes_h.m4 /inttypes_h.m4
/isnan.m4 /isnan.m4
@@ -97,7 +96,6 @@
/locale-ja.m4 /locale-ja.m4
/locale-zh.m4 /locale-zh.m4
/locale_h.m4 /locale_h.m4
/localtime-buffer.m4
/lock.m4 /lock.m4
/longlong.m4 /longlong.m4
/lstat.m4 /lstat.m4
@@ -117,6 +115,7 @@
/msvc-inval.m4 /msvc-inval.m4
/msvc-nothrow.m4 /msvc-nothrow.m4
/multiarch.m4 /multiarch.m4
/musl.m4
/nls.m4 /nls.m4
/nocrash.m4 /nocrash.m4
/non-recursive-gnulib-prefix-hack.m4 /non-recursive-gnulib-prefix-hack.m4
@@ -184,6 +183,7 @@
/strndup.m4 /strndup.m4
/strnlen.m4 /strnlen.m4
/strverscmp.m4 /strverscmp.m4
/sys_ioctl_h.m4
/sys_resource_h.m4 /sys_resource_h.m4
/sys_socket_h.m4 /sys_socket_h.m4
/sys_stat_h.m4 /sys_stat_h.m4
@@ -191,6 +191,7 @@
/sys_times_h.m4 /sys_times_h.m4
/sys_types_h.m4 /sys_types_h.m4
/sys_wait_h.m4 /sys_wait_h.m4
/termios_h.m4
/threadlib.m4 /threadlib.m4
/time_h.m4 /time_h.m4
/timespec.m4 /timespec.m4
+9 -14
View File
@@ -113,13 +113,8 @@ free_counterexample (counterexample *cex)
free (cex); free (cex);
} }
static int max (int a, int b)
{
return a < b ? b : a;
}
static void 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 bool flat = getenv ("YYFLAT");
const char *example1_label const char *example1_label
@@ -131,8 +126,8 @@ print_counterexample (const counterexample *cex, FILE *out, const char *prefix)
const char *deriv2_label const char *deriv2_label
= cex->shift_reduce ? _("Reduce derivation") : _("Second reduce derivation"); = cex->shift_reduce ? _("Reduce derivation") : _("Second reduce derivation");
const int width = const int width =
max (max (mbswidth (example1_label, 0), mbswidth (example2_label, 0)), max_int (max_int (mbswidth (example1_label, 0), mbswidth (example2_label, 0)),
max (mbswidth (deriv1_label, 0), mbswidth (deriv2_label, 0))); max_int (mbswidth (deriv1_label, 0), mbswidth (deriv2_label, 0)));
if (flat) if (flat)
fprintf (out, " %s%s%*s ", prefix, fprintf (out, " %s%s%*s ", prefix,
example1_label, width - mbswidth (example1_label, 0), ""); 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); for (gl_list_iterator_t it = gl_list_iterator (result);
state_item_list_next (&it, &sip); state_item_list_next (&it, &sip);
) )
print_state_item (sip, stderr, ""); state_item_print (sip, stderr, "");
} }
return result; return result;
} }
@@ -1267,7 +1262,7 @@ counterexample_report (state_item_number itm1, state_item_number itm2,
: example_from_path (shift_reduce, itm2, shortest_path, next_sym); : example_from_path (shift_reduce, itm2, shortest_path, next_sym);
gl_list_free (shortest_path); gl_list_free (shortest_path);
print_counterexample (cex, out, prefix); counterexample_print (cex, out, prefix);
free_counterexample (cex); free_counterexample (cex);
} }
@@ -1290,8 +1285,8 @@ counterexample_report_shift_reduce (state_item_number itm1, state_item_number it
// In the report, print the items. // In the report, print the items.
if (out != stderr || trace_flag & trace_cex) if (out != stderr || trace_flag & trace_cex)
{ {
print_state_item (&state_items[itm1], out, prefix); state_item_print (&state_items[itm1], out, prefix);
print_state_item (&state_items[itm2], out, prefix); state_item_print (&state_items[itm2], out, prefix);
} }
counterexample_report (itm1, itm2, next_sym, true, 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. // In the report, print the items.
if (out != stderr || trace_flag & trace_cex) if (out != stderr || trace_flag & trace_cex)
{ {
print_state_item (&state_items[itm1], out, prefix); state_item_print (&state_items[itm1], out, prefix);
print_state_item (&state_items[itm2], out, prefix); state_item_print (&state_items[itm2], out, prefix);
} }
counterexample_report (itm1, itm2, bitset_first (conflict_syms), counterexample_report (itm1, itm2, bitset_first (conflict_syms),
false, out, prefix); false, out, prefix);
+8 -14
View File
@@ -76,12 +76,12 @@ void derivation_list_free (derivation_list dl)
derivation * derivation *
derivation_new (symbol_number sym, derivation_list children) derivation_new (symbol_number sym, derivation_list children)
{ {
derivation *deriv = xmalloc (sizeof (derivation)); derivation *res = xmalloc (sizeof *res);
deriv->sym = sym; res->sym = sym;
deriv->children = children; res->children = children;
deriv->reference_count = 0; res->reference_count = 0;
deriv->color = -1; res->color = -1;
return deriv; return res;
} }
void 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. // Longest distance from root to leaf.
static int static int
derivation_depth (const derivation *deriv) 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); for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
derivation_list_next (&it, &child); derivation_list_next (&it, &child);
) )
res = max (res, derivation_depth (child)); res = max_int (res, derivation_depth (child));
return res + 1; return res + 1;
} }
else else
@@ -237,7 +231,7 @@ derivation_width (const derivation *deriv)
// No separator at the beginning. // No separator at the beginning.
children_width -= derivation_separator_width; children_width -= derivation_separator_width;
} }
return max (self_width, children_width); return max_int (self_width, children_width);
} }
else if (deriv == &d_dot) else if (deriv == &d_dot)
{ {
+9 -1
View File
@@ -112,7 +112,15 @@ static struct obstack obstack_for_string;
# define STRING_1GROW(Char) \ # define STRING_1GROW(Char) \
obstack_1grow (&obstack_for_string, Char) obstack_1grow (&obstack_for_string, Char)
# define STRING_FREE() \ # ifdef NDEBUG
# define STRING_FREE() \
obstack_free (&obstack_for_string, last_string) obstack_free (&obstack_for_string, last_string)
# else
# define STRING_FREE() \
do { \
obstack_free (&obstack_for_string, last_string); \
last_string = NULL; \
} while (0)
# endif
#endif #endif
+1 -1
View File
@@ -423,7 +423,7 @@ ielr_item_has_lookahead (state *s, symbol_number lhs, size_t item,
check all predecessors' goto follows for the LHS. */ check all predecessors' goto follows for the LHS. */
if (item_number_is_rule_number (ritem[s->items[item] - 2])) if (item_number_is_rule_number (ritem[s->items[item] - 2]))
{ {
aver (lhs != accept->content->number); aver (lhs != acceptsymbol->content->number);
for (state **predecessor = predecessors[s->number]; for (state **predecessor = predecessors[s->number];
*predecessor; *predecessor;
++predecessor) ++predecessor)
-12
View File
@@ -40,18 +40,6 @@
location const empty_loc = EMPTY_LOCATION_INIT; location const empty_loc = EMPTY_LOCATION_INIT;
static int
min_int (int a, int b)
{
return a < b ? a : b;
}
static int
max_int (int a, int b)
{
return a >= b ? a : b;
}
/* The terminal width. Not less than 40. */ /* The terminal width. Not less than 40. */
static int static int
columns (void) columns (void)
+1 -1
View File
@@ -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); gl_list_iterator_t it = gl_list_iterator (res);
const void *sip; const void *sip;
while (gl_list_iterator_next (&it, &sip, NULL)) while (gl_list_iterator_next (&it, &sip, NULL))
print_state_item ((state_item *) sip, stdout, ""); state_item_print ((state_item *) sip, stdout, "");
} }
return res; return res;
} }
+21 -21
View File
@@ -1,4 +1,4 @@
/* A Bison parser, made by GNU Bison 3.6.90. */ /* A Bison parser, made by GNU Bison 3.7.14-eb26-dirty. */
/* Bison implementation for Yacc-like parsers in C /* Bison implementation for Yacc-like parsers in C
@@ -49,7 +49,7 @@
#define YYBISON 1 #define YYBISON 1
/* Bison version. */ /* Bison version. */
#define YYBISON_VERSION "3.6.90" #define YYBISON_VERSION "3.7.14-eb26-dirty"
/* Skeleton name. */ /* Skeleton name. */
#define YYSKELETON_NAME "yacc.c" #define YYSKELETON_NAME "yacc.c"
@@ -149,7 +149,7 @@ enum yysymbol_kind_t
YYSYMBOL_BRACED_CODE = 41, /* "{...}" */ YYSYMBOL_BRACED_CODE = 41, /* "{...}" */
YYSYMBOL_BRACED_PREDICATE = 42, /* "%?{...}" */ YYSYMBOL_BRACED_PREDICATE = 42, /* "%?{...}" */
YYSYMBOL_BRACKETED_ID = 43, /* "[identifier]" */ YYSYMBOL_BRACKETED_ID = 43, /* "[identifier]" */
YYSYMBOL_CHAR = 44, /* "character literal" */ YYSYMBOL_CHAR_LITERAL = 44, /* "character literal" */
YYSYMBOL_COLON = 45, /* ":" */ YYSYMBOL_COLON = 45, /* ":" */
YYSYMBOL_EPILOGUE = 46, /* "epilogue" */ YYSYMBOL_EPILOGUE = 46, /* "epilogue" */
YYSYMBOL_EQUAL = 47, /* "=" */ YYSYMBOL_EQUAL = 47, /* "=" */
@@ -162,7 +162,7 @@ enum yysymbol_kind_t
YYSYMBOL_TAG = 54, /* "<tag>" */ YYSYMBOL_TAG = 54, /* "<tag>" */
YYSYMBOL_TAG_ANY = 55, /* "<*>" */ YYSYMBOL_TAG_ANY = 55, /* "<*>" */
YYSYMBOL_TAG_NONE = 56, /* "<>" */ YYSYMBOL_TAG_NONE = 56, /* "<>" */
YYSYMBOL_INT = 57, /* "integer literal" */ YYSYMBOL_INT_LITERAL = 57, /* "integer literal" */
YYSYMBOL_PERCENT_PARAM = 58, /* "%param" */ YYSYMBOL_PERCENT_PARAM = 58, /* "%param" */
YYSYMBOL_PERCENT_UNION = 59, /* "%union" */ YYSYMBOL_PERCENT_UNION = 59, /* "%union" */
YYSYMBOL_PERCENT_EMPTY = 60, /* "%empty" */ YYSYMBOL_PERCENT_EMPTY = 60, /* "%empty" */
@@ -1115,8 +1115,8 @@ tron (yyo);
{ fprintf (yyo, "[%s]", ((*yyvaluep).BRACKETED_ID)); } { fprintf (yyo, "[%s]", ((*yyvaluep).BRACKETED_ID)); }
break; break;
case YYSYMBOL_CHAR: /* "character literal" */ case YYSYMBOL_CHAR_LITERAL: /* "character literal" */
{ fputs (char_name (((*yyvaluep).CHAR)), yyo); } { fputs (char_name (((*yyvaluep).CHAR_LITERAL)), yyo); }
break; break;
case YYSYMBOL_EPILOGUE: /* "epilogue" */ case YYSYMBOL_EPILOGUE: /* "epilogue" */
@@ -1139,8 +1139,8 @@ tron (yyo);
{ fprintf (yyo, "<%s>", ((*yyvaluep).TAG)); } { fprintf (yyo, "<%s>", ((*yyvaluep).TAG)); }
break; break;
case YYSYMBOL_INT: /* "integer literal" */ case YYSYMBOL_INT_LITERAL: /* "integer literal" */
{ fprintf (yyo, "%d", ((*yyvaluep).INT)); } { fprintf (yyo, "%d", ((*yyvaluep).INT_LITERAL)); }
break; break;
case YYSYMBOL_PERCENT_PARAM: /* "%param" */ case YYSYMBOL_PERCENT_PARAM: /* "%param" */
@@ -2087,11 +2087,11 @@ yyreduce:
break; break;
case 12: /* prologue_declaration: "%expect" "integer literal" */ case 12: /* prologue_declaration: "%expect" "integer literal" */
{ expected_sr_conflicts = (yyvsp[0].INT); } { expected_sr_conflicts = (yyvsp[0].INT_LITERAL); }
break; break;
case 13: /* prologue_declaration: "%expect-rr" "integer literal" */ case 13: /* prologue_declaration: "%expect-rr" "integer literal" */
{ expected_rr_conflicts = (yyvsp[0].INT); } { expected_rr_conflicts = (yyvsp[0].INT_LITERAL); }
break; break;
case 14: /* prologue_declaration: "%file-prefix" "string" */ case 14: /* prologue_declaration: "%file-prefix" "string" */
@@ -2339,13 +2339,13 @@ yyreduce:
case 67: /* token_decls: "<tag>" token_decl.1 */ case 67: /* token_decls: "<tag>" token_decl.1 */
{ {
(yyval.token_decls) = symbol_list_type_set ((yyvsp[0].yykind_80), (yyvsp[-1].TAG), (yylsp[-1])); (yyval.token_decls) = symbol_list_type_set ((yyvsp[0].yykind_80), (yyvsp[-1].TAG));
} }
break; break;
case 68: /* token_decls: token_decls "<tag>" token_decl.1 */ case 68: /* token_decls: token_decls "<tag>" token_decl.1 */
{ {
(yyval.token_decls) = symbol_list_append ((yyvsp[-2].token_decls), symbol_list_type_set ((yyvsp[0].yykind_80), (yyvsp[-1].TAG), (yylsp[-1]))); (yyval.token_decls) = symbol_list_append ((yyvsp[-2].token_decls), symbol_list_type_set ((yyvsp[0].yykind_80), (yyvsp[-1].TAG)));
} }
break; break;
@@ -2396,13 +2396,13 @@ yyreduce:
case 78: /* token_decls_for_prec: "<tag>" token_decl_for_prec.1 */ case 78: /* token_decls_for_prec: "<tag>" token_decl_for_prec.1 */
{ {
(yyval.token_decls_for_prec) = symbol_list_type_set ((yyvsp[0].yykind_85), (yyvsp[-1].TAG), (yylsp[-1])); (yyval.token_decls_for_prec) = symbol_list_type_set ((yyvsp[0].yykind_85), (yyvsp[-1].TAG));
} }
break; break;
case 79: /* token_decls_for_prec: token_decls_for_prec "<tag>" token_decl_for_prec.1 */ case 79: /* token_decls_for_prec: token_decls_for_prec "<tag>" token_decl_for_prec.1 */
{ {
(yyval.token_decls_for_prec) = symbol_list_append ((yyvsp[-2].token_decls_for_prec), symbol_list_type_set ((yyvsp[0].yykind_85), (yyvsp[-1].TAG), (yylsp[-1]))); (yyval.token_decls_for_prec) = symbol_list_append ((yyvsp[-2].token_decls_for_prec), symbol_list_type_set ((yyvsp[0].yykind_85), (yyvsp[-1].TAG)));
} }
break; break;
@@ -2431,13 +2431,13 @@ yyreduce:
case 85: /* symbol_decls: "<tag>" symbol_decl.1 */ case 85: /* symbol_decls: "<tag>" symbol_decl.1 */
{ {
(yyval.symbol_decls) = symbol_list_type_set ((yyvsp[0].yykind_88), (yyvsp[-1].TAG), (yylsp[-1])); (yyval.symbol_decls) = symbol_list_type_set ((yyvsp[0].yykind_88), (yyvsp[-1].TAG));
} }
break; break;
case 86: /* symbol_decls: symbol_decls "<tag>" symbol_decl.1 */ case 86: /* symbol_decls: symbol_decls "<tag>" symbol_decl.1 */
{ {
(yyval.symbol_decls) = symbol_list_append ((yyvsp[-2].symbol_decls), symbol_list_type_set ((yyvsp[0].yykind_88), (yyvsp[-1].TAG), (yylsp[-1]))); (yyval.symbol_decls) = symbol_list_append ((yyvsp[-2].symbol_decls), symbol_list_type_set ((yyvsp[0].yykind_88), (yyvsp[-1].TAG)));
} }
break; break;
@@ -2506,7 +2506,7 @@ yyreduce:
break; break;
case 105: /* rhs: rhs "%dprec" "integer literal" */ case 105: /* rhs: rhs "%dprec" "integer literal" */
{ grammar_current_rule_dprec_set ((yyvsp[0].INT), (yylsp[0])); } { grammar_current_rule_dprec_set ((yyvsp[0].INT_LITERAL), (yylsp[0])); }
break; break;
case 106: /* rhs: rhs "%merge" "<tag>" */ case 106: /* rhs: rhs "%merge" "<tag>" */
@@ -2514,11 +2514,11 @@ yyreduce:
break; break;
case 107: /* rhs: rhs "%expect" "integer literal" */ case 107: /* rhs: rhs "%expect" "integer literal" */
{ grammar_current_rule_expect_sr ((yyvsp[0].INT), (yylsp[0])); } { grammar_current_rule_expect_sr ((yyvsp[0].INT_LITERAL), (yylsp[0])); }
break; break;
case 108: /* rhs: rhs "%expect-rr" "integer literal" */ case 108: /* rhs: rhs "%expect-rr" "integer literal" */
{ grammar_current_rule_expect_rr ((yyvsp[0].INT), (yylsp[0])); } { grammar_current_rule_expect_rr ((yyvsp[0].INT_LITERAL), (yylsp[0])); }
break; break;
case 109: /* named_ref.opt: %empty */ case 109: /* named_ref.opt: %empty */
@@ -2566,9 +2566,9 @@ yyreduce:
location loc = muscle_percent_define_get_loc (var); location loc = muscle_percent_define_get_loc (var);
subcomplain (&loc, complaint, _("definition of %s"), var); subcomplain (&loc, complaint, _("definition of %s"), var);
} }
(yyval.id) = symbol_get (char_name ((yyvsp[0].CHAR)), (yylsp[0])); (yyval.id) = symbol_get (char_name ((yyvsp[0].CHAR_LITERAL)), (yylsp[0]));
symbol_class_set ((yyval.id), token_sym, (yylsp[0]), false); symbol_class_set ((yyval.id), token_sym, (yylsp[0]), false);
symbol_code_set ((yyval.id), (yyvsp[0].CHAR), (yylsp[0])); symbol_code_set ((yyval.id), (yyvsp[0].CHAR_LITERAL), (yylsp[0]));
} }
break; break;
+5 -5
View File
@@ -1,4 +1,4 @@
/* A Bison parser, made by GNU Bison 3.6.90. */ /* A Bison parser, made by GNU Bison 3.7.14-eb26-dirty. */
/* Bison interface for Yacc-like parsers in C /* Bison interface for Yacc-like parsers in C
@@ -123,7 +123,7 @@ extern int gram_debug;
BRACED_CODE = 41, /* "{...}" */ BRACED_CODE = 41, /* "{...}" */
BRACED_PREDICATE = 42, /* "%?{...}" */ BRACED_PREDICATE = 42, /* "%?{...}" */
BRACKETED_ID = 43, /* "[identifier]" */ BRACKETED_ID = 43, /* "[identifier]" */
CHAR = 44, /* "character literal" */ CHAR_LITERAL = 44, /* "character literal" */
COLON = 45, /* ":" */ COLON = 45, /* ":" */
EPILOGUE = 46, /* "epilogue" */ EPILOGUE = 46, /* "epilogue" */
EQUAL = 47, /* "=" */ EQUAL = 47, /* "=" */
@@ -136,7 +136,7 @@ extern int gram_debug;
TAG = 54, /* "<tag>" */ TAG = 54, /* "<tag>" */
TAG_ANY = 55, /* "<*>" */ TAG_ANY = 55, /* "<*>" */
TAG_NONE = 56, /* "<>" */ TAG_NONE = 56, /* "<>" */
INT = 57, /* "integer literal" */ INT_LITERAL = 57, /* "integer literal" */
PERCENT_PARAM = 58, /* "%param" */ PERCENT_PARAM = 58, /* "%param" */
PERCENT_UNION = 59, /* "%union" */ PERCENT_UNION = 59, /* "%union" */
PERCENT_EMPTY = 60 /* "%empty" */ PERCENT_EMPTY = 60 /* "%empty" */
@@ -156,7 +156,7 @@ union GRAM_STYPE
char* EPILOGUE; /* "epilogue" */ char* EPILOGUE; /* "epilogue" */
char* PROLOGUE; /* "%{...%}" */ char* PROLOGUE; /* "%{...%}" */
code_props_type code_props_type; /* code_props_type */ code_props_type code_props_type; /* code_props_type */
int INT; /* "integer literal" */ int INT_LITERAL; /* "integer literal" */
int yykind_82; /* int.opt */ int yykind_82; /* int.opt */
named_ref* yykind_95; /* named_ref.opt */ named_ref* yykind_95; /* named_ref.opt */
param_type PERCENT_PARAM; /* "%param" */ param_type PERCENT_PARAM; /* "%param" */
@@ -188,7 +188,7 @@ union GRAM_STYPE
uniqstr yykind_74; /* tag.opt */ uniqstr yykind_74; /* tag.opt */
uniqstr tag; /* tag */ uniqstr tag; /* tag */
uniqstr variable; /* variable */ uniqstr variable; /* variable */
unsigned char CHAR; /* "character literal" */ unsigned char CHAR_LITERAL; /* "character literal" */
value_type value; /* value */ value_type value; /* value */
+16 -16
View File
@@ -214,7 +214,7 @@
BRACED_CODE "{...}" BRACED_CODE "{...}"
BRACED_PREDICATE "%?{...}" BRACED_PREDICATE "%?{...}"
BRACKETED_ID _("[identifier]") BRACKETED_ID _("[identifier]")
CHAR _("character literal") CHAR_LITERAL _("character literal")
COLON ":" COLON ":"
EPILOGUE _("epilogue") EPILOGUE _("epilogue")
EQUAL "=" EQUAL "="
@@ -232,7 +232,7 @@
%code pre-printer {tron (yyo);} %code pre-printer {tron (yyo);}
%code post-printer {troff (yyo);} %code post-printer {troff (yyo);}
%type <unsigned char> CHAR %type <unsigned char> CHAR_LITERAL
%printer { fputs (char_name ($$), yyo); } <unsigned char> %printer { fputs (char_name ($$), yyo); } <unsigned char>
%type <char*> "{...}" "%?{...}" "%{...%}" EPILOGUE STRING TSTRING %type <char*> "{...}" "%?{...}" "%{...%}" EPILOGUE STRING TSTRING
@@ -249,7 +249,7 @@
%printer { fprintf (yyo, "%%%s", $$); } PERCENT_FLAG %printer { fprintf (yyo, "%%%s", $$); } PERCENT_FLAG
%printer { fprintf (yyo, "<%s>", $$); } TAG tag %printer { fprintf (yyo, "<%s>", $$); } TAG tag
%token <int> INT _("integer literal") %token <int> INT_LITERAL _("integer literal")
%printer { fprintf (yyo, "%d", $$); } <int> %printer { fprintf (yyo, "%d", $$); } <int>
%type <symbol*> id id_colon string_as_id symbol token_decl token_decl_for_prec %type <symbol*> id id_colon string_as_id symbol token_decl token_decl_for_prec
@@ -342,8 +342,8 @@ prologue_declaration:
| "%defines" { defines_flag = true; } | "%defines" { defines_flag = true; }
| "%defines" STRING { handle_defines ($2); } | "%defines" STRING { handle_defines ($2); }
| "%error-verbose" { handle_error_verbose (&@$, $1); } | "%error-verbose" { handle_error_verbose (&@$, $1); }
| "%expect" INT { expected_sr_conflicts = $2; } | "%expect" INT_LITERAL { expected_sr_conflicts = $2; }
| "%expect-rr" INT { expected_rr_conflicts = $2; } | "%expect-rr" INT_LITERAL { expected_rr_conflicts = $2; }
| "%file-prefix" STRING { handle_file_prefix (&@$, &@1, $1, $2); } | "%file-prefix" STRING { handle_file_prefix (&@$, &@1, $1, $2); }
| "%glr-parser" | "%glr-parser"
{ {
@@ -532,11 +532,11 @@ token_decls:
} }
| TAG token_decl.1[syms] | TAG token_decl.1[syms]
{ {
$$ = symbol_list_type_set ($syms, $TAG, @TAG); $$ = symbol_list_type_set ($syms, $TAG);
} }
| token_decls TAG token_decl.1[syms] | token_decls TAG token_decl.1[syms]
{ {
$$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG, @TAG)); $$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG));
} }
; ;
@@ -561,7 +561,7 @@ token_decl:
%type <int> int.opt; %type <int> int.opt;
int.opt: int.opt:
%empty { $$ = -1; } %empty { $$ = -1; }
| INT | INT_LITERAL
; ;
%type <symbol*> alias; %type <symbol*> alias;
@@ -592,11 +592,11 @@ token_decls_for_prec:
} }
| TAG token_decl_for_prec.1[syms] | TAG token_decl_for_prec.1[syms]
{ {
$$ = symbol_list_type_set ($syms, $TAG, @TAG); $$ = symbol_list_type_set ($syms, $TAG);
} }
| token_decls_for_prec TAG token_decl_for_prec.1[syms] | token_decls_for_prec TAG token_decl_for_prec.1[syms]
{ {
$$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG, @TAG)); $$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG));
} }
; ;
@@ -632,11 +632,11 @@ symbol_decls:
} }
| TAG symbol_decl.1[syms] | TAG symbol_decl.1[syms]
{ {
$$ = symbol_list_type_set ($syms, $TAG, @TAG); $$ = symbol_list_type_set ($syms, $TAG);
} }
| symbol_decls TAG symbol_decl.1[syms] | symbol_decls TAG symbol_decl.1[syms]
{ {
$$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG, @TAG)); $$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG));
} }
; ;
@@ -703,13 +703,13 @@ rhs:
{ grammar_current_rule_empty_set (@2); } { grammar_current_rule_empty_set (@2); }
| rhs "%prec" symbol | rhs "%prec" symbol
{ grammar_current_rule_prec_set ($3, @3); } { grammar_current_rule_prec_set ($3, @3); }
| rhs "%dprec" INT | rhs "%dprec" INT_LITERAL
{ grammar_current_rule_dprec_set ($3, @3); } { grammar_current_rule_dprec_set ($3, @3); }
| rhs "%merge" TAG | rhs "%merge" TAG
{ grammar_current_rule_merge_set ($3, @3); } { grammar_current_rule_merge_set ($3, @3); }
| rhs "%expect" INT | rhs "%expect" INT_LITERAL
{ grammar_current_rule_expect_sr ($3, @3); } { grammar_current_rule_expect_sr ($3, @3); }
| rhs "%expect-rr" INT | rhs "%expect-rr" INT_LITERAL
{ grammar_current_rule_expect_rr ($3, @3); } { grammar_current_rule_expect_rr ($3, @3); }
; ;
@@ -765,7 +765,7 @@ value:
id: id:
ID ID
{ $$ = symbol_from_uniqstr ($1, @1); } { $$ = symbol_from_uniqstr ($1, @1); }
| CHAR | CHAR_LITERAL
{ {
const char *var = "api.token.raw"; const char *var = "api.token.raw";
if (current_class == nterm_sym) if (current_class == nterm_sym)
+13 -17
View File
@@ -30,17 +30,17 @@
typedef struct parse_state typedef struct parse_state
{ {
// path of state-items the parser has traversed // Path of state-items the parser has traversed.
struct si_chunk struct si_chunk
{ {
// elements newly added in this chunk // Elements newly added in this chunk.
state_item_list contents; state_item_list contents;
// properties of the linked list this chunk represents // Properties of the linked list this chunk represents.
const state_item *head_elt; const state_item *head_elt;
const state_item *tail_elt; const state_item *tail_elt;
size_t total_size; size_t total_size;
} state_items; } state_items;
// list of derivations of the symbols // List of derivations of the symbols.
struct deriv_chunk struct deriv_chunk
{ {
derivation_list contents; derivation_list contents;
@@ -50,16 +50,13 @@ typedef struct parse_state
} derivs; } derivs;
struct parse_state *parent; struct parse_state *parent;
int reference_count; int reference_count;
// incremented during productions, // Incremented during productions, decremented during reductions.
// decremented during reductions
int depth; int depth;
// whether the contents of the chunks should be // Whether the contents of the chunks should be prepended or
// prepended or appended to the list the chunks // appended to the list the chunks represent.
// represent
bool prepend; bool prepend;
// causes chunk contents to be freed when the // Causes chunk contents to be freed when the reference count is
// reference count is one. Used when only the chunk metadata // one. Used when only the chunk metadata will be needed.
// will be needed.
bool free_contents_early; bool free_contents_early;
} parse_state; } parse_state;
@@ -438,9 +435,8 @@ simulate_transition (parse_state *ps)
// symbols into account. // symbols into account.
parse_state_list result = parse_state_list_new (); parse_state_list result = parse_state_list_new ();
state_item_number si_next = si->trans; state_item_number si_next = si->trans;
// check for disabled transition, shouldn't happen // Check for disabled transition, shouldn't happen as any
// as any state_items that lead to these should be // state_items that lead to these should be disabled.
// disabled.
if (si_next < 0) if (si_next < 0)
return result; return result;
parse_state *next_ps = copy_parse_state (false, ps); parse_state *next_ps = copy_parse_state (false, ps);
@@ -594,8 +590,8 @@ print_parse_state (parse_state *ps)
FILE *out = stderr; FILE *out = stderr;
fprintf (out, "(size %zu depth %d rc %d)\n", fprintf (out, "(size %zu depth %d rc %d)\n",
ps->state_items.total_size, ps->depth, ps->reference_count); ps->state_items.total_size, ps->depth, ps->reference_count);
print_state_item (ps->state_items.head_elt, out, ""); state_item_print (ps->state_items.head_elt, out, "");
print_state_item (ps->state_items.tail_elt, out, ""); state_item_print (ps->state_items.tail_elt, out, "");
if (ps->derivs.total_size > 0) if (ps->derivs.total_size > 0)
derivation_print (ps->derivs.head_elt, out, ""); derivation_print (ps->derivs.head_elt, out, "");
putc ('\n', out); putc ('\n', out);
+1 -1
View File
@@ -804,7 +804,7 @@ check_and_convert_grammar (void)
$accept: %start $end. */ $accept: %start $end. */
{ {
symbol_list *p = symbol_list_sym_new (accept, empty_loc); symbol_list *p = symbol_list_sym_new (acceptsymbol, empty_loc);
p->rhs_loc = grammar->rhs_loc; p->rhs_loc = grammar->rhs_loc;
p->next = symbol_list_sym_new (startsymbol, empty_loc); p->next = symbol_list_sym_new (startsymbol, empty_loc);
p->next->next = symbol_list_sym_new (eoftoken, empty_loc); p->next->next = symbol_list_sym_new (eoftoken, empty_loc);
+4 -4
View File
@@ -160,9 +160,9 @@ inaccessable_symbols (void)
bitset Pp = bitset_create (nrules, BITSET_FIXED); bitset Pp = bitset_create (nrules, BITSET_FIXED);
/* If the start symbol isn't useful, then nothing will be useful. */ /* If the start symbol isn't useful, then nothing will be useful. */
if (bitset_test (N, accept->content->number - ntokens)) if (bitset_test (N, acceptsymbol->content->number - ntokens))
{ {
bitset_set (V, accept->content->number); bitset_set (V, acceptsymbol->content->number);
while (1) while (1)
{ {
@@ -301,7 +301,7 @@ nonterminals_reduce (void)
for (item_number *rhsp = rules[r].rhs; 0 <= *rhsp; ++rhsp) for (item_number *rhsp = rules[r].rhs; 0 <= *rhsp; ++rhsp)
if (ISVAR (*rhsp)) if (ISVAR (*rhsp))
*rhsp = symbol_number_as_item_number (nterm_map[*rhsp - ntokens]); *rhsp = symbol_number_as_item_number (nterm_map[*rhsp - ntokens]);
accept->content->number = nterm_map[accept->content->number - ntokens]; acceptsymbol->content->number = nterm_map[acceptsymbol->content->number - ntokens];
} }
nsyms -= nuseless_nonterminals; nsyms -= nuseless_nonterminals;
@@ -381,7 +381,7 @@ reduce_grammar (void)
{ {
reduce_print (); reduce_print ();
if (!bitset_test (N, accept->content->number - ntokens)) if (!bitset_test (N, acceptsymbol->content->number - ntokens))
complain (&startsymbol_loc, fatal, complain (&startsymbol_loc, fatal,
_("start symbol %s does not derive any sentence"), _("start symbol %s does not derive any sentence"),
startsymbol->tag); startsymbol->tag);
+8 -7
View File
@@ -322,8 +322,8 @@ eqopt ({sp}=)?
BEGIN SC_AFTER_IDENTIFIER; BEGIN SC_AFTER_IDENTIFIER;
} }
{int} RETURN_VALUE (INT, scan_integer (yytext, 10, *loc)); {int} RETURN_VALUE (INT_LITERAL, scan_integer (yytext, 10, *loc));
{xint} RETURN_VALUE (INT, scan_integer (yytext, 16, *loc)); {xint} RETURN_VALUE (INT_LITERAL, scan_integer (yytext, 16, *loc));
/* Identifiers may not start with a digit. Yet, don't silently /* Identifiers may not start with a digit. Yet, don't silently
accept "1FOO" as "1 FOO". */ accept "1FOO" as "1 FOO". */
@@ -403,6 +403,7 @@ eqopt ({sp}=)?
{ {
\0 { \0 {
complain (loc, complaint, _("invalid null character")); complain (loc, complaint, _("invalid null character"));
STRING_FINISH ();
STRING_FREE (); STRING_FREE ();
return GRAM_error; return GRAM_error;
} }
@@ -599,7 +600,6 @@ eqopt ({sp}=)?
STRING_FINISH (); STRING_FINISH ();
BEGIN INITIAL; BEGIN INITIAL;
loc->start = token_start; loc->start = token_start;
val->CHAR = last_string[0];
if (last_string[0] == '\0') if (last_string[0] == '\0')
{ {
@@ -615,8 +615,9 @@ eqopt ({sp}=)?
} }
else else
{ {
val->CHAR_LITERAL = last_string[0];
STRING_FREE (); STRING_FREE ();
return CHAR; return CHAR_LITERAL;
} }
} }
{eol} unexpected_newline (token_start, "'"); {eol} unexpected_newline (token_start, "'");
@@ -933,9 +934,9 @@ convert_ucn_to_byte (char const *ucn)
} }
/*---------------------------------------------------------------------. /*----------------------------------------------------------------------------.
| Handle '#line INT( "FILE")?\n'. ARGS has already skipped '#line '. | | Handle '#line INT_LITERAL( "FILE")?\n'. ARGS has already skipped '#line '. |
`---------------------------------------------------------------------*/ `----------------------------------------------------------------------------*/
static void static void
handle_syncline (char *args, location loc) handle_syncline (char *args, location loc)
+3 -3
View File
@@ -475,7 +475,7 @@ prune_disabled_paths (void)
} }
void void
print_state_item (const state_item *si, FILE *out, const char *prefix) state_item_print (const state_item *si, FILE *out, const char *prefix)
{ {
fputs (prefix, out); fputs (prefix, out);
item_print (si->item, NULL, out); item_print (si->item, NULL, out);
@@ -506,7 +506,7 @@ state_items_report (void)
if (si->trans >= 0) if (si->trans >= 0)
{ {
fputs (" -> ", stdout); fputs (" -> ", stdout);
print_state_item (&state_items[si->trans], stdout, ""); state_item_print (&state_items[si->trans], stdout, "");
} }
bitset sets[2] = { si->prods, si->revs }; bitset sets[2] = { si->prods, si->revs };
@@ -521,7 +521,7 @@ state_items_report (void)
BITSET_FOR_EACH (biter, b, sin, 0) BITSET_FOR_EACH (biter, b, sin, 0)
{ {
fputs (txt[seti], stdout); fputs (txt[seti], stdout);
print_state_item (&state_items[sin], stdout, ""); state_item_print (&state_items[sin], stdout, "");
} }
} }
} }
+2 -1
View File
@@ -90,9 +90,10 @@ state_item_index_lookup (state_number s, state_item_number off)
} }
void state_items_init (void); void state_items_init (void);
void print_state_item (const state_item *si, FILE *out, const char *prefix);
void state_items_free (void); void state_items_free (void);
void state_item_print (const state_item *si, FILE *out, const char *prefix);
bool production_allowed (const state_item *si, const state_item *next); bool production_allowed (const state_item *si, const state_item *next);
// Iterating on a state_item_list. // Iterating on a state_item_list.
+2 -2
View File
@@ -83,10 +83,10 @@ symbol_list_type_new (uniqstr type_name, location loc)
symbol_list * symbol_list *
symbol_list_type_set (symbol_list *syms, uniqstr type_name, location loc) symbol_list_type_set (symbol_list *syms, uniqstr type_name)
{ {
for (symbol_list *l = syms; l; l = l->next) for (symbol_list *l = syms; l; l = l->next)
symbol_type_set (l->content.sym, type_name, loc); symbol_type_set (l->content.sym, type_name, l->sym_loc);
return syms; return syms;
} }
+1 -2
View File
@@ -110,8 +110,7 @@ symbol_list *symbol_list_type_new (uniqstr type_name, location loc);
/** Assign the type \c type_name to all the members of \c syms. /** Assign the type \c type_name to all the members of \c syms.
** \returns \c syms */ ** \returns \c syms */
symbol_list *symbol_list_type_set (symbol_list *syms, symbol_list *symbol_list_type_set (symbol_list *syms, uniqstr type_name);
uniqstr type_name, location loc);
/** Print this list. /** Print this list.
+5 -5
View File
@@ -59,7 +59,7 @@ static semantic_type **semantic_types_sorted = NULL;
symbol *errtoken = NULL; symbol *errtoken = NULL;
symbol *undeftoken = NULL; symbol *undeftoken = NULL;
symbol *eoftoken = NULL; symbol *eoftoken = NULL;
symbol *accept = NULL; symbol *acceptsymbol = NULL;
symbol *startsymbol = NULL; symbol *startsymbol = NULL;
location startsymbol_loc; location startsymbol_loc;
@@ -849,10 +849,10 @@ symbols_new (void)
hash_symbol_comparator, hash_symbol_comparator,
symbol_free); symbol_free);
/* Construct the accept symbol. */ /* Construct the acceptsymbol symbol. */
accept = symbol_get ("$accept", empty_loc); acceptsymbol = symbol_get ("$accept", empty_loc);
accept->content->class = nterm_sym; acceptsymbol->content->class = nterm_sym;
accept->content->number = nnterms++; acceptsymbol->content->number = nnterms++;
/* Construct the YYerror/"error" token */ /* Construct the YYerror/"error" token */
errtoken = symbol_get ("YYerror", empty_loc); errtoken = symbol_get ("YYerror", empty_loc);
+1 -1
View File
@@ -245,7 +245,7 @@ extern symbol *eoftoken;
/** The genuine start symbol. /** The genuine start symbol.
$accept: start-symbol $end */ $accept: start-symbol $end */
extern symbol *accept; extern symbol *acceptsymbol;
/** The user start symbol. */ /** The user start symbol. */
extern symbol *startsymbol; extern symbol *startsymbol;
+16
View File
@@ -131,6 +131,22 @@ typedef size_t uintptr_t;
# include <stdbool.h> # include <stdbool.h>
/*-----------.
| Integers. |
`-----------*/
static inline int
min_int (int a, int b)
{
return a < b ? a : b;
}
static inline int
max_int (int a, int b)
{
return a >= b ? a : b;
}
/*-------------. /*-------------.
| Assertions. | | Assertions. |
+42 -14
View File
@@ -1,4 +1,4 @@
# Checking the Bison scanner. -*- Autotest -*- # Checking the Bison reader. -*- Autotest -*-
# Copyright (C) 2002-2015, 2018-2020 Free Software Foundation, Inc. # Copyright (C) 2002-2015, 2018-2020 Free Software Foundation, Inc.
@@ -78,10 +78,13 @@ AT_CLEANUP
## Invalid inputs. ## ## Invalid inputs. ##
## ---------------- ## ## ---------------- ##
# The truly bad guys no human would write, but easily uncovered by
# fuzzers.
AT_SETUP([Invalid inputs]) AT_SETUP([Invalid inputs])
AT_DATA([input.y], AT_DATA([input.y],
[[\000\001\002\377? [[\000\001\002\377?
"\000"
%% %%
? ?
default: 'a' } default: 'a' }
@@ -92,16 +95,41 @@ default: 'a' }
]]) ]])
AT_PERL_REQUIRE([[-pi -e 's/\\(\d{3})/chr(oct($1))/ge' input.y]]) 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:1.1-2: error: invalid characters: '\0\001\002\377?'
input.y:3.1: error: invalid character: '?' 1 | \x00\xff?
input.y:4.14: error: invalid character: '}' | ^~
input.y:5.1: error: invalid character: '%' input.y:2.2: error: invalid null character
input.y:5.2: error: invalid character: '&' 2 | "\x00"
input.y:6.1-17: error: invalid directive: '%a-does-not-exist' | ^
input.y:7.1: error: invalid character: '%' input.y:4.1: error: invalid character: '?'
input.y:7.2: error: invalid character: '-' 4 | ?
input.y:8.1-9.0: error: missing '%}' at end of file | ^
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 AT_CLEANUP
@@ -1224,12 +1252,12 @@ AT_TEST([[%token foo "foo"
%% %%
exp: 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 3 | %type <baz> foo
| ^~~~~ | ^~~
input.y:2.7-11: note: previous declaration input.y:2.13-17: note: previous declaration
2 | %type <bar> "foo" 2 | %type <bar> "foo"
| ^~~~~ | ^~~~~
]]) ]])
AT_TEST([[%token foo "foo" AT_TEST([[%token foo "foo"