Compare commits

..
Author SHA1 Message Date
Theophile Ranquet fcf845a716 testsuite: introduce --release
* tests/atlocal.in, tests/local.at: Support option --release, which sets
BISON_USE_PUSH_FOR_PULL and BISON_TEST_XML.
* tests/local.mk: Use it for maintainer-release-check.
2013-01-31 17:48:52 +01:00
Theophile Ranquet 3158164614 build: run checks in distinct directories
* tests/local.mk (maintainer-release-check) Import this rule from maint. Run
maintainer-checks in separate directories.
* configure.ac (AC_CONFIG_TESTDIR), tests/local.at: Adjust paths.
2013-01-31 17:48:52 +01:00
100 changed files with 3720 additions and 7611 deletions
+1 -1
View File
@@ -1 +1 @@
3.0 2.7
+4 -4
View File
@@ -32,8 +32,8 @@ EXTRA_DIST = .prev-version .version \
## version of Bison nearby... ## version of Bison nearby...
BISON = $(top_builddir)/tests/bison BISON = $(top_builddir)/tests/bison
BISON_IN = $(top_srcdir)/tests/bison.in BISON_IN = $(top_srcdir)/tests/bison.in
YACC = $(BISON) -o y.tab.c YACC = $(BISON) -y
AM_YFLAGS = -d -v -Werror -Wall -Wno-yacc --report=all AM_YFLAGS = -d -v --warnings=all,error --report=all
# Initialization before completion by local.mk's. # Initialization before completion by local.mk's.
AM_CFLAGS = $(WARN_CFLAGS) AM_CFLAGS = $(WARN_CFLAGS)
@@ -78,11 +78,11 @@ dist-hook: gen-ChangeLog
.PHONY: update-b4-copyright update-package-copyright-year .PHONY: update-b4-copyright update-package-copyright-year
update-b4-copyright: update-b4-copyright:
$(AM_V_GEN)find $(srcdir)/data -type f \ find $(srcdir)/data -type f \
| xargs $(srcdir)/build-aux/$@ | xargs $(srcdir)/build-aux/$@
@echo 'warning: src/parse-gram.[hc] may need to be regenerated.' @echo 'warning: src/parse-gram.[hc] may need to be regenerated.'
update-package-copyright-year: update-package-copyright-year:
$(AM_V_GEN)$(srcdir)/build-aux/$@ $(srcdir)/configure.ac $(srcdir)/build-aux/$@ $(srcdir)/configure.ac
gen_start_date = 2012-01-16 gen_start_date = 2012-01-16
.PHONY: gen-ChangeLog .PHONY: gen-ChangeLog
+60 -397
View File
@@ -2,37 +2,16 @@ GNU Bison NEWS
* Noteworthy changes in release ?.? (????-??-??) [?] * Noteworthy changes in release ?.? (????-??-??) [?]
** New syntax: partial-order precedence relationships
Formerly, the precedence order of tokens was linear, depending only on the
order in which they were declared. With the new syntax, all the tokens are
not necessarily comparable. It is possible to declare a group of tokens with
no links outside of the group, and to later on add only those needed.
The uncomparability of tokens would allow for more feedback on new conflicts
silently resolved via precedence.
An example of the new syntax applied to arithmetic and boolean operators,
with '^' serving as both numerical power and boolean XOR:
%gprec arith {
%left '+' '-'
%left '*' '/'
}
%gprec bool {
%left OR
%left AND
}
%gprec { %right '^' }
%precr '^' > arith
%precr OR AND > '^'
Here, AND is not comparable with '+', but '^' > '+' and AND > '^'
* Noteworthy changes in release 3.0 (2013-07-25) [stable]
** WARNING: Future backward-incompatibilities! ** WARNING: Future backward-incompatibilities!
Bison will stop adding a semicolon at the end of the actions (as announced
in the release 2.5):
foo.y:2.22: warning: a ';' might be needed at the end of action code
exp: "num" { $$ = $1 }
^
foo.y:2.22: future versions of Bison will not add the ';'
Like other GNU packages, Bison will start using some of the C99 features Like other GNU packages, Bison will start using some of the C99 features
for its own code, especially the definition of variables after statements. for its own code, especially the definition of variables after statements.
The generated C parsers still aim at C90. The generated C parsers still aim at C90.
@@ -49,32 +28,9 @@ GNU Bison NEWS
Support for YYLEX_PARAM and YYPARSE_PARAM is removed (deprecated in Bison Support for YYLEX_PARAM and YYPARSE_PARAM is removed (deprecated in Bison
1.875): use %lex-param, %parse-param, or %param. 1.875): use %lex-param, %parse-param, or %param.
Missing semicolons at the end of actions are no longer added (as announced
in the release 2.5).
*** Use of YACC='bison -y'
TL;DR: With Autoconf <= 2.69, pass -Wno-yacc to (AM_)YFLAGS if you use
Bison extensions.
Traditional Yacc generates 'y.tab.c' whatever the name of the input file.
Therefore Makefiles written for Yacc expect 'y.tab.c' (and possibly
'y.tab.h' and 'y.outout') to be generated from 'foo.y'.
To this end, for ages, AC_PROG_YACC, Autoconf's macro to look for an
implementation of Yacc, was using Bison as 'bison -y'. While it does
ensure compatible output file names, it also enables warnings for
incompatibilities with POSIX Yacc. In other words, 'bison -y' triggers
warnings for Bison extensions.
Autoconf 2.70+ fixes this incompatibility by using YACC='bison -o y.tab.c'
(which also generates 'y.tab.h' and 'y.output' when needed).
Alternatively, disable Yacc warnings by passing '-Wno-yacc' to your Yacc
flags (YFLAGS, or AM_YFLAGS with Automake).
** Bug fixes ** Bug fixes
*** The epilogue is no longer affected by internal #defines (glr.c) *** The epilogue is no longer affected by internal #defines
The glr.c skeleton uses defines such as #define yylval (yystackp->yyval) in The glr.c skeleton uses defines such as #define yylval (yystackp->yyval) in
generated code. These weren't properly undefined before the inclusion of generated code. These weren't properly undefined before the inclusion of
@@ -83,7 +39,7 @@ GNU Bison NEWS
int yylex (YYSTYPE *yylval); int yylex (YYSTYPE *yylval);
This is fixed: yylval, yynerrs, yychar, and yylloc are now valid This is has been fixed: yylval, yynerrs, yychar, and yylloc are now valid
identifiers for user-provided variables. identifiers for user-provided variables.
*** stdio.h is no longer needed when locations are enabled (yacc.c) *** stdio.h is no longer needed when locations are enabled (yacc.c)
@@ -91,8 +47,6 @@ GNU Bison NEWS
Changes in Bison 2.7 introduced a dependency on FILE and fprintf when Changes in Bison 2.7 introduced a dependency on FILE and fprintf when
locations are enabled. This is fixed. locations are enabled. This is fixed.
*** Warnings about useless %pure-parser/%define api.pure are restored
** Diagnostics reported by Bison ** Diagnostics reported by Bison
Most of these features were contributed by Théophile Ranquet and Victor Most of these features were contributed by Théophile Ranquet and Victor
@@ -104,29 +58,6 @@ GNU Bison NEWS
activated by default. The old format can still be used by invoking Bison activated by default. The old format can still be used by invoking Bison
with -fno-caret (or -fnone). with -fno-caret (or -fnone).
Some error messages that reproduced excerpts of the grammar are now using
the caret information only. For instance on:
%%
exp: 'a' | 'a';
Bison 2.7 reports:
in.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
in.y:2.12-14: warning: rule useless in parser due to conflicts: exp: 'a' [-Wother]
Now bison reports:
in.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
in.y:2.12-14: warning: rule useless in parser due to conflicts [-Wother]
exp: 'a' | 'a';
^^^
and "bison -fno-caret" reports:
in.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
in.y:2.12-14: warning: rule useless in parser due to conflicts [-Wother]
*** Enhancements of the -Werror option *** Enhancements of the -Werror option
The -Werror=CATEGORY option is now recognized, and will treat specified The -Werror=CATEGORY option is now recognized, and will treat specified
@@ -267,10 +198,12 @@ GNU Bison NEWS
bar.y: error: shift/reduce conflicts: 1 found, 0 expected bar.y: error: shift/reduce conflicts: 1 found, 0 expected
bar.y: error: reduce/reduce conflicts: 2 found, 0 expected bar.y: error: reduce/reduce conflicts: 2 found, 0 expected
** Incompatibilities with POSIX Yacc *** Useless precedence
The 'yacc' category is no longer part of '-Wall', enable it explicitly Bison now warns about symbols with a declared precedence but no declared
with '-Wyacc'. associativity (i.e. declared with %precedence), and whose precedence is
never used. In that case, the symbol can be safely declared with %token
instead, without modifying the parsing tables.
** Additional yylex/yyparse arguments ** Additional yylex/yyparse arguments
@@ -287,271 +220,13 @@ GNU Bison NEWS
%param {arg1_type *arg1} {arg2_type *arg2} %param {arg1_type *arg1} {arg2_type *arg2}
** Types of values for %define variables
Bison used to make no difference between '%define foo bar' and '%define
foo "bar"'. The former is now called a 'keyword value', and the latter a
'string value'. A third kind was added: 'code values', such as '%define
foo {bar}'.
Keyword variables are used for fixed value sets, e.g.,
%define lr.type lalr
Code variables are used for value in the target language, e.g.,
%define api.value.type {struct semantic_type}
String variables are used remaining cases, e.g. file names.
** Variable api.token.prefix
The variable api.token.prefix changes the way tokens are identified in
the generated files. This is especially useful to avoid collisions
with identifiers in the target language. For instance
%token FILE for ERROR
%define api.token.prefix {TOK_}
%%
start: FILE for ERROR;
will generate the definition of the symbols TOK_FILE, TOK_for, and
TOK_ERROR in the generated sources. In particular, the scanner must
use these prefixed token names, although the grammar itself still
uses the short names (as in the sample rule given above).
** Variable api.value.type
This new %define variable supersedes the #define macro YYSTYPE. The use
of YYSTYPE is discouraged. In particular, #defining YYSTYPE *and* either
using %union or %defining api.value.type results in undefined behavior.
Either define api.value.type, or use "%union":
%union
{
int ival;
char *sval;
}
%token <ival> INT "integer"
%token <sval> STRING "string"
%printer { fprintf (yyo, "%d", $$); } <ival>
%destructor { free ($$); } <sval>
/* In yylex(). */
yylval.ival = 42; return INT;
yylval.sval = "42"; return STRING;
The %define variable api.value.type supports both keyword and code values.
The keyword value 'union' means that the user provides genuine types, not
union member names such as "ival" and "sval" above (WARNING: will fail if
-y/--yacc/%yacc is enabled).
%define api.value.type union
%token <int> INT "integer"
%token <char *> STRING "string"
%printer { fprintf (yyo, "%d", $$); } <int>
%destructor { free ($$); } <char *>
/* In yylex(). */
yylval.INT = 42; return INT;
yylval.STRING = "42"; return STRING;
The keyword value variant is somewhat equivalent, but for C++ special
provision is made to allow classes to be used (more about this below).
%define api.value.type variant
%token <int> INT "integer"
%token <std::string> STRING "string"
Code values (in braces) denote user defined types. This is where YYSTYPE
used to be used.
%code requires
{
struct my_value
{
enum
{
is_int, is_string
} kind;
union
{
int ival;
char *sval;
} u;
};
}
%define api.value.type {struct my_value}
%token <u.ival> INT "integer"
%token <u.sval> STRING "string"
%printer { fprintf (yyo, "%d", $$); } <u.ival>
%destructor { free ($$); } <u.sval>
/* In yylex(). */
yylval.u.ival = 42; return INT;
yylval.u.sval = "42"; return STRING;
** Variable parse.error
This variable controls the verbosity of error messages. The use of the
%error-verbose directive is deprecated in favor of "%define parse.error
verbose".
** Renamed %define variables
The following variables have been renamed for consistency. Backward
compatibility is ensured, but upgrading is recommended.
lr.default-reductions -> lr.default-reduction
lr.keep-unreachable-states -> lr.keep-unreachable-state
namespace -> api.namespace
stype -> api.value.type
** Semantic predicates
Contributed by Paul Hilfinger.
The new, experimental, semantic-predicate feature allows actions of the
form "%?{ BOOLEAN-EXPRESSION }", which cause syntax errors (as for
YYERROR) if the expression evaluates to 0, and are evaluated immediately
in GLR parsers, rather than being deferred. The result is that they allow
the programmer to prune possible parses based on the values of run-time
expressions.
** The directive %expect-rr is now an error in non GLR mode
It used to be an error only if used in non GLR mode, _and_ if there are
reduce/reduce conflicts.
** Tokens are numbered in their order of appearance
Contributed by Valentin Tolmer.
With '%token A B', A had a number less than the one of B. However,
precedence declarations used to generate a reversed order. This is now
fixed, and introducing tokens with any of %token, %left, %right,
%precedence, or %nonassoc yields the same result.
When mixing declarations of tokens with a litteral character (e.g., 'a')
or with an identifier (e.g., B) in a precedence declaration, Bison
numbered the litteral characters first. For example
%right A B 'c' 'd'
would lead to the tokens declared in this order: 'c' 'd' A B. Again, the
input order is now preserved.
These changes were made so that one can remove useless precedence and
associativity declarations (i.e., map %nonassoc, %left or %right to
%precedence, or to %token) and get exactly the same output.
** Useless precedence and associativity
Contributed by Valentin Tolmer.
When developing and maintaining a grammar, useless associativity and
precedence directives are common. They can be a nuisance: new ambiguities
arising are sometimes masked because their conflicts are resolved due to
the extra precedence or associativity information. Furthermore, it can
hinder the comprehension of a new grammar: one will wonder about the role
of a precedence, where in fact it is useless. The following changes aim
at detecting and reporting these extra directives.
*** Precedence warning category
A new category of warning, -Wprecedence, was introduced. It flags the
useless precedence and associativity directives.
*** Useless associativity
Bison now warns about symbols with a declared associativity that is never
used to resolve conflicts. In that case, using %precedence is sufficient;
the parsing tables will remain unchanged. Solving these warnings may raise
useless precedence warnings, as the symbols no longer have associativity.
For example:
%left '+'
%left '*'
%%
exp:
"number"
| exp '+' "number"
| exp '*' exp
;
will produce a
warning: useless associativity for '+', use %precedence [-Wprecedence]
%left '+'
^^^
*** Useless precedence
Bison now warns about symbols with a declared precedence and no declared
associativity (i.e., declared with %precedence), and whose precedence is
never used. In that case, the symbol can be safely declared with %token
instead, without modifying the parsing tables. For example:
%precedence '='
%%
exp: "var" '=' "number";
will produce a
warning: useless precedence for '=' [-Wprecedence]
%precedence '='
^^^
*** Useless precedence and associativity
In case of both useless precedence and associativity, the issue is flagged
as follows:
%nonassoc '='
%%
exp: "var" '=' "number";
The warning is:
warning: useless precedence and associativity for '=' [-Wprecedence]
%nonassoc '='
^^^
** Empty rules
With help from Joel E. Denny and Gabriel Rassoul.
Empty rules (i.e., with an empty right-hand side) can now be explicitly
marked by the new %empty directive. Using %empty on a non-empty rule is
an error. The new -Wempty-rule warning reports empty rules without
%empty. On the following grammar:
%%
s: a b c;
a: ;
b: %empty;
c: 'a' %empty;
bison reports:
3.4-5: warning: empty rule without %empty [-Wempty-rule]
a: {}
^^
5.8-13: error: %empty on non-empty rule
c: 'a' %empty {};
^^^^^^
** Java skeleton improvements ** Java skeleton improvements
Contributed by Paolo Bonzini.
The constants for token names were moved to the Lexer interface. Also, it The constants for token names were moved to the Lexer interface. Also, it
is possible to add code to the parser's constructors using "%code init" is possible to add code to the parser's constructors using "%code init"
and "%define init_throws". and "%define init_throws".
Contributed by Paolo Bonzini.
The Java skeleton now supports push parsing.
Contributed by Dennis Heimbigner.
** C++ skeletons improvements ** C++ skeletons improvements
@@ -574,66 +249,59 @@ GNU Bison NEWS
used by the scanner, or rejecting invalid combinations from a used by the scanner, or rejecting invalid combinations from a
factory invoked by the user actions). factory invoked by the user actions).
*** %define api.value.type variant ** Renamed %define variables
This is based on a submission from Michiel De Wilde. With help The following variables have been renamed for consistency. Backward
from Théophile Ranquet. compatibility is ensured, but upgrading is recommended.
In this mode, complex C++ objects can be used as semantic values. For lr.default-reductions -> lr.default-reduction
instance: lr.keep-unreachable-states -> lr.keep-unreachable-state
namespace -> api.namespace
stype -> api.value.type
%token <::std::string> TEXT; ** Variable api.token.prefix
%token <int> NUMBER;
%token SEMICOLON ";" The variable api.token.prefix changes the way tokens are identified in
%type <::std::string> item; the generated files. This is especially useful to avoid collisions
%type <::std::list<std::string>> list; with identifiers in the target language. For instance
%token FILE for ERROR
%define api.token.prefix "TOK_"
%% %%
result: start: FILE for ERROR;
list { std::cout << $1 << std::endl; }
;
list: will generate the definition of the symbols TOK_FILE, TOK_for, and
%empty { /* Generates an empty string list. */ } TOK_ERROR in the generated sources. In particular, the scanner must
| list item ";" { std::swap ($$, $1); $$.push_back ($2); } use these prefixed token names, although the grammar itself still
; uses the short names (as in the sample rule given above).
item: ** Variable parse.error
TEXT { std::swap ($$, $1); }
| NUMBER { $$ = string_cast ($1); }
;
*** %define api.token.constructor This variable controls the verbosity of error messages. The use of the
%error-verbose directive is deprecated in favor of "%define parse.error
verbose".
When variants are enabled, Bison can generate functions to build the ** Semantic predicates
tokens. This guarantees that the token type (e.g., NUMBER) is consistent
with the semantic value (e.g., int):
parser::symbol_type yylex () Contributed by Paul Hilfinger.
{
parser::location_type loc = ...;
...
return parser::make_TEXT ("Hello, world!", loc);
...
return parser::make_NUMBER (42, loc);
...
return parser::make_SEMICOLON (loc);
...
}
*** C++ locations The new, experimental, semantic-predicate feature allows actions of the
form "%?{ BOOLEAN-EXPRESSION }", which cause syntax errors (as for
YYERROR) if the expression evaluates to 0, and are evaluated immediately
in GLR parsers, rather than being deferred. The result is that they allow
the programmer to prune possible parses based on the values of run-time
expressions.
There are operator- and operator-= for 'location'. Negative line/column ** The directive %expect-rr is now an error in non GLR mode
increments can no longer underflow the resulting value.
* Noteworthy changes in release 2.7.1 (2013-04-15) [stable] It used to be an error only if used in non GLR mode, _and_ if there are
reduce/reduce conflicts.
** Bug fixes ** Token numbering has changed to preserve the user-defined order
*** Fix compiler attribute portability (yacc.c) When declaring %token A B, the numbering for A is inferior to B. Up to now,
when declaring associativity at the same time, with %left (or %right,
With locations enabled, __attribute__ was used unprotected. %precedence, %nonassoc), B was inferior to A.
*** Fix some compiler warnings (lalr1.cc)
* Noteworthy changes in release 2.7 (2012-12-12) [stable] * Noteworthy changes in release 2.7 (2012-12-12) [stable]
@@ -685,8 +353,8 @@ GNU Bison NEWS
exp: exp '+' exp { $exp = $1 + $3; }; exp: exp '+' exp { $exp = $1 + $3; };
^^^ ^^^
The default behavior for now is still not to display these unless The default behaviour for now is still not to display these unless
explicitly asked with -fcaret (or -fall). However, in a later release, it explictly asked with -fcaret (or -fall). However, in a later release, it
will be made the default behavior (but may still be deactivated with will be made the default behavior (but may still be deactivated with
-fno-caret). -fno-caret).
@@ -773,7 +441,7 @@ GNU Bison NEWS
Other issues in the test suite have been addressed. Other issues in the test suite have been addressed.
Null characters are correctly displayed in error messages. Nul characters are correctly displayed in error messages.
When possible, yylloc is correctly initialized before calling yylex. It When possible, yylloc is correctly initialized before calling yylex. It
is no longer necessary to initialize it in the %initial-action. is no longer necessary to initialize it in the %initial-action.
@@ -2689,12 +2357,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
LocalWords: Automake TMPDIR LESSEQ ylwrap endif yydebug YYTOKEN YYLSP ival hh LocalWords: Automake TMPDIR LESSEQ ylwrap endif yydebug YYTOKEN YYLSP ival hh
LocalWords: extern YYTOKENTYPE TOKENTYPE yytokentype tokentype STYPE lval pdf LocalWords: extern YYTOKENTYPE TOKENTYPE yytokentype tokentype STYPE lval pdf
LocalWords: lang yyoutput dvi html ps POSIX lvalp llocp Wother nterm arg init LocalWords: lang yyoutput dvi html ps POSIX lvalp llocp Wother nterm arg init
LocalWords: TOK calc yyo fval Wconflicts parsers yystackp yyval yynerrs LocalWords: TOK calc yyo fval Wconflicts
LocalWords: Théophile Ranquet Santet fno fnone stype associativity Tolmer
LocalWords: Wprecedence Rassoul Wempty Paolo Bonzini parser's Michiel loc
LocalWords: redeclaration sval fcaret reentrant XSLT xsl Wmaybe yyvsp Tedi
LocalWords: pragmas noreturn untyped Rozenman unexpanded Wojciech Polak
LocalWords: Alexandre MERCHANTABILITY yytype
Local Variables: Local Variables:
mode: outline mode: outline
+1 -1
View File
@@ -30,7 +30,7 @@ not answer them, please send mail to <[email protected]>.
* Bug reports * Bug reports
Please send bug reports to <[email protected]>. Please include the Please send bug reports to <[email protected]>. Please include the
version number from 'bison --version', and a complete, self-contained version number from `bison --version', and a complete, self-contained
test case in each bug report. test case in each bug report.
* Copyright statements * Copyright statements
+1 -1
View File
@@ -9,7 +9,7 @@ Bison supports the @N construction, which gives you access to
the starting and ending line number and character number associated the starting and ending line number and character number associated
with any of the symbols in the current rule. with any of the symbols in the current rule.
Also, Bison supports the command '%expect N' which says not to mention Also, Bison supports the command `%expect N' which says not to mention
the conflicts if there are N shift/reduce conflicts and no reduce/reduce the conflicts if there are N shift/reduce conflicts and no reduce/reduce
conflicts. conflicts.
-7
View File
@@ -25,12 +25,10 @@ Bruce Lilly [email protected]
Bruno Haible [email protected] Bruno Haible [email protected]
Charles-Henri de Boysson [email protected] Charles-Henri de Boysson [email protected]
Christian Burger [email protected] Christian Burger [email protected]
Colin Daley [email protected]
Cris Bailiff [email protected] Cris Bailiff [email protected]
Cris van Pelt [email protected] Cris van Pelt [email protected]
Csaba Raduly [email protected] Csaba Raduly [email protected]
Dagobert Michelsen [email protected] Dagobert Michelsen [email protected]
Daniel Frużyński [email protected]
Daniel Hagerty [email protected] Daniel Hagerty [email protected]
David J. MacKenzie [email protected] David J. MacKenzie [email protected]
David Kastrup [email protected] David Kastrup [email protected]
@@ -39,7 +37,6 @@ Derek M. Jones [email protected]
Di-an Jan [email protected] Di-an Jan [email protected]
Dick Streefland [email protected] Dick Streefland [email protected]
Didier Godefroy [email protected] Didier Godefroy [email protected]
Efi Fogel [email protected]
Enrico Scholz [email protected] Enrico Scholz [email protected]
Eric Blake [email protected] Eric Blake [email protected]
Evgeny Stambulchik [email protected] Evgeny Stambulchik [email protected]
@@ -47,7 +44,6 @@ Fabrice Bauzac [email protected]
Florian Krohm [email protected] Florian Krohm [email protected]
Frank Heckenbach [email protected] Frank Heckenbach [email protected]
Frans Englich [email protected] Frans Englich [email protected]
Gabriel Rassoul [email protected]
Georg Sauthoff [email protected] Georg Sauthoff [email protected]
George Neuner [email protected] George Neuner [email protected]
Gilles Espinasse [email protected] Gilles Espinasse [email protected]
@@ -101,7 +97,6 @@ Peter Eisentraut [email protected]
Peter Fales [email protected] Peter Fales [email protected]
Peter Hamorsky [email protected] Peter Hamorsky [email protected]
Peter Simons [email protected] Peter Simons [email protected]
Petr Machata [email protected]
Piotr Gackiewicz [email protected] Piotr Gackiewicz [email protected]
Quentin Hocquet [email protected] Quentin Hocquet [email protected]
Quoc Peyrot [email protected] Quoc Peyrot [email protected]
@@ -111,7 +106,6 @@ Ralf Wildenhues [email protected]
Richard Stallman [email protected] Richard Stallman [email protected]
Rob Vermaas [email protected] Rob Vermaas [email protected]
Robert Anisko [email protected] Robert Anisko [email protected]
Rob Conde [email protected]
Roland Levillain [email protected] Roland Levillain [email protected]
Satya Kiran Popuri [email protected] Satya Kiran Popuri [email protected]
Sebastian Setzer [email protected] Sebastian Setzer [email protected]
@@ -132,7 +126,6 @@ Tommy Nordgren [email protected]
Troy A. Johnson [email protected] Troy A. Johnson [email protected]
Tys Lefering [email protected] Tys Lefering [email protected]
Valentin Tolmer [email protected] Valentin Tolmer [email protected]
Victor Khomenko [email protected]
Vin Shelton [email protected] Vin Shelton [email protected]
W.C.A. Wijngaards [email protected] W.C.A. Wijngaards [email protected]
Wayne Green [email protected] Wayne Green [email protected]
+12 -23
View File
@@ -1,27 +1,16 @@
* Short term * Short term
** Graphviz display code thoughts ** Graphviz display code thoughts
The code for the --graph option is over two files: print_graph, and The code for the --graph option is over two files: print_graph, and
graphviz. This is because Bison used to also produce VCG graphs, but since graphviz. I believe this is because Bison used to also produce VCG graphs,
this is no longer true, maybe we could consider these files for fusion. but since this is no longer true, maybe we could consider these files for
fusion.
An other consideration worth noting is that print_graph.c (correct me if I Little effort factoring seems to have been given to factoring in these files,
am wrong) should contain generic functions, whereas graphviz.c and other and their print-xml and print counterpart. We would very much like to re-use
potential files should contain just the specific code for that output the pretty format of states from .output in the .dot
format. It will probably prove difficult to tell if the implementation is
actually generic whilst only having support for a single format, but it
would be nice to keep stuff a bit tidier: right now, the construction of the
bitset used to show reductions is in the graphviz-specific code, and on the
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 Also, the underscore in print_graph.[ch] isn't very fitting considering
rint{,-xml} counterpart. We would very much like to re-use the pretty format the dashes in the other filenames.
of states from .output for the graphs, etc.
Also, the underscore in print_graph.[ch] isn't very fitting considering the
dashes in the other filenames.
Since graphviz dies on medium-to-big grammars, maybe consider an other tool?
** push-parser ** push-parser
Check it too when checking the different kinds of parsers. And be Check it too when checking the different kinds of parsers. And be
@@ -176,13 +165,13 @@ part of $default. Should we make the two reductions explicit, or just
keep $default? See the following point. keep $default? See the following point.
** Disabled Reductions ** Disabled Reductions
See 'tests/conflicts.at (Defaulted Conflicted Reduction)', and decide See `tests/conflicts.at (Defaulted Conflicted Reduction)', and decide
what we want to do. what we want to do.
** Documentation ** Documentation
Extend with error productions. The hard part will probably be finding Extend with error productions. The hard part will probably be finding
the right rule so that a single state does not exhibit too many yet the right rule so that a single state does not exhibit too many yet
undocumented ''features''. Maybe an empty action ought to be undocumented ``features''. Maybe an empty action ought to be
presented too. Shall we try to make a single grammar with all these presented too. Shall we try to make a single grammar with all these
features, or should we have several very small grammars? features, or should we have several very small grammars?
@@ -243,9 +232,9 @@ into
exp: exp '+' exp | exp '&' exp; exp: exp '+' exp | exp '&' exp;
when there are no actions. This can significantly speed up some when there are no actions. This can significantly speed up some
grammars. I can't find the papers. In particular the book 'LR grammars. I can't find the papers. In particular the book `LR
parsing: Theory and Practice' is impossible to find, but according to parsing: Theory and Practice' is impossible to find, but according to
'Parsing Techniques: a Practical Guide', it includes information about `Parsing Techniques: a Practical Guide', it includes information about
this issue. Does anybody have it? this issue. Does anybody have it?
+43 -55
View File
@@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Print a version string. # Print a version string.
scriptversion=2013-07-03.20; # UTC scriptversion=2012-12-28.10; # UTC
# Bootstrap this package from checked-out sources. # Bootstrap this package from checked-out sources.
@@ -140,21 +140,20 @@ po_download_command_format2=\
"wget --mirror -nd -q -np -A.po -P '%s' \ "wget --mirror -nd -q -np -A.po -P '%s' \
http://translationproject.org/latest/%s/" http://translationproject.org/latest/%s/"
# Prefer a non-empty tarname (4th argument of AC_INIT if given), else
# fall back to the package name (1st argument with munging)
extract_package_name=' extract_package_name='
/^AC_INIT(\[*/{ /^AC_INIT(/{
s/// /.*,.*,.*, */{
/^[^,]*,[^,]*,[^,]*,[ []*\([^][ ,)]\)/{ s///
s//\1/ s/[][]//g
s/[],)].*// s/)$//
p p
q q
} }
s/[],)].*// s/AC_INIT(\[*//
s/]*,.*//
s/^GNU // s/^GNU //
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
s/[^abcdefghijklmnopqrstuvwxyz0123456789_]/-/g s/[^A-Za-z0-9_]/-/g
p p
} }
' '
@@ -256,12 +255,12 @@ esac
# Extra files from gnulib, which override files from other sources. # Extra files from gnulib, which override files from other sources.
test -z "${gnulib_extra_files}" && \ test -z "${gnulib_extra_files}" && \
gnulib_extra_files=" gnulib_extra_files="
build-aux/install-sh $build_aux/install-sh
build-aux/mdate-sh $build_aux/mdate-sh
build-aux/texinfo.tex $build_aux/texinfo.tex
build-aux/depcomp $build_aux/depcomp
build-aux/config.guess $build_aux/config.guess
build-aux/config.sub $build_aux/config.sub
doc/INSTALL doc/INSTALL
" "
@@ -307,34 +306,34 @@ if test -n "$checkout_only_file" && test ! -r "$checkout_only_file"; then
die "Bootstrapping from a non-checked-out distribution is risky." die "Bootstrapping from a non-checked-out distribution is risky."
fi fi
# Strip blank and comment lines to leave significant entries. # Ensure that lines starting with ! sort last, per gitignore conventions
gitignore_entries() { # for whitelisting exceptions after a more generic blacklist pattern.
sed '/^#/d; /^$/d' "$@" sort_patterns() {
sort -u "$@" | sed '/^!/ {
H
d
}
$ {
P
x
s/^\n//
}' | sed '/^$/d'
} }
# If $STR is not already on a line by itself in $FILE, insert it at the start. # If $STR is not already on a line by itself in $FILE, insert it,
# Entries are inserted at the start of the ignore list to ensure existing # sorting the new contents of the file and replacing $FILE with the result.
# entries starting with ! are not overridden. Such entries support insert_sorted_if_absent() {
# whitelisting exceptions after a more generic blacklist pattern.
insert_if_absent() {
file=$1 file=$1
str=$2 str=$2
test -f $file || touch $file test -f $file || touch $file
test -r $file || die "Error: failed to read ignore file: $file" echo "$str" | sort_patterns - $file | cmp -s - $file > /dev/null \
duplicate_entries=$(gitignore_entries $file | sort | uniq -d) || { echo "$str" | sort_patterns - $file > $file.bak \
if [ "$duplicate_entries" ] ; then && mv $file.bak $file; } \
die "Error: Duplicate entries in $file: " $duplicate_entries || die "insert_sorted_if_absent $file $str: failed"
fi
linesold=$(gitignore_entries $file | wc -l)
linesnew=$(echo "$str" | gitignore_entries - $file | sort -u | wc -l)
if [ $linesold != $linesnew ] ; then
{ echo "$str" | cat - $file > $file.bak && mv $file.bak $file; } \
|| die "insert_if_absent $file $str: failed"
fi
} }
# Adjust $PATTERN for $VC_IGNORE_FILE and insert it with # Adjust $PATTERN for $VC_IGNORE_FILE and insert it with
# insert_if_absent. # insert_sorted_if_absent.
insert_vc_ignore() { insert_vc_ignore() {
vc_ignore_file="$1" vc_ignore_file="$1"
pattern="$2" pattern="$2"
@@ -345,7 +344,7 @@ insert_vc_ignore() {
# .gitignore entry. # .gitignore entry.
pattern=$(echo "$pattern" | sed s,^,/,);; pattern=$(echo "$pattern" | sed s,^,/,);;
esac esac
insert_if_absent "$vc_ignore_file" "$pattern" insert_sorted_if_absent "$vc_ignore_file" "$pattern"
} }
# Die if there is no AC_CONFIG_AUX_DIR($build_aux) line in configure.ac. # Die if there is no AC_CONFIG_AUX_DIR($build_aux) line in configure.ac.
@@ -551,7 +550,7 @@ fi
echo "$0: Bootstrapping from checked-out $package sources..." echo "$0: Bootstrapping from checked-out $package sources..."
# See if we can use gnulib's git-merge-changelog merge driver. # See if we can use gnulib's git-merge-changelog merge driver.
if $use_git && test -d .git && (git --version) >/dev/null 2>/dev/null ; then if test -d .git && (git --version) >/dev/null 2>/dev/null ; then
if git config merge.merge-changelog.driver >/dev/null ; then if git config merge.merge-changelog.driver >/dev/null ; then
: :
elif (git-merge-changelog --version) >/dev/null 2>/dev/null ; then elif (git-merge-changelog --version) >/dev/null 2>/dev/null ; then
@@ -574,17 +573,13 @@ git_modules_config () {
test -f .gitmodules && git config --file .gitmodules "$@" test -f .gitmodules && git config --file .gitmodules "$@"
} }
if $use_git; then gnulib_path=$(git_modules_config submodule.gnulib.path)
gnulib_path=$(git_modules_config submodule.gnulib.path) test -z "$gnulib_path" && gnulib_path=gnulib
test -z "$gnulib_path" && gnulib_path=gnulib
fi
# Get gnulib files. Populate $GNULIB_SRCDIR, possibly updating a # Get gnulib files.
# submodule, for use in the rest of the script.
case ${GNULIB_SRCDIR--} in case ${GNULIB_SRCDIR--} in
-) -)
# Note that $use_git is necessarily true in this case.
if git_modules_config submodule.gnulib.url >/dev/null; then if git_modules_config submodule.gnulib.url >/dev/null; then
echo "$0: getting gnulib files..." echo "$0: getting gnulib files..."
git submodule init || exit $? git submodule init || exit $?
@@ -605,8 +600,8 @@ case ${GNULIB_SRCDIR--} in
GNULIB_SRCDIR=$gnulib_path GNULIB_SRCDIR=$gnulib_path
;; ;;
*) *)
# Use GNULIB_SRCDIR directly or as a reference. # Use GNULIB_SRCDIR as a reference.
if $use_git && test -d "$GNULIB_SRCDIR"/.git && \ if test -d "$GNULIB_SRCDIR"/.git && \
git_modules_config submodule.gnulib.url >/dev/null; then git_modules_config submodule.gnulib.url >/dev/null; then
echo "$0: getting gnulib files..." echo "$0: getting gnulib files..."
if git submodule -h|grep -- --reference > /dev/null; then if git submodule -h|grep -- --reference > /dev/null; then
@@ -632,19 +627,12 @@ case ${GNULIB_SRCDIR--} in
;; ;;
esac esac
# $GNULIB_SRCDIR now points to the version of gnulib to use, and
# we no longer need to use git or $gnulib_path below here.
if $bootstrap_sync; then if $bootstrap_sync; then
cmp -s "$0" "$GNULIB_SRCDIR/build-aux/bootstrap" || { cmp -s "$0" "$GNULIB_SRCDIR/build-aux/bootstrap" || {
echo "$0: updating bootstrap and restarting..." echo "$0: updating bootstrap and restarting..."
case $(sh -c 'echo "$1"' -- a) in
a) ignored=--;;
*) ignored=ignored;;
esac
exec sh -c \ exec sh -c \
'cp "$1" "$2" && shift && exec "${CONFIG_SHELL-/bin/sh}" "$@"' \ 'cp "$1" "$2" && shift && exec "${CONFIG_SHELL-/bin/sh}" "$@"' \
$ignored "$GNULIB_SRCDIR/build-aux/bootstrap" \ -- "$GNULIB_SRCDIR/build-aux/bootstrap" \
"$0" "$@" --no-bootstrap-sync "$0" "$@" --no-bootstrap-sync
} }
fi fi
-16
View File
@@ -1,16 +0,0 @@
# Linux seattle 2.6.32-5-amd64 #1 SMP Thu Mar 22 17:26:33 UTC 2012
# x86_64 GNU/Linux
{
index
Memcheck:Cond
fun:index
fun:expand_dynamic_string_token
fun:_dl_map_object
fun:map_doit
fun:_dl_catch_error
fun:do_preload
fun:dl_main
fun:_dl_sysdep_start
fun:_dl_start
obj:/lib/ld-2.11.3.so
}
+2 -1
View File
@@ -1,3 +1,5 @@
## Makefile for Bison testsuite.
# Copyright (C) 2000-2013 Free Software Foundation, Inc. # Copyright (C) 2000-2013 Free Software Foundation, Inc.
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
@@ -16,7 +18,6 @@
EXTRA_DIST += \ EXTRA_DIST += \
build-aux/cross-options.pl \ build-aux/cross-options.pl \
build-aux/darwin11.4.0.valgrind \ build-aux/darwin11.4.0.valgrind \
build-aux/linux-gnu.valgrind \
build-aux/move-if-change \ build-aux/move-if-change \
build-aux/prev-version.txt \ build-aux/prev-version.txt \
build-aux/update-b4-copyright build-aux/update-b4-copyright
+1 -2
View File
@@ -135,7 +135,7 @@ _sed_rm_comments_q = $(subst ','\'',$(_sed_remove_comments))
_space_before_paren_exempt =? \\n\\$$ _space_before_paren_exempt =? \\n\\$$
_space_before_paren_exempt = \ _space_before_paren_exempt = \
(^ *\#|(LA)?LR\([01]\)|percent_(code|define)|b4_syncline|m4_(define|init)|symbol) (^ *\#|\\n\\$$|%s\(to %s|(date|group|character)\(s\))
# Ensure that there is a space before each open parenthesis in C code. # Ensure that there is a space before each open parenthesis in C code.
sc_space_before_open_paren: sc_space_before_open_paren:
@if $(VC_LIST_EXCEPT) | grep -l '\.[ch]$$' > /dev/null; then \ @if $(VC_LIST_EXCEPT) | grep -l '\.[ch]$$' > /dev/null; then \
@@ -175,6 +175,5 @@ $(call exclude, \
prohibit_strcmp=^doc/bison\.texi|tests/local\.at$$ \ prohibit_strcmp=^doc/bison\.texi|tests/local\.at$$ \
prohibit_tab_based_indentation=\.(am|mk)$$|^djgpp/|^\.git \ prohibit_tab_based_indentation=\.(am|mk)$$|^djgpp/|^\.git \
require_config_h_first=^(lib/yyerror|data/(glr|yacc))\.c$$ \ require_config_h_first=^(lib/yyerror|data/(glr|yacc))\.c$$ \
space_before_open_paren=^(data/|djgpp/) \
unmarked_diagnostics=^(djgpp/|doc/bison.texi$$|tests/c\+\+\.at$$) \ unmarked_diagnostics=^(djgpp/|doc/bison.texi$$|tests/c\+\+\.at$$) \
) )
+8 -16
View File
@@ -18,7 +18,7 @@
# In order for some versions of Sun Studio to compile our C++ test cases # In order for some versions of Sun Studio to compile our C++ test cases
# correctly, we need Autoconf 2.64 or better to handle the restrict # correctly, we need Autoconf 2.64 or better to handle the restrict
# keyword in at least string.h from gnulib. We need Autoconf 2.68 or # keyword in at least string.h from gnulib. We need Autoconf 2.68 or
# better to avoid a typo in the 'configure --help' entry for the YACC # better to avoid a typo in the `configure --help' entry for the YACC
# environment variable. # environment variable.
AC_PREREQ([2.68]) AC_PREREQ([2.68])
m4_pattern_forbid([^gl_[A-Z]]) m4_pattern_forbid([^gl_[A-Z]])
@@ -91,7 +91,7 @@ if test "$enable_gcc_warnings" = yes; then
# -fno-color-diagnostics: Clang's use of colors in the error # -fno-color-diagnostics: Clang's use of colors in the error
# messages is confusing the tests looking at the compiler's output # messages is confusing the tests looking at the compiler's output
# (e.g., synclines.at). # (e.g., synclines.at).
warn_tests='-Wundef -pedantic -Wsign-compare -fno-color-diagnostics' warn_tests='-Wundef -pedantic -fno-color-diagnostics'
AC_LANG_PUSH([C]) AC_LANG_PUSH([C])
# Clang supports many of GCC's -W options, but only issues warnings # Clang supports many of GCC's -W options, but only issues warnings
@@ -143,11 +143,9 @@ if test "$enable_gcc_warnings" = yes; then
gl_WARN_ADD([$i], [WARN_CXXFLAGS_TEST]) gl_WARN_ADD([$i], [WARN_CXXFLAGS_TEST])
done done
# Clang++ 3.2+ reject C code generated by Flex. # Clang++ 3.2+ reject C code generated by Flex.
gl_WARN_ADD([-Wno-null-conversion], [FLEX_SCANNER_CXXFLAGS]) gl_WARN_ADD([-Wno-null-conversion], [WARN_NO_NULL_CONVERSION_CXXFLAGS])
# So does G++ 4.8... # Variants break strict aliasing analysis.
gl_WARN_ADD([-Wno-sign-compare], [FLEX_SCANNER_CXXFLAGS]) gl_WARN_ADD([-fno-strict-aliasing], [NO_STRICT_ALIAS_CXXFLAGS])
# ... possiby in std=c++11 mode.
gl_WARN_ADD([-Wno-zero-as-null-pointer-constant], [FLEX_SCANNER_CXXFLAGS])
CXXFLAGS=$save_CXXFLAGS CXXFLAGS=$save_CXXFLAGS
AC_LANG_POP([C++]) AC_LANG_POP([C++])
fi fi
@@ -222,7 +220,7 @@ AC_SUBST([aclocaldir])
AC_CONFIG_FILES([etc/bench.pl], [chmod +x etc/bench.pl]) AC_CONFIG_FILES([etc/bench.pl], [chmod +x etc/bench.pl])
# Initialize the test suite. # Initialize the test suite.
AC_CONFIG_TESTDIR(tests) AC_CONFIG_TESTDIR([tests], [$ac_abs_top_builddir/tests])
AC_CONFIG_FILES([tests/atlocal]) AC_CONFIG_FILES([tests/atlocal])
AC_CONFIG_FILES([tests/bison], [chmod +x tests/bison]) AC_CONFIG_FILES([tests/bison], [chmod +x tests/bison])
AC_CHECK_PROGS([VALGRIND], [valgrind]) AC_CHECK_PROGS([VALGRIND], [valgrind])
@@ -230,16 +228,10 @@ case $VALGRIND:$host_os in
'':*) ;; '':*) ;;
*:darwin*) *:darwin*)
# See README-hacking. # See README-hacking.
# VALGRIND+='-q --suppressions=$(abs_top_srcdir)/build-aux/darwin11.4.0.valgrind' # VALGRIND+=' --suppressions=$(abs_top_srcdir)/build-aux/darwin11.4.0.valgrind'
VALGRIND=;; VALGRIND=;;
*:*) *:*)
suppfile=build-aux/$host_os.valgrind AC_SUBST([VALGRIND_PREBISON], ["$VALGRIND -q"]);;
if test -f "$srcdir/$suppfile"; then
VALGRIND="$VALGRIND --gen-suppressions=all"
VALGRIND="$VALGRIND --suppressions=\$(abs_top_srcdir)/$suppfile"
fi
AC_SUBST([VALGRIND_PREBISON], ["$VALGRIND -q"])
;;
esac esac
AM_MISSING_PROG([AUTOM4TE], [autom4te]) AM_MISSING_PROG([AUTOM4TE], [autom4te])
+1 -1
View File
@@ -27,7 +27,7 @@ Currently, the supported skeletons are:
These skeletons are the only ones supported by the Bison team. These skeletons are the only ones supported by the Bison team.
Because the interface between skeletons and the bison program is not Because the interface between skeletons and the bison program is not
finished, *we are not bound to it*. In particular, Bison is not finished, *we are not bound to it*. In particular, Bison is not
mature enough for us to consider that "foreign skeletons" are mature enough for us to consider that ``foreign skeletons'' are
supported. supported.
* m4sugar * m4sugar
+28 -141
View File
@@ -85,20 +85,6 @@ m4_changecom([#])
]) ])
# b4_divert_kill(CODE)
# --------------------
# Expand CODE for its side effects, discard its output.
m4_define([b4_divert_kill],
[m4_divert_text([KILL], [$1])])
# b4_define_silent(MACRO, CODE)
# -----------------------------
# Same as m4_define, but throw away the expansion of CODE.
m4_define([b4_define_silent],
[m4_define([$1], [b4_divert_kill([$2])])])
## ---------------- ## ## ---------------- ##
## Error handling. ## ## Error handling. ##
## ---------------- ## ## ---------------- ##
@@ -327,7 +313,7 @@ m4_define([b4_define_flag_if],
# _b4_define_flag_if($1, $2, FLAG) # _b4_define_flag_if($1, $2, FLAG)
# -------------------------------- # --------------------------------
# Work around the impossibility to define macros inside macros, # Work around the impossibility to define macros inside macros,
# because issuing '[$1]' is not possible in M4. GNU M4 should provide # because issuing `[$1]' is not possible in M4. GNU M4 should provide
# $$1 a la M5/TeX. # $$1 a la M5/TeX.
m4_define([_b4_define_flag_if], m4_define([_b4_define_flag_if],
[m4_if([$1$2], $[1]$[2], [], [m4_if([$1$2], $[1]$[2], [],
@@ -361,7 +347,6 @@ b4_define_flag_if([yacc]) # Whether POSIX Yacc is emulated.
# Whether the symbol has an id. # Whether the symbol has an id.
# - id: string # - id: string
# If has_id, the id. Guaranteed to be usable as a C identifier. # If has_id, the id. Guaranteed to be usable as a C identifier.
# Prefixed by api.token.prefix if defined.
# - tag: string. # - tag: string.
# A representat of the symbol. Can be 'foo', 'foo.id', '"foo"' etc. # A representat of the symbol. Can be 'foo', 'foo.id', '"foo"' etc.
# - user_number: integer # - user_number: integer
@@ -372,13 +357,9 @@ b4_define_flag_if([yacc]) # Whether POSIX Yacc is emulated.
# The internalized number (used after yytranslate). # The internalized number (used after yytranslate).
# - has_type: 0, 1 # - has_type: 0, 1
# Whether has a semantic value. # Whether has a semantic value.
# - type_tag: string
# When api.value.type=union, the generated name for the union member.
# yytype_INT etc. for symbols that has_id, otherwise yytype_1 etc.
# - type # - type
# If it has a semantic value, its type tag, or, if variant are used, # If it has a semantic value, its type tag, or, if variant are used,
# its type. # its type.
# In the case of api.value.type=union, type is the real type (e.g. int).
# - has_printer: 0, 1 # - has_printer: 0, 1
# - printer: string # - printer: string
# - printer_file: string # - printer_file: string
@@ -461,24 +442,6 @@ m4_define([b4_symbol_destructor], [b4_symbol_action([$1], [destructor])])
m4_define([b4_symbol_printer], [b4_symbol_action([$1], [printer])]) m4_define([b4_symbol_printer], [b4_symbol_action([$1], [printer])])
# b4_symbol_actions(KIND, [TYPE = yytype])
# ----------------------------------------
# Emit the symbol actions for KIND ("printer" or "destructor").
# Dispatch on TYPE.
m4_define([b4_symbol_actions],
[m4_pushdef([b4_actions_], m4_expand([b4_symbol_foreach([b4_symbol_$1])]))dnl
m4_ifval(m4_defn([b4_actions_]),
[switch (m4_default([$2], [yytype]))
{
m4_defn([b4_actions_])
default:
break;
}dnl
],
[YYUSE (m4_default([$2], [yytype]));])dnl
m4_popdef([b4_actions_])dnl
])
# b4_symbol_case_(SYMBOL-NUM) # b4_symbol_case_(SYMBOL-NUM)
# --------------------------- # ---------------------------
# Issue a "case NUM" for SYMBOL-NUM. # Issue a "case NUM" for SYMBOL-NUM.
@@ -614,14 +577,14 @@ m4_define([b4_define_user_code],
# b4_user_initial_action # b4_user_initial_action
# b4_user_post_prologue # b4_user_post_prologue
# b4_user_pre_prologue # b4_user_pre_prologue
# b4_user_union_members # b4_user_stype
# ---------------------- # ----------------------
# Macros that issue user code, ending with synclines. # Macros that issue user code, ending with synclines.
b4_define_user_code([actions]) b4_define_user_code([actions])
b4_define_user_code([initial_action]) b4_define_user_code([initial_action])
b4_define_user_code([post_prologue]) b4_define_user_code([post_prologue])
b4_define_user_code([pre_prologue]) b4_define_user_code([pre_prologue])
b4_define_user_code([union_members]) b4_define_user_code([stype])
# b4_check_user_names(WHAT, USER-LIST, BISON-NAMESPACE) # b4_check_user_names(WHAT, USER-LIST, BISON-NAMESPACE)
@@ -702,9 +665,9 @@ m4_define([b4_percent_define_use],
# b4_percent_define_get([[foo]]) # b4_percent_define_get([[foo]])
m4_define([b4_percent_define_get], m4_define([b4_percent_define_get],
[b4_percent_define_use([$1])dnl [b4_percent_define_use([$1])dnl
b4_percent_define_ifdef_([$1], m4_ifdef([b4_percent_define(]$1[)],
[m4_indir([b4_percent_define(]$1[)])], [m4_indir([b4_percent_define(]$1[)])],
[$2])]) [$2])])
# b4_percent_define_get_loc(VARIABLE) # b4_percent_define_get_loc(VARIABLE)
# ----------------------------------- # -----------------------------------
@@ -723,21 +686,7 @@ m4_define([b4_percent_define_get_loc],
[m4_pushdef([b4_loc], m4_indir([b4_percent_define_loc(]$1[)]))dnl [m4_pushdef([b4_loc], m4_indir([b4_percent_define_loc(]$1[)]))dnl
b4_loc[]dnl b4_loc[]dnl
m4_popdef([b4_loc])], m4_popdef([b4_loc])],
[b4_fatal([[$0: undefined %%define variable '%s']], [$1])])]) [b4_fatal([[b4_percent_define_get_loc: undefined %%define variable '%s']], [$1])])])
# b4_percent_define_get_kind(VARIABLE)
# ------------------------------------
# Get the kind (code, keyword, string) of VARIABLE, i.e., how its
# value was defined (braces, not delimiters, quotes).
#
# If the %define variable VARIABLE is undefined, complain fatally
# since that's a Bison or skeleton error. Don't record this as a
# Bison usage of VARIABLE as there's no reason to suspect that the
# user-supplied value has yet influenced the output.
m4_define([b4_percent_define_get_kind],
[m4_ifdef([b4_percent_define_kind(]$1[)],
[m4_indir([b4_percent_define_kind(]$1[)])],
[b4_fatal([[$0: undefined %%define variable '%s']], [$1])])])
# b4_percent_define_get_syncline(VARIABLE) # b4_percent_define_get_syncline(VARIABLE)
# ---------------------------------------- # ----------------------------------------
@@ -754,20 +703,7 @@ m4_define([b4_percent_define_get_kind],
m4_define([b4_percent_define_get_syncline], m4_define([b4_percent_define_get_syncline],
[m4_ifdef([b4_percent_define_syncline(]$1[)], [m4_ifdef([b4_percent_define_syncline(]$1[)],
[m4_indir([b4_percent_define_syncline(]$1[)])], [m4_indir([b4_percent_define_syncline(]$1[)])],
[b4_fatal([[$0: undefined %%define variable '%s']], [$1])])]) [b4_fatal([[b4_percent_define_get_syncline: undefined %%define variable '%s']], [$1])])])
# b4_percent_define_ifdef_(VARIABLE, IF-TRUE, [IF-FALSE])
# ------------------------------------------------------
# If the %define variable VARIABLE is defined, expand IF-TRUE, else expand
# IF-FALSE. Don't record usage of VARIABLE.
#
# For example:
#
# b4_percent_define_ifdef_([[foo]], [[it's defined]], [[it's undefined]])
m4_define([b4_percent_define_ifdef_],
[m4_ifdef([b4_percent_define(]$1[)],
[$2],
[$3])])
# b4_percent_define_ifdef(VARIABLE, IF-TRUE, [IF-FALSE]) # b4_percent_define_ifdef(VARIABLE, IF-TRUE, [IF-FALSE])
# ------------------------------------------------------ # ------------------------------------------------------
@@ -780,9 +716,9 @@ m4_define([b4_percent_define_ifdef_],
# #
# b4_percent_define_ifdef([[foo]], [[it's defined]], [[it's undefined]]) # b4_percent_define_ifdef([[foo]], [[it's defined]], [[it's undefined]])
m4_define([b4_percent_define_ifdef], m4_define([b4_percent_define_ifdef],
[b4_percent_define_ifdef_([$1], [m4_ifdef([b4_percent_define(]$1[)],
[b4_percent_define_use([$1])$2], [b4_percent_define_use([$1])$2],
[$3])]) [$3])])
## --------- ## ## --------- ##
@@ -811,11 +747,11 @@ m4_define([b4_percent_define_flag_if],
[[invalid value for %%define Boolean variable '%s']], [[invalid value for %%define Boolean variable '%s']],
[$1])], [$1])],
[[b4_percent_define_flag_if($1)]])])], [[b4_percent_define_flag_if($1)]])])],
[b4_fatal([[$0: undefined %%define variable '%s']], [$1])])]) [b4_fatal([[b4_percent_define_flag_if: undefined %%define variable '%s']], [$1])])])
# b4_percent_define_default(VARIABLE, DEFAULT, [KIND = keyword]) # b4_percent_define_default(VARIABLE, DEFAULT)
# -------------------------------------------------------------- # --------------------------------------------
# Mimic muscle_percent_define_default in ../src/muscle-tab.h exactly. That is, # Mimic muscle_percent_define_default in ../src/muscle-tab.h exactly. That is,
# if the %define variable VARIABLE is undefined, set its value to DEFAULT. # if the %define variable VARIABLE is undefined, set its value to DEFAULT.
# Don't record this as a Bison usage of VARIABLE as there's no reason to # Don't record this as a Bison usage of VARIABLE as there's no reason to
@@ -825,10 +761,8 @@ m4_define([b4_percent_define_flag_if],
# #
# b4_percent_define_default([[foo]], [[default value]]) # b4_percent_define_default([[foo]], [[default value]])
m4_define([b4_percent_define_default], m4_define([b4_percent_define_default],
[b4_percent_define_ifdef_([$1], [], [m4_ifndef([b4_percent_define(]$1[)],
[m4_define([b4_percent_define(]$1[)], [$2])dnl [m4_define([b4_percent_define(]$1[)], [$2])dnl
m4_define([b4_percent_define_kind(]$1[)],
[m4_default([$3], [keyword])])dnl
m4_define([b4_percent_define_loc(]$1[)], m4_define([b4_percent_define_loc(]$1[)],
[[[[<skeleton default value>:-1.-1]], [[[[<skeleton default value>:-1.-1]],
[[<skeleton default value>:-1.-1]]]])dnl [[<skeleton default value>:-1.-1]]]])dnl
@@ -838,8 +772,8 @@ m4_define([b4_percent_define_default],
# b4_percent_define_if_define(NAME, [VARIABLE = NAME]) # b4_percent_define_if_define(NAME, [VARIABLE = NAME])
# ---------------------------------------------------- # ----------------------------------------------------
# Define b4_NAME_if that executes its $1 or $2 depending whether # Define b4_NAME_if that executes its $1 or $2 depending whether
# VARIABLE was %defined. The characters '.' and `-' in VARIABLE are mapped # VARIABLE was %defined. The characters `.' and `-' in VARIABLE are mapped
# to '_'. # to `_'.
m4_define([b4_percent_define_if_define_], m4_define([b4_percent_define_if_define_],
[m4_define(m4_bpatsubst([b4_$1_if], [[-.]], [_]), [m4_define(m4_bpatsubst([b4_$1_if], [[-.]], [_]),
[b4_percent_define_flag_if(m4_default([$2], [$1]), [b4_percent_define_flag_if(m4_default([$2], [$1]),
@@ -849,21 +783,6 @@ m4_define([b4_percent_define_if_define],
b4_percent_define_if_define_([$1], [$2], $[1], $[2])]) b4_percent_define_if_define_([$1], [$2], $[1], $[2])])
# b4_percent_define_check_kind(VARIABLE, KIND, [DIAGNOSTIC = complain])
# ---------------------------------------------------------------------
m4_define([b4_percent_define_check_kind],
[b4_percent_define_ifdef_([$1],
[m4_if(b4_percent_define_get_kind([$1]), [$2], [],
[b4_error([m4_default([$3], [complain])],
b4_percent_define_get_loc([$1]),
[m4_case([$2],
[code], [[%%define variable '%s' requires '{...}' values]],
[keyword], [[%%define variable '%s' requires keyword values]],
[string], [[%%define variable '%s' requires '"..."' values]])],
[$1])])])dnl
])
# b4_percent_define_check_values(VALUES) # b4_percent_define_check_values(VALUES)
# -------------------------------------- # --------------------------------------
# Mimic muscle_percent_define_check_values in ../src/muscle-tab.h exactly # Mimic muscle_percent_define_check_values in ../src/muscle-tab.h exactly
@@ -885,9 +804,8 @@ m4_define([b4_percent_define_check_values],
[_b4_percent_define_check_values(b4_sublist)])]) [_b4_percent_define_check_values(b4_sublist)])])
m4_define([_b4_percent_define_check_values], m4_define([_b4_percent_define_check_values],
[b4_percent_define_ifdef_([$1], [m4_ifdef([b4_percent_define(]$1[)],
[b4_percent_define_check_kind(]$1[, [keyword], [deprecated])dnl [m4_pushdef([b4_good_value], [0])dnl
m4_pushdef([b4_good_value], [0])dnl
m4_if($#, 1, [], m4_if($#, 1, [],
[m4_foreach([b4_value], m4_dquote(m4_shift($@)), [m4_foreach([b4_value], m4_dquote(m4_shift($@)),
[m4_if(m4_indir([b4_percent_define(]$1[)]), b4_value, [m4_if(m4_indir([b4_percent_define(]$1[)]), b4_value,
@@ -902,7 +820,7 @@ m4_define([_b4_percent_define_check_values],
[[accepted value: '%s']], [[accepted value: '%s']],
m4_dquote(b4_value))])])dnl m4_dquote(b4_value))])])dnl
m4_popdef([b4_good_value])], m4_popdef([b4_good_value])],
[b4_fatal([[$0: undefined %%define variable '%s']], [$1])])]) [b4_fatal([[b4_percent_define_check_values: undefined %%define variable '%s']], [$1])])])
# b4_percent_code_get([QUALIFIER]) # b4_percent_code_get([QUALIFIER])
# -------------------------------- # --------------------------------
@@ -943,6 +861,10 @@ m4_define([b4_percent_code_ifdef],
## Common variables. ## ## Common variables. ##
## ------------------ ## ## ------------------ ##
# Default values for %define.
# ---------------------------
# If the api.token.prefix, it is empty.
m4_percent_define_default([[api.token.prefix]], [[]])
# b4_parse_assert_if([IF-ASSERTIONS-ARE-USED], [IF-NOT]) # b4_parse_assert_if([IF-ASSERTIONS-ARE-USED], [IF-NOT])
# b4_parse_trace_if([IF-DEBUG-TRACES-ARE-ENABLED], [IF-NOT]) # b4_parse_trace_if([IF-DEBUG-TRACES-ARE-ENABLED], [IF-NOT])
@@ -982,11 +904,9 @@ b4_error_verbose_if([m4_define([b4_token_table_flag], [1])])
# b4_variant_if([IF-VARIANT-ARE-USED], [IF-NOT]) # b4_variant_if([IF-VARIANT-ARE-USED], [IF-NOT])
# ---------------------------------------------- # ----------------------------------------------
b4_percent_define_if_define([variant]) b4_percent_define_if_define([variant])
m4_define([b4_variant_flag], [[0]]) m4_case(b4_percent_define_get([[api.value.type]]),
b4_percent_define_ifdef([[api.value.type]], [variant], [m4_define([b4_variant_flag], [[1]])],
[m4_case(b4_percent_define_get_kind([[api.value.type]]), [keyword], [m4_define([b4_variant_flag], [[0]])])
[m4_case(b4_percent_define_get([[api.value.type]]), [variant],
[m4_define([b4_variant_flag], [[1]])])])])
b4_define_flag_if([variant]) b4_define_flag_if([variant])
@@ -1021,43 +941,10 @@ m4_define_default([b4_parse_param], [])
m4_define_default([b4_location_initial_column], [1]) m4_define_default([b4_location_initial_column], [1])
m4_define_default([b4_location_initial_line], [1]) m4_define_default([b4_location_initial_line], [1])
# Sanity checks.
## --------------- ##
## Sanity checks. ##
## --------------- ##
# api.location.prefix={...} (Java and C++).
b4_percent_define_check_kind([api.location.type], [code], [deprecated])
# api.position.prefix={...} (Java).
b4_percent_define_check_kind([api.position.type], [code], [deprecated])
# api.prefix >< %name-prefix.
b4_percent_define_check_kind([api.prefix], [code], [deprecated])
b4_percent_define_ifdef([api.prefix], b4_percent_define_ifdef([api.prefix],
[m4_ifdef([b4_prefix], [m4_ifdef([b4_prefix],
[b4_complain_at(b4_percent_define_get_loc([api.prefix]), [b4_complain_at(b4_percent_define_get_loc([api.prefix]),
[['%s' and '%s' cannot be used together]], [['%s' and '%s' cannot be used together]],
[%name-prefix], [%name-prefix],
[%define api.prefix])])]) [%define api.prefix])])])
# api.token.prefix={...}
# Make it a warning for those who used betas of Bison 3.0.
b4_percent_define_check_kind([api.token.prefix], [code], [deprecated])
# api.value.type >< %union.
b4_percent_define_ifdef([api.value.type],
[m4_ifdef([b4_union_members],
[b4_complain_at(b4_percent_define_get_loc([api.value.type]),
[['%s' and '%s' cannot be used together]],
[%union],
[%define api.value.type])])])
# api.value.type=union >< %yacc.
b4_percent_define_ifdef([api.value.type],
[m4_if(b4_percent_define_get([api.value.type]), [union],
[b4_yacc_if(dnl
[b4_complain_at(b4_percent_define_get_loc([api.value.type]),
[['%s' and '%s' cannot be used together]],
[%yacc],
[%define api.value.type "union"])])])])
+13 -35
View File
@@ -25,12 +25,6 @@ m4_include(b4_pkgdatadir/[c.m4])
m4_define([b4_comment], m4_define([b4_comment],
[b4_comment_([$1], [$2// ], [$2// ])]) [b4_comment_([$1], [$2// ], [$2// ])])
## -------- ##
## Checks. ##
## -------- ##
b4_percent_define_check_kind([api.namespace], [code], [deprecated])
b4_percent_define_check_kind([parser_class_name], [code], [deprecated])
## ---------------- ## ## ---------------- ##
## Default values. ## ## Default values. ##
@@ -44,7 +38,6 @@ b4_percent_define_default([[parser_class_name]], [[parser]])
# b4_percent_define_default([[api.location.type]], [[location]]) # b4_percent_define_default([[api.location.type]], [[location]])
b4_percent_define_default([[filename_type]], [[std::string]]) b4_percent_define_default([[filename_type]], [[std::string]])
# Make it a warning for those who used betas of Bison 3.0.
b4_percent_define_default([[api.namespace]], m4_defn([b4_prefix])) b4_percent_define_default([[api.namespace]], m4_defn([b4_prefix]))
b4_percent_define_default([[global_tokens_and_yystype]], [[false]]) b4_percent_define_default([[global_tokens_and_yystype]], [[false]])
@@ -61,8 +54,8 @@ b4_percent_define_default([[define_location_comparison]],
m4_define([b4_namespace_ref], [b4_percent_define_get([[api.namespace]])]) m4_define([b4_namespace_ref], [b4_percent_define_get([[api.namespace]])])
# Don't permit an empty b4_namespace_ref. Any '::parser::foo' appended to it # Don't permit an empty b4_namespace_ref. Any `::parser::foo' appended to it
# would compile as an absolute reference with 'parser' in the global namespace. # would compile as an absolute reference with `parser' in the global namespace.
# b4_namespace_open would open an anonymous namespace and thus establish # b4_namespace_open would open an anonymous namespace and thus establish
# internal linkage. This would compile. However, it's cryptic, and internal # internal linkage. This would compile. However, it's cryptic, and internal
# linkage for the parser would be specified in all translation units that # linkage for the parser would be specified in all translation units that
@@ -119,24 +112,19 @@ m4_define([b4_token_enums],
## Semantic Values. ## ## Semantic Values. ##
## ----------------- ## ## ----------------- ##
# b4_semantic_type_declare
# ------------------------
# b4_value_type_declare
# ---------------------
# Declare semantic_type. # Declare semantic_type.
m4_define([b4_value_type_declare], m4_define([b4_semantic_type_declare],
[b4_value_type_setup[]dnl
[ /// Symbol semantic values. [ /// Symbol semantic values.
]m4_bmatch(b4_percent_define_get_kind([[api.value.type]]), m4_ifdef([b4_stype],
[code], [ union semantic_type
[[ typedef ]b4_percent_define_get([[api.value.type]])[ semantic_type;]],
[m4_bmatch(b4_percent_define_get([[api.value.type]]),
[union\|union-directive],
[[ union semantic_type
{ {
]b4_user_union_members[ b4_user_stype
};]])])dnl };],
]) [m4_if(b4_tag_seen_flag, 0,
[[ typedef int semantic_type;]],
[[ typedef ]b4_api_PREFIX[STYPE semantic_type;]])])])
# b4_public_types_declare # b4_public_types_declare
@@ -145,7 +133,7 @@ m4_define([b4_value_type_declare],
# Depending on %define token_lex, may be output in the header or source file. # Depending on %define token_lex, may be output in the header or source file.
m4_define([b4_public_types_declare], m4_define([b4_public_types_declare],
[[#ifndef ]b4_api_PREFIX[STYPE [[#ifndef ]b4_api_PREFIX[STYPE
]b4_value_type_declare[ ]b4_semantic_type_declare[
#else #else
typedef ]b4_api_PREFIX[STYPE semantic_type; typedef ]b4_api_PREFIX[STYPE semantic_type;
#endif]b4_locations_if([ #endif]b4_locations_if([
@@ -532,13 +520,3 @@ m4_define([b4_yylloc_default_define],
while (/*CONSTCOND*/ false) while (/*CONSTCOND*/ false)
# endif # endif
]]) ]])
## -------- ##
## Checks. ##
## -------- ##
b4_token_ctor_if([b4_variant_if([],
[b4_fatal_at(b4_percent_define_get_loc(api.token.constructor),
[cannot use '%s' without '%s'],
[%define api.token.constructor],
[%define api.value.type variant]))])])
+28 -190
View File
@@ -150,7 +150,7 @@ m4_popdef([$1])dnl
# b4_parse_param_use([VAL], [LOC]) # b4_parse_param_use([VAL], [LOC])
# -------------------------------- # --------------------------------
# 'YYUSE' VAL, LOC if locations are enabled, and all the parse-params. # `YYUSE' VAL, LOC if locations are enabled, and all the parse-params.
m4_define([b4_parse_param_use], m4_define([b4_parse_param_use],
[m4_ifvaln([$1], [ YYUSE ([$1]);])dnl [m4_ifvaln([$1], [ YYUSE ([$1]);])dnl
b4_locations_if([m4_ifvaln([$2], [ YYUSE ([$2]);])])dnl b4_locations_if([m4_ifvaln([$2], [ YYUSE ([$2]);])])dnl
@@ -182,7 +182,7 @@ m4_define([b4_int_type],
# b4_int_type_for(NAME) # b4_int_type_for(NAME)
# --------------------- # ---------------------
# Return the smallest int type able to handle numbers ranging from # Return the smallest int type able to handle numbers ranging from
# 'NAME_min' to 'NAME_max' (included). # `NAME_min' to `NAME_max' (included).
m4_define([b4_int_type_for], m4_define([b4_int_type_for],
[b4_int_type($1_min, $1_max)]) [b4_int_type($1_min, $1_max)])
@@ -199,50 +199,6 @@ m4_define([b4_table_value_equals],
[(!!(($2) == ($3)))])]) [(!!(($2) == ($3)))])])
## ----------------- ##
## Compiler issues. ##
## ----------------- ##
# b4_attribute_define
# -------------------
# Provide portability for __attribute__.
m4_define([b4_attribute_define],
[#ifndef __attribute__
/* This feature is available in gcc versions 2.5 and later. */
# if (! defined __GNUC__ || __GNUC__ < 2 \
|| (__GNUC__ == 2 && __GNUC_MINOR__ < 5))
# define __attribute__(Spec) /* empty */
# endif
#endif
/* Suppress unused-variable warnings by "using" E. */
#if ! defined lint || defined __GNUC__
# define YYUSE(E) ((void) (E))
#else
# define YYUSE(E) /* empty */
#endif
#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
_Pragma ("GCC diagnostic push") \
_Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
_Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
_Pragma ("GCC diagnostic pop")
#else
# define YY_INITIAL_VALUE(Value) Value
#endif
#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
# define YY_IGNORE_MAYBE_UNINITIALIZED_END
#endif
#ifndef YY_INITIAL_VALUE
# define YY_INITIAL_VALUE(Value) /* Nothing. */
#endif
])
## ---------## ## ---------##
## Values. ## ## Values. ##
## ---------## ## ---------##
@@ -465,9 +421,12 @@ m4_ifset([b4_parse_param], [, b4_parse_param]))[
yymsg = "Deleting"; yymsg = "Deleting";
YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN switch (yytype)
]b4_symbol_actions([destructor])[ {
YY_IGNORE_MAYBE_UNINITIALIZED_END ]b4_symbol_foreach([b4_symbol_destructor])dnl
[ default:
break;
}
}]dnl }]dnl
]) ])
@@ -477,9 +436,9 @@ m4_ifset([b4_parse_param], [, b4_parse_param]))[
# Define the "yy_symbol_print" function. # Define the "yy_symbol_print" function.
m4_define_default([b4_yy_symbol_print_define], m4_define_default([b4_yy_symbol_print_define],
[[ [[
/*----------------------------------------. /*--------------------------------.
| Print this symbol's value on YYOUTPUT. | | Print this symbol on YYOUTPUT. |
`----------------------------------------*/ `--------------------------------*/
]b4_function_define([yy_symbol_value_print], ]b4_function_define([yy_symbol_value_print],
[static void], [static void],
@@ -500,7 +459,12 @@ m4_if(b4_skeleton, ["yacc.c"],
YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
# endif # endif
]])dnl ]])dnl
b4_symbol_actions([printer])[ [ switch (yytype)
{
]b4_symbol_foreach([b4_symbol_printer])dnl
[ default:
break;
}
} }
@@ -528,154 +492,28 @@ b4_locations_if([, yylocationp])[]b4_user_args[);
}]dnl }]dnl
]) ])
## ---------------- ##
## api.value.type. ##
## ---------------- ##
# ---------------------- #
# api.value.type=union. #
# ---------------------- #
# b4_symbol_type_register(SYMBOL-NUM)
# -----------------------------------
# Symbol SYMBOL-NUM has a type (for variant) instead of a type-tag.
# Extend the definition of %union's body with a field of that type,
# and extend the symbol's "type" field to point to the field name,
# instead of the type name.
m4_define([b4_symbol_type_register],
[m4_define([b4_symbol($1, type_tag)],
[b4_symbol_if([$1], [has_id],
[b4_symbol([$1], [id])],
[yytype_[]b4_symbol([$1], [number])])])dnl
m4_append([b4_user_union_members],
m4_expand([
b4_symbol_tag_comment([$1])dnl
b4_symbol([$1], [type]) b4_symbol([$1], [type_tag]);]))
])
# b4_type_define_tag(SYMBOL1-NUM, ...)
# ------------------------------------
# For the batch of symbols SYMBOL1-NUM... (which all have the same
# type), enhance the %union definition for each of them, and set
# there "type" field to the field tag name, instead of the type name.
m4_define([b4_type_define_tag],
[b4_symbol_if([$1], [has_type],
[m4_map([b4_symbol_type_register], [$@])])
])
# b4_symbol_value_union(VAL, [TYPE])
# ----------------------------------
# Same of b4_symbol_value, but when api.value.type=union.
m4_define([b4_symbol_value_union],
[m4_ifval([$2],
[(*($2*)(&$1))],
[$1])])
])
# b4_value_type_setup_union
# -------------------------
# Setup support for api.value.type=union. Symbols are defined with a
# type instead of a union member name: build the corresponding union,
# and give the symbols their tag.
m4_define([b4_value_type_setup_union],
[m4_define([b4_union_members])
b4_type_foreach([b4_type_define_tag])
m4_copy_force([b4_symbol_value_union], [b4_symbol_value])
])
# ---------------- #
# api.value.type. #
# ---------------- #
# b4_value_type_setup_variant
# ---------------------------
# Setup support for api.value.type=variant. By default, fail, specialized
# by other skeletons.
m4_define([b4_value_type_setup_variant],
[b4_complain_at(b4_percent_define_get_loc([[api.value.type]]),
[['%s' does not support '%s']],
[b4_skeleton],
[%define api.value.type variant])])
# _b4_value_type_setup_keyword
# ----------------------------
# api.value.type is defined with a keyword/string syntax. Check if
# that is properly defined, and prepare its use.
m4_define([_b4_value_type_setup_keyword],
[b4_percent_define_check_values([[[[api.value.type]],
[[none]],
[[union]],
[[union-directive]],
[[variant]],
[[yystype]]]])dnl
m4_case(b4_percent_define_get([[api.value.type]]),
[union], [b4_value_type_setup_union],
[variant], [b4_value_type_setup_variant])])
# b4_value_type_setup
# -------------------
# Check if api.value.type is properly defined, and possibly prepare
# its use.
b4_define_silent([b4_value_type_setup],
[# Define default value.
b4_percent_define_ifdef([[api.value.type]], [],
[# %union => api.value.type=union-directive
m4_ifdef([b4_union_members],
[m4_define([b4_percent_define_kind(api.value.type)], [keyword])
m4_define([b4_percent_define(api.value.type)], [union-directive])],
[# no tag seen => api.value.type={int}
m4_if(b4_tag_seen_flag, 0,
[m4_define([b4_percent_define_kind(api.value.type)], [code])
m4_define([b4_percent_define(api.value.type)], [int])],
[# otherwise api.value.type=yystype
m4_define([b4_percent_define_kind(api.value.type)], [keyword])
m4_define([b4_percent_define(api.value.type)], [yystype])])])])
# Set up.
m4_bmatch(b4_percent_define_get_kind([[api.value.type]]),
[keyword\|string], [_b4_value_type_setup_keyword])
])
## -------------- ## ## -------------- ##
## Declarations. ## ## Declarations. ##
## -------------- ## ## -------------- ##
# b4_value_type_define # b4_value_type_define
# -------------------- # --------------------
m4_define([b4_value_type_define], m4_define([b4_value_type_define],
[b4_value_type_setup[]dnl [[/* Value type. */
/* Value type. */ #if ! defined ]b4_api_PREFIX[STYPE && ! defined ]b4_api_PREFIX[STYPE_IS_DECLARED
m4_bmatch(b4_percent_define_get_kind([[api.value.type]]), ]m4_ifdef([b4_stype],
[code], [[typedef union ]b4_union_name[ ]b4_api_PREFIX[STYPE;
[[#if ! defined ]b4_api_PREFIX[STYPE && ! defined ]b4_api_PREFIX[STYPE_IS_DECLARED
typedef ]b4_percent_define_get([[api.value.type]])[ ]b4_api_PREFIX[STYPE;
# define ]b4_api_PREFIX[STYPE_IS_TRIVIAL 1
# define ]b4_api_PREFIX[STYPE_IS_DECLARED 1
#endif
]],
[m4_bmatch(b4_percent_define_get([[api.value.type]]),
[union\|union-directive],
[[#if ! defined ]b4_api_PREFIX[STYPE && ! defined ]b4_api_PREFIX[STYPE_IS_DECLARED
typedef union ]b4_union_name[ ]b4_api_PREFIX[STYPE;
union ]b4_union_name[ union ]b4_union_name[
{ {
]b4_user_union_members[ ]b4_user_stype[
}; };
# define ]b4_api_PREFIX[STYPE_IS_TRIVIAL 1 # define ]b4_api_PREFIX[STYPE_IS_TRIVIAL 1]],
[m4_if(b4_tag_seen_flag, 0,
[[typedef int ]b4_api_PREFIX[STYPE;
# define ]b4_api_PREFIX[STYPE_IS_TRIVIAL 1]])])[
# define ]b4_api_PREFIX[STYPE_IS_DECLARED 1 # define ]b4_api_PREFIX[STYPE_IS_DECLARED 1
#endif #endif
]])])]) ]])
# b4_location_type_define # b4_location_type_define
@@ -711,7 +549,7 @@ b4_pure_if([], [[extern ]b4_api_PREFIX[STYPE ]b4_prefix[lval;
# b4_YYDEBUG_define # b4_YYDEBUG_define
# ----------------- # ------------------
m4_define([b4_YYDEBUG_define], m4_define([b4_YYDEBUG_define],
[[/* Debug traces. */ [[/* Debug traces. */
]m4_if(b4_api_prefix, [yy], ]m4_if(b4_api_prefix, [yy],
+18 -1
View File
@@ -246,6 +246,13 @@ b4_percent_code_get[]dnl
# endif # endif
#endif #endif
/* Suppress unused-variable warnings by "using" E. */
#ifdef __GNUC__
# define YYUSE(E) ((void) (E))
#else
# define YYUSE(E) /* empty */
#endif
#ifndef YYFREE #ifndef YYFREE
# define YYFREE free # define YYFREE free
#endif #endif
@@ -274,7 +281,17 @@ b4_percent_code_get[]dnl
# define YYLONGJMP(Env, Val) (longjmp (Env, Val), YYASSERT (0)) # define YYLONGJMP(Env, Val) (longjmp (Env, Val), YYASSERT (0))
#endif #endif
]b4_attribute_define[ /*-----------------.
| GCC extensions. |
`-----------------*/
#ifndef __attribute__
/* This feature is available in gcc versions 2.5 and later. */
# if (! defined __GNUC__ || __GNUC__ < 2 \
|| (__GNUC__ == 2 && __GNUC_MINOR__ < 5))
# define __attribute__(Spec) /* empty */
# endif
#endif
#ifndef YYASSERT #ifndef YYASSERT
# define YYASSERT(Condition) ((void) ((Condition) || (abort (), 0))) # define YYASSERT(Condition) ((void) ((Condition) || (abort (), 0)))
+12 -1
View File
@@ -43,6 +43,12 @@
# user must initialize the first positions (in particular the # user must initialize the first positions (in particular the
# filename member). # filename member).
b4_token_ctor_if([b4_variant_if([],
[b4_fatal_at(b4_percent_define_get_loc(api.token.constructor),
[cannot use '%s' without '%s'],
[%define api.token.constructor],
[%define api.value.type variant]))])])
# We require a pure interface. # We require a pure interface.
m4_define([b4_pure_flag], [1]) m4_define([b4_pure_flag], [1])
@@ -187,7 +193,12 @@ m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
std::ostream& yyoutput = debug_stream (); std::ostream& yyoutput = debug_stream ();
std::ostream& yyo = yyoutput; std::ostream& yyo = yyoutput;
YYUSE (yyo); YYUSE (yyo);
]b4_symbol_actions([printer])[ switch (yytype)
{
]b4_symbol_foreach([b4_symbol_printer])dnl
[ default:
break;
}
} }
+1 -17
View File
@@ -103,7 +103,7 @@ m4_define([b4_int_type],
# b4_int_type_for(NAME) # b4_int_type_for(NAME)
# --------------------- # ---------------------
# Return the smallest int type able to handle numbers ranging from # Return the smallest int type able to handle numbers ranging from
# 'NAME_min' to 'NAME_max' (included). # `NAME_min' to `NAME_max' (included).
m4_define([b4_int_type_for], m4_define([b4_int_type_for],
[b4_int_type($1_min, $1_max)]) [b4_int_type($1_min, $1_max)])
@@ -169,22 +169,6 @@ m4_define([b4_predicate_case], [ case $1:
]) ])
## -------- ##
## Checks. ##
## -------- ##
b4_percent_define_check_kind([[api.value.type]], [code], [deprecated])
b4_percent_define_check_kind([[annotations]], [code], [deprecated])
b4_percent_define_check_kind([[extends]], [code], [deprecated])
b4_percent_define_check_kind([[implements]], [code], [deprecated])
b4_percent_define_check_kind([[init_throws]], [code], [deprecated])
b4_percent_define_check_kind([[lex_throws]], [code], [deprecated])
b4_percent_define_check_kind([[parser_class_name]], [code], [deprecated])
b4_percent_define_check_kind([[throws]], [code], [deprecated])
## ---------------- ## ## ---------------- ##
## Default values. ## ## Default values. ##
## ---------------- ## ## ---------------- ##
+18 -14
View File
@@ -17,8 +17,6 @@
m4_include(b4_pkgdatadir/[c++.m4]) m4_include(b4_pkgdatadir/[c++.m4])
# api.value.type=variant is valid.
m4_define([b4_value_type_setup_variant])
# b4_integral_parser_table_declare(TABLE-NAME, CONTENT, COMMENT) # b4_integral_parser_table_declare(TABLE-NAME, CONTENT, COMMENT)
# -------------------------------------------------------------- # --------------------------------------------------------------
@@ -40,14 +38,13 @@ m4_define([b4_integral_parser_table_define],
};dnl };dnl
]) ])
# b4_symbol_value_template(VAL, [TYPE]) # b4_symbol_value_template(VAL, [TYPE])
# ------------------------------------- # -------------------------------------
# Same as b4_symbol_value, but used in a template method. It makes # Same as b4_symbol_value, but used in a template method. It makes
# a difference when using variants. Note that b4_value_type_setup_union # a difference when using variants.
# overrides b4_symbol_value, so we must override it again.
m4_copy([b4_symbol_value], [b4_symbol_value_template]) m4_copy([b4_symbol_value], [b4_symbol_value_template])
m4_append([b4_value_type_setup_union],
[m4_copy_force([b4_symbol_value_union], [b4_symbol_value_template])])
# b4_lhs_value([TYPE]) # b4_lhs_value([TYPE])
# -------------------- # --------------------
@@ -204,10 +201,6 @@ b4_location_define])])[
void error (const syntax_error& err); void error (const syntax_error& err);
private: private:
/// This class is not copyable.
]b4_parser_class_name[ (const ]b4_parser_class_name[&);
]b4_parser_class_name[& operator= (const ]b4_parser_class_name[&);
/// State numbers. /// State numbers.
typedef int state_type; typedef int state_type;
@@ -598,7 +591,13 @@ m4_if(b4_prefix, [yy], [],
YY_SYMBOL_PRINT (yymsg, yysym);]b4_variant_if([], [ YY_SYMBOL_PRINT (yymsg, yysym);]b4_variant_if([], [
// User destructor. // User destructor.
b4_symbol_actions([destructor], [yysym.type_get ()])])[ symbol_number_type yytype = yysym.type_get ();
switch (yytype)
{
]b4_symbol_foreach([b4_symbol_destructor])dnl
[ default:
break;
}])[
} }
#if ]b4_api_PREFIX[DEBUG #if ]b4_api_PREFIX[DEBUG
@@ -613,7 +612,12 @@ m4_if(b4_prefix, [yy], [],
yyo << (yytype < yyntokens_ ? "token" : "nterm") yyo << (yytype < yyntokens_ ? "token" : "nterm")
<< ' ' << yytname_[yytype] << " ("]b4_locations_if([ << ' ' << yytname_[yytype] << " ("]b4_locations_if([
<< yysym.location << ": "])[; << yysym.location << ": "])[;
]b4_symbol_actions([printer])[ switch (yytype)
{
]b4_symbol_foreach([b4_symbol_printer])dnl
[ default:
break;
}
yyo << ')'; yyo << ')';
} }
#endif #endif
@@ -733,7 +737,7 @@ b4_dollar_popdef])[]dnl
yynewstate, since the latter expects the semantical and the yynewstate, since the latter expects the semantical and the
location values to have been already stored, initialize these location values to have been already stored, initialize these
stacks with a primary value. */ stacks with a primary value. */
yystack_.clear (); yystack_ = stack_type (0);
yypush_ (YY_NULL, 0, yyla); yypush_ (YY_NULL, 0, yyla);
// A new symbol was pushed on the stack. // A new symbol was pushed on the stack.
@@ -820,7 +824,7 @@ b4_dollar_popdef])[]dnl
variants. */ variants. */
b4_symbol_variant([[yyr1_@{yyn@}]], [yylhs.value], [build])],[ b4_symbol_variant([[yyr1_@{yyn@}]], [yylhs.value], [build])],[
/* If YYLEN is nonzero, implement the default value of the action: /* If YYLEN is nonzero, implement the default value of the action:
'$$ = $1'. Otherwise, use the top of the stack. `$$ = $1'. Otherwise, use the top of the stack.
Otherwise, the following line sets YYLHS.VALUE to garbage. Otherwise, the following line sets YYLHS.VALUE to garbage.
This behavior is undocumented and Bison This behavior is undocumented and Bison
+71 -260
View File
@@ -20,8 +20,7 @@ m4_include(b4_pkgdatadir/[java.m4])
b4_defines_if([b4_fatal([%s: %%defines does not make sense in Java], b4_defines_if([b4_fatal([%s: %%defines does not make sense in Java],
[b4_skeleton])]) [b4_skeleton])])
# We do not depend on %debug in Java, but pacify warnings about # We don't depend on %debug in Java, but pacify warnings about non-used flags.
# non-used flags.
b4_parse_trace_if([0], [0]) b4_parse_trace_if([0], [0])
m4_define([b4_symbol_no_destructor_assert], m4_define([b4_symbol_no_destructor_assert],
@@ -31,57 +30,6 @@ m4_define([b4_symbol_no_destructor_assert],
[b4_symbol_action_location([$1], [destructor])])])]) [b4_symbol_action_location([$1], [destructor])])])])
b4_symbol_foreach([b4_symbol_no_destructor_assert]) b4_symbol_foreach([b4_symbol_no_destructor_assert])
# Setup some macros for api.push-pull.
b4_percent_define_default([[api.push-pull]], [[pull]])
b4_percent_define_check_values([[[[api.push-pull]],
[[pull]], [[push]], [[both]]]])
# Define m4 conditional macros that encode the value
# of the api.push-pull flag.
b4_define_flag_if([pull]) m4_define([b4_pull_flag], [[1]])
b4_define_flag_if([push]) m4_define([b4_push_flag], [[1]])
m4_case(b4_percent_define_get([[api.push-pull]]),
[pull], [m4_define([b4_push_flag], [[0]])],
[push], [m4_define([b4_pull_flag], [[0]])])
# Define a macro to be true when api.push-pull has the value "both".
m4_define([b4_both_if],[b4_push_if([b4_pull_if([$1],[$2])],[$2])])
# Handle BISON_USE_PUSH_FOR_PULL for the test suite. So that push parsing
# tests function as written, do not let BISON_USE_PUSH_FOR_PULL modify the
# behavior of Bison at all when push parsing is already requested.
b4_define_flag_if([use_push_for_pull])
b4_use_push_for_pull_if([
b4_push_if([m4_define([b4_use_push_for_pull_flag], [[0]])],
[m4_define([b4_push_flag], [[1]])])])
# Define a macro to encapsulate the parse state variables.
# This allows them to be defined either in parse() when doing
# pull parsing, or as class instance variable when doing push parsing.
m4_define([b4_define_state],[[
/* Lookahead and lookahead in internal form. */
int yychar = yyempty_;
int yytoken = 0;
/* State. */
int yyn = 0;
int yylen = 0;
int yystate = 0;
YYStack yystack = new YYStack ();
int label = YYNEWSTATE;
/* Error handling. */
int yynerrs_ = 0;
]b4_locations_if([/* The location where the error started. */
b4_location_type yyerrloc = null;
/* Location. */
b4_location_type yylloc = new b4_location_type (null, null);])[
/* Semantic value of the lookahead. */
]b4_yystype[ yylval = null;
]])
b4_output_begin([b4_parser_file_name]) b4_output_begin([b4_parser_file_name])
b4_copyright([Skeleton implementation for Bison LALR(1) parsers in Java], b4_copyright([Skeleton implementation for Bison LALR(1) parsers in Java],
[2007-2013]) [2007-2013])
@@ -107,9 +55,7 @@ b4_percent_define_get3([implements], [ implements ])[
{ {
]b4_identification[ ]b4_identification[
]b4_error_verbose_if([[ ]b4_error_verbose_if([[
/** /** True if verbose error messages are enabled. */
* True if verbose error messages are enabled.
*/
private boolean yyErrorVerbose = true; private boolean yyErrorVerbose = true;
/** /**
@@ -130,24 +76,18 @@ b4_locations_if([[
* A class defining a pair of positions. Positions, defined by the * A class defining a pair of positions. Positions, defined by the
* <code>]b4_position_type[</code> class, denote a point in the input. * <code>]b4_position_type[</code> class, denote a point in the input.
* Locations represent a part of the input through the beginning * Locations represent a part of the input through the beginning
* and ending positions. * and ending positions. */
*/
public class ]b4_location_type[ { public class ]b4_location_type[ {
/** /** The first, inclusive, position in the range. */
* The first, inclusive, position in the range.
*/
public ]b4_position_type[ begin; public ]b4_position_type[ begin;
/** /** The first position beyond the range. */
* The first position beyond the range.
*/
public ]b4_position_type[ end; public ]b4_position_type[ end;
/** /**
* Create a <code>]b4_location_type[</code> denoting an empty range located at * Create a <code>]b4_location_type[</code> denoting an empty range located at
* a given point. * a given point.
* @@param loc The position at which the range is anchored. * @@param loc The position at which the range is anchored. */
*/
public ]b4_location_type[ (]b4_position_type[ loc) { public ]b4_location_type[ (]b4_position_type[ loc) {
this.begin = this.end = loc; this.begin = this.end = loc;
} }
@@ -155,8 +95,7 @@ b4_locations_if([[
/** /**
* Create a <code>]b4_location_type[</code> from the endpoints of the range. * Create a <code>]b4_location_type[</code> from the endpoints of the range.
* @@param begin The first position included in the range. * @@param begin The first position included in the range.
* @@param end The first position beyond the range. * @@param end The first position beyond the range. */
*/
public ]b4_location_type[ (]b4_position_type[ begin, ]b4_position_type[ end) { public ]b4_location_type[ (]b4_position_type[ begin, ]b4_position_type[ end) {
this.begin = begin; this.begin = begin;
this.end = end; this.end = end;
@@ -165,8 +104,7 @@ b4_locations_if([[
/** /**
* Print a representation of the location. For this to be correct, * Print a representation of the location. For this to be correct,
* <code>]b4_position_type[</code> should override the <code>equals</code> * <code>]b4_position_type[</code> should override the <code>equals</code>
* method. * method. */
*/
public String toString () { public String toString () {
if (begin.equals (end)) if (begin.equals (end))
return begin.toString (); return begin.toString ();
@@ -198,28 +136,24 @@ b4_locations_if([[
]b4_locations_if([[/** ]b4_locations_if([[/**
* Method to retrieve the beginning position of the last scanned token. * Method to retrieve the beginning position of the last scanned token.
* @@return the position at which the last scanned token starts. * @@return the position at which the last scanned token starts. */
*/
]b4_position_type[ getStartPos (); ]b4_position_type[ getStartPos ();
/** /**
* Method to retrieve the ending position of the last scanned token. * Method to retrieve the ending position of the last scanned token.
* @@return the first position beyond the last scanned token. * @@return the first position beyond the last scanned token. */
*/
]b4_position_type[ getEndPos ();]])[ ]b4_position_type[ getEndPos ();]])[
/** /**
* Method to retrieve the semantic value of the last scanned token. * Method to retrieve the semantic value of the last scanned token.
* @@return the semantic value of the last scanned token. * @@return the semantic value of the last scanned token. */
*/
]b4_yystype[ getLVal (); ]b4_yystype[ getLVal ();
/** /**
* Entry point for the scanner. Returns the token identifier corresponding * Entry point for the scanner. Returns the token identifier corresponding
* to the next token and prepares to return the semantic value * to the next token and prepares to return the semantic value
* ]b4_locations_if([and beginning/ending positions ])[of the token. * ]b4_locations_if([and beginning/ending positions ])[of the token.
* @@return the token identifier corresponding to the next token. * @@return the token identifier corresponding to the next token. */
*/
int yylex () ]b4_maybe_throws([b4_lex_throws])[; int yylex () ]b4_maybe_throws([b4_lex_throws])[;
/** /**
@@ -228,8 +162,7 @@ b4_locations_if([[
* *
* ]b4_locations_if([[@@param loc The location of the element to which the * ]b4_locations_if([[@@param loc The location of the element to which the
* error message is related]])[ * error message is related]])[
* @@param msg The string for the error message. * @@param msg The string for the error message. */
*/
void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[String msg);] void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[String msg);]
} }
@@ -237,9 +170,7 @@ b4_locations_if([[
]b4_percent_code_get([[lexer]])[ ]b4_percent_code_get([[lexer]])[
} }
]])[/** ]])[/** The object doing lexical analysis for us. */
* The object doing lexical analysis for us.
*/
private Lexer yylexer; private Lexer yylexer;
] ]
b4_parse_param_vars b4_parse_param_vars
@@ -405,49 +336,34 @@ b4_lexer_if([[
/** /**
* Returned by a Bison action in order to stop the parsing process and * Returned by a Bison action in order to stop the parsing process and
* return success (<tt>true</tt>). * return success (<tt>true</tt>). */
*/
public static final int YYACCEPT = 0; public static final int YYACCEPT = 0;
/** /**
* Returned by a Bison action in order to stop the parsing process and * Returned by a Bison action in order to stop the parsing process and
* return failure (<tt>false</tt>). * return failure (<tt>false</tt>). */
*/
public static final int YYABORT = 1; public static final int YYABORT = 1;
]b4_push_if([
/**
* Returned by a Bison action in order to request a new token.
*/
public static final int YYPUSH_MORE = 4;])[
/** /**
* Returned by a Bison action in order to start error recovery without * Returned by a Bison action in order to start error recovery without
* printing an error message. * printing an error message. */
*/
public static final int YYERROR = 2; public static final int YYERROR = 2;
/** // Internal return codes that are not supported for user semantic
* Internal return codes that are not supported for user semantic // actions.
* actions.
*/
private static final int YYERRLAB = 3; private static final int YYERRLAB = 3;
private static final int YYNEWSTATE = 4; private static final int YYNEWSTATE = 4;
private static final int YYDEFAULT = 5; private static final int YYDEFAULT = 5;
private static final int YYREDUCE = 6; private static final int YYREDUCE = 6;
private static final int YYERRLAB1 = 7; private static final int YYERRLAB1 = 7;
private static final int YYRETURN = 8; private static final int YYRETURN = 8;
]b4_push_if([[ private static final int YYGETTOKEN = 9; /* Signify that a new token is expected when doing push-parsing. */]])[
private int yyerrstatus_ = 0; private int yyerrstatus_ = 0;
]b4_push_if([dnl
b4_define_state])[
/** /**
* Return whether error recovery is being done. In this state, the parser * Return whether error recovery is being done. In this state, the parser
* reads token until it reaches a known state, and then restarts normal * reads token until it reaches a known state, and then restarts normal
* operation. * operation. */
*/
public final boolean recovering () public final boolean recovering ()
{ {
return yyerrstatus_ == 0; return yyerrstatus_ == 0;
@@ -459,7 +375,7 @@ b4_define_state])[
]b4_locations_if([b4_location_type[ yyloc = yylloc (yystack, yylen);]])[ ]b4_locations_if([b4_location_type[ yyloc = yylloc (yystack, yylen);]])[
/* If YYLEN is nonzero, implement the default value of the action: /* If YYLEN is nonzero, implement the default value of the action:
'$$ = $1'. Otherwise, use the top of the stack. `$$ = $1'. Otherwise, use the top of the stack.
Otherwise, the following line sets YYVAL to garbage. Otherwise, the following line sets YYVAL to garbage.
This behavior is undocumented and Bison This behavior is undocumented and Bison
@@ -547,7 +463,6 @@ b4_define_state])[
+ (yyvaluep == null ? "(null)" : yyvaluep.toString ()) + ")"); + (yyvaluep == null ? "(null)" : yyvaluep.toString ()) + ")");
} }
]b4_push_if([],[[
/** /**
* Parse input from the scanner that was specified at object construction * Parse input from the scanner that was specified at object construction
* time. Return whether the end of the input was reached successfully. * time. Return whether the end of the input was reached successfully.
@@ -555,53 +470,46 @@ b4_define_state])[
* @@return <tt>true</tt> if the parsing succeeds. Note that this does not * @@return <tt>true</tt> if the parsing succeeds. Note that this does not
* imply that there were no syntax errors. * imply that there were no syntax errors.
*/ */
public boolean parse () ]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[]])[ public boolean parse () ]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[
]b4_push_if([
/**
* Push Parse input from external lexer
*
* @@param yylextoken current token
* @@param yylexval current lval
]b4_locations_if([ * @@param yylexloc current position])[
*
* @@return <tt>YYACCEPT, YYABORT, YYPUSH_MORE</tt>
*/
public int push_parse (int yylextoken, b4_yystype yylexval[]b4_locations_if([, b4_location_type yylexloc]))
b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])])[
{ {
]b4_locations_if([/* @@$. */ /// Lookahead and lookahead in internal form.
b4_location_type yyloc;])[ int yychar = yyempty_;
]b4_push_if([],[[ int yytoken = 0;
]b4_define_state[
/* State. */
int yyn = 0;
int yylen = 0;
int yystate = 0;
YYStack yystack = new YYStack ();
/* Error handling. */
int yynerrs_ = 0;
]b4_locations_if([/// The location where the error started.
]b4_location_type[ yyerrloc = null;
/// ]b4_location_type[ of the lookahead.
]b4_location_type[ yylloc = new ]b4_location_type[ (null, null);
/// @@$.
]b4_location_type[ yyloc;])
/// Semantic value of the lookahead.
b4_yystype[ yylval = null;
yycdebug ("Starting parse\n"); yycdebug ("Starting parse\n");
yyerrstatus_ = 0; yyerrstatus_ = 0;
/* Initialize the stack. */
yystack.push (yystate, yylval ]b4_locations_if([, yylloc])[);
]m4_ifdef([b4_initial_action], [ ]m4_ifdef([b4_initial_action], [
b4_dollar_pushdef([yylval], [], [yylloc])dnl b4_dollar_pushdef([yylval], [], [yylloc])dnl
/* User initialization code. */ /* User initialization code. */
b4_user_initial_action b4_user_initial_action
b4_dollar_popdef[]dnl b4_dollar_popdef])[]dnl
])[
]])[
]b4_push_if([[
if (!this.push_parse_initialized)
{
push_parse_initialize ();
]m4_ifdef([b4_initial_action], [
b4_dollar_pushdef([yylval], [], [yylloc])dnl
/* User initialization code. */
b4_user_initial_action
b4_dollar_popdef[]dnl
])[
yycdebug ("Starting parse\n");
yyerrstatus_ = 0;
} else
label = YYGETTOKEN;
boolean push_token_consumed = true; [ /* Initialize the stack. */
]])[ yystack.push (yystate, yylval]b4_locations_if([, yylloc])[);
int label = YYNEWSTATE;
for (;;) for (;;)
switch (label) switch (label)
{ {
@@ -614,8 +522,7 @@ b4_dollar_popdef[]dnl
/* Accept? */ /* Accept? */
if (yystate == yyfinal_) if (yystate == yyfinal_)
]b4_push_if([{label = YYACCEPT; break;}], return true;
[return true;])[
/* Take a decision. First try without lookahead. */ /* Take a decision. First try without lookahead. */
yyn = yypact_[yystate]; yyn = yypact_[yystate];
@@ -624,27 +531,16 @@ b4_dollar_popdef[]dnl
label = YYDEFAULT; label = YYDEFAULT;
break; break;
} }
]b4_push_if([ /* Fall Through */
case YYGETTOKEN:])[
/* Read a lookahead token. */ /* Read a lookahead token. */
if (yychar == yyempty_) if (yychar == yyempty_)
{ {
]b4_push_if([[
if (!push_token_consumed)
return YYPUSH_MORE;
yycdebug ("Reading a token: "); yycdebug ("Reading a token: ");
yychar = yylextoken; yychar = yylexer.yylex ();]
yylval = yylexval;]b4_locations_if([ b4_locations_if([[
yylloc = yylexloc;])[ yylloc = new ]b4_location_type[(yylexer.getStartPos (),
push_token_consumed = false;]])[ yylexer.getEndPos ());]])
]b4_push_if([],[[ yylval = yylexer.getLVal ();[
yycdebug ("Reading a token: ");
yychar = yylexer.yylex ();
yylval = yylexer.getLVal ();]b4_locations_if([
yylloc = new b4_location_type (yylexer.getStartPos (),
yylexer.getEndPos ());])[
]])[
} }
/* Convert token to internal form. */ /* Convert token to internal form. */
@@ -741,10 +637,10 @@ b4_dollar_popdef[]dnl
{ {
/* Return failure if at end of input. */ /* Return failure if at end of input. */
if (yychar == Lexer.EOF) if (yychar == Lexer.EOF)
]b4_push_if([{label = YYABORT; break;}],[return false;])[ return false;
} }
else else
yychar = yyempty_; yychar = yyempty_;
} }
/* Else will try to reuse lookahead token after shifting the error /* Else will try to reuse lookahead token after shifting the error
@@ -752,9 +648,9 @@ b4_dollar_popdef[]dnl
label = YYERRLAB1; label = YYERRLAB1;
break; break;
/*-------------------------------------------------. /*---------------------------------------------------.
| errorlab -- error raised explicitly by YYERROR. | | errorlab -- error raised explicitly by YYERROR. |
`-------------------------------------------------*/ `---------------------------------------------------*/
case YYERROR: case YYERROR:
]b4_locations_if([yyerrloc = yystack.locationAt (yylen - 1);])[ ]b4_locations_if([yyerrloc = yystack.locationAt (yylen - 1);])[
@@ -786,10 +682,9 @@ b4_dollar_popdef[]dnl
} }
} }
/* Pop the current state because it cannot handle the /* Pop the current state because it cannot handle the error token. */
* error token. */
if (yystack.height == 0) if (yystack.height == 0)
]b4_push_if([{label = YYABORT; break;}],[return false;])[ return false;
]b4_locations_if([yyerrloc = yystack.locationAt (0);])[ ]b4_locations_if([yyerrloc = yystack.locationAt (0);])[
yystack.pop (); yystack.pop ();
@@ -798,11 +693,7 @@ b4_dollar_popdef[]dnl
yystack.print (yyDebugStream); yystack.print (yyDebugStream);
} }
if (label == YYABORT) ]b4_locations_if([
/* Leave the switch. */
break;
]b4_locations_if([
/* Muck with the stack to setup for yylloc. */ /* Muck with the stack to setup for yylloc. */
yystack.push (0, null, yylloc); yystack.push (0, null, yylloc);
yystack.push (0, null, yyerrloc); yystack.push (0, null, yyerrloc);
@@ -820,91 +711,13 @@ b4_dollar_popdef[]dnl
/* Accept. */ /* Accept. */
case YYACCEPT: case YYACCEPT:
]b4_push_if([this.push_parse_initialized = false; return YYACCEPT;], return true;
[return true;])[
/* Abort. */ /* Abort. */
case YYABORT: case YYABORT:
]b4_push_if([this.push_parse_initialized = false; return YYABORT;], return false;
[return false;])[
} }
}
]b4_push_if([[
boolean push_parse_initialized = false;
/**
* (Re-)Initialize the state of the push parser.
*/
public void push_parse_initialize()
{
/* Lookahead and lookahead in internal form. */
this.yychar = yyempty_;
this.yytoken = 0;
/* State. */
this.yyn = 0;
this.yylen = 0;
this.yystate = 0;
this.yystack = new YYStack ();
this.label = YYNEWSTATE;
/* Error handling. */
this.yynerrs_ = 0;
]b4_locations_if([/* The location where the error started. */
this.yyerrloc = null;
this.yylloc = new b4_location_type (null, null);])[
/* Semantic value of the lookahead. */
this.yylval = null;
yystack.push (this.yystate, this.yylval]b4_locations_if([, this.yylloc])[);
this.push_parse_initialized = true;
} }
]b4_locations_if([
/**
* Push parse given input from an external lexer.
*
* @@param yylextoken current token
* @@param yylexval current lval
* @@param yyylexpos current position
*
* @@return <tt>YYACCEPT, YYABORT, YYPUSH_MORE</tt>
*/
public int push_parse (int yylextoken, b4_yystype yylexval, b4_position_type yylexpos)
b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])
{
return push_parse (yylextoken, yylexval, new b4_location_type (yylexpos));
}
])[]])
b4_both_if([[
/**
* Parse input from the scanner that was specified at object construction
* time. Return whether the end of the input was reached successfully.
* This version of parse () is defined only when api.push-push=both.
*
* @@return <tt>true</tt> if the parsing succeeds. Note that this does not
* imply that there were no syntax errors.
*/
public boolean parse () ]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[
{
if (yylexer == null)
throw new NullPointerException("Null Lexer");
int status;
do {
int token = yylexer.yylex();
]b4_yystype[ lval = yylexer.getLVal();
]b4_locations_if([dnl
b4_location_type yyloc = new b4_location_type (yylexer.getStartPos (),
yylexer.getEndPos ());])[
]b4_locations_if([status = push_parse(token,lval,yyloc);],[
status = push_parse(token,lval);])[
} while (status == YYPUSH_MORE);
return (status == YYACCEPT);
}
]])[
// Generate an error message. // Generate an error message.
private String yysyntax_error (int yystate, int tok) private String yysyntax_error (int yystate, int tok)
@@ -939,8 +752,8 @@ b4_both_if([[
*/ */
if (tok != yyempty_) if (tok != yyempty_)
{ {
/* FIXME: This method of building the message is not compatible // FIXME: This method of building the message is not compatible
with internationalization. */ // with internationalization.
StringBuffer res = StringBuffer res =
new StringBuffer ("syntax error, unexpected "); new StringBuffer ("syntax error, unexpected ");
res.append (yytnamerr_ (yytname_[tok])); res.append (yytnamerr_ (yytname_[tok]));
@@ -989,9 +802,8 @@ b4_both_if([[
} }
/** /**
* Whether the given <code>yytable_</code> * Whether the given <code>yytable_</code> value indicates a syntax error.
* value indicates a syntax error. * @@param yyvalue the value to check
* @@param yyvalue the value to check
*/ */
private static boolean yy_table_value_is_error_ (int yyvalue) private static boolean yy_table_value_is_error_ (int yyvalue)
{ {
@@ -1013,7 +825,6 @@ b4_both_if([[
]b4_integral_parser_table_define([rline], [b4_rline], ]b4_integral_parser_table_define([rline], [b4_rline],
[[YYRLINE[YYN] -- Source line where rule number YYN was defined.]])[ [[YYRLINE[YYN] -- Source line where rule number YYN was defined.]])[
// Report on the debug stream that the rule yyrule is going to be reduced. // Report on the debug stream that the rule yyrule is going to be reduced.
private void yy_reduce_print (int yyrule, YYStack yystack) private void yy_reduce_print (int yyrule, YYStack yystack)
{ {
+24 -43
View File
@@ -25,7 +25,8 @@ m4_define([b4_position_define],
[[ /// Abstract a position. [[ /// Abstract a position.
class position class position
{ {
public:]m4_ifdef([b4_location_constructors], [[ public:
]m4_ifdef([b4_location_constructors], [[
/// Construct a position. /// Construct a position.
explicit position (]b4_percent_define_get([[filename_type]])[* f = YY_NULL, explicit position (]b4_percent_define_get([[filename_type]])[* f = YY_NULL,
unsigned int l = ]b4_location_initial_line[u, unsigned int l = ]b4_location_initial_line[u,
@@ -52,17 +53,14 @@ m4_define([b4_position_define],
/// (line related) Advance to the COUNT next lines. /// (line related) Advance to the COUNT next lines.
void lines (int count = 1) void lines (int count = 1)
{ {
if (count) column = ]b4_location_initial_column[u;
{ line += count;
column = ]b4_location_initial_column[u;
line = add_ (line, count, ]b4_location_initial_line[);
}
} }
/// (column related) Advance to the COUNT next columns. /// (column related) Advance to the COUNT next columns.
void columns (int count = 1) void columns (int count = 1)
{ {
column = add_ (column, count, ]b4_location_initial_column[); column = std::max (]b4_location_initial_column[u, column + count);
} }
/** \} */ /** \} */
@@ -72,44 +70,36 @@ m4_define([b4_position_define],
unsigned int line; unsigned int line;
/// Current column number. /// Current column number.
unsigned int column; unsigned int column;
private:
/// Compute max(min, lhs+rhs) (provided min <= lhs).
static unsigned int add_ (unsigned int lhs, int rhs, unsigned int min)
{
return (0 < rhs || -static_cast<unsigned int>(rhs) < lhs
? rhs + lhs
: min);
}
}; };
/// Add and assign a position. /// Add and assign a position.
inline position& inline position&
operator+= (position& res, int width) operator+= (position& res, const int width)
{ {
res.columns (width); res.columns (width);
return res; return res;
} }
/// Add two position objects. /// Add two position objects.
inline position inline const position
operator+ (position res, int width) operator+ (const position& begin, const int width)
{ {
position res = begin;
return res += width; return res += width;
} }
/// Add and assign a position. /// Add and assign a position.
inline position& inline position&
operator-= (position& res, int width) operator-= (position& res, const int width)
{ {
return res += -width; return res += -width;
} }
/// Add two position objects. /// Add two position objects.
inline position inline const position
operator- (position res, int width) operator- (const position& begin, const int width)
{ {
return res -= width; return begin + -width;
} }
]b4_percent_define_flag_if([[define_location_comparison]], [[ ]b4_percent_define_flag_if([[define_location_comparison]], [[
/// Compare two position objects. /// Compare two position objects.
@@ -196,13 +186,13 @@ m4_define([b4_location_define],
} }
/// Extend the current location to the COUNT next columns. /// Extend the current location to the COUNT next columns.
void columns (int count = 1) void columns (unsigned int count = 1)
{ {
end += count; end += count;
} }
/// Extend the current location to the COUNT next lines. /// Extend the current location to the COUNT next lines.
void lines (int count = 1) void lines (unsigned int count = 1)
{ {
end.lines (count); end.lines (count);
} }
@@ -217,35 +207,26 @@ m4_define([b4_location_define],
}; };
/// Join two location objects to create a location. /// Join two location objects to create a location.
inline location operator+ (location res, const location& end) inline const location operator+ (const location& begin, const location& end)
{ {
location res = begin;
res.end = end.end; res.end = end.end;
return res; return res;
} }
/// Change end position in place. /// Add two location objects.
inline location& operator+= (location& res, int width) inline const location operator+ (const location& begin, unsigned int width)
{ {
location res = begin;
res.columns (width); res.columns (width);
return res; return res;
} }
/// Change end position. /// Add and assign a location.
inline location operator+ (location res, int width) inline location& operator+= (location& res, unsigned int width)
{ {
return res += width; res.columns (width);
} return res;
/// Change end position in place.
inline location& operator-= (location& res, int width)
{
return res += -width;
}
/// Change end position.
inline location operator- (const location& begin, int width)
{
return begin + -width;
} }
]b4_percent_define_flag_if([[define_location_comparison]], [[ ]b4_percent_define_flag_if([[define_location_comparison]], [[
/// Compare two location objects. /// Compare two location objects.
-8
View File
@@ -72,12 +72,6 @@ m4_define([b4_stack_define],
seq_.pop_back (); seq_.pop_back ();
} }
void
clear ()
{
seq_.clear ();
}
inline inline
typename S::size_type typename S::size_type
size () const size () const
@@ -100,8 +94,6 @@ m4_define([b4_stack_define],
} }
private: private:
stack (const stack&);
stack& operator= (const stack&);
/// The wrapped container. /// The wrapped container.
S seq_; S seq_;
}; };
+39 -56
View File
@@ -26,7 +26,7 @@
# YYTYPE. # YYTYPE.
m4_define([b4_symbol_variant], m4_define([b4_symbol_variant],
[m4_pushdef([b4_dollar_dollar], [m4_pushdef([b4_dollar_dollar],
[$2.$3< $][3 > (m4_shift3($@))])dnl [$2.$3< $][3 >(m4_shift3($@))])dnl
switch ($1) switch ($1)
{ {
b4_type_foreach([b4_type_action_])[]dnl b4_type_foreach([b4_type_action_])[]dnl
@@ -63,7 +63,7 @@ m4_define([b4_char_sizeof],
[b4_symbol_if([$1], [has_type], [b4_symbol_if([$1], [has_type],
[ [
m4_map([ b4_symbol_tag_comment], [$@])dnl m4_map([ b4_symbol_tag_comment], [$@])dnl
char _b4_char_sizeof_dummy@{sizeof(b4_symbol([$1], [type]))@}; char _b4_char_sizeof_dummy@{sizeof([b4_symbol([$1], [type])])@};
])]) ])])
@@ -95,22 +95,22 @@ m4_define([b4_variant_define],
/// Empty construction. /// Empty construction.
variant ()]b4_parse_assert_if([ variant ()]b4_parse_assert_if([
: yytname_ (YY_NULL)])[ : tname (YY_NULL)])[
{} {}
/// Construct and fill. /// Construct and fill.
template <typename T> template <typename T>
variant (const T& t)]b4_parse_assert_if([ variant (const T& t)]b4_parse_assert_if([
: yytname_ (typeid (T).name ())])[ : tname (typeid (T).name ())])[
{ {
YYASSERT (sizeof (T) <= S); YYASSERT (sizeof (T) <= S);
new (yyas_<T> ()) T (t); new (buffer.raw) T (t);
} }
/// Destruction, allowed only if empty. /// Destruction, allowed only if empty.
~variant () ~variant ()
{]b4_parse_assert_if([ {]b4_parse_assert_if([
YYASSERT (!yytname_); YYASSERT (!tname);
])[} ])[}
/// Instantiate an empty \a T in here. /// Instantiate an empty \a T in here.
@@ -118,10 +118,10 @@ m4_define([b4_variant_define],
T& T&
build () build ()
{]b4_parse_assert_if([ {]b4_parse_assert_if([
YYASSERT (!yytname_); YYASSERT (!tname);
YYASSERT (sizeof (T) <= S); YYASSERT (sizeof (T) <= S);
yytname_ = typeid (T).name ();])[ tname = typeid (T).name ();])[
return *new (yyas_<T> ()) T; return *new (buffer.raw) T;
} }
/// Instantiate a \a T in here from \a t. /// Instantiate a \a T in here from \a t.
@@ -129,10 +129,10 @@ m4_define([b4_variant_define],
T& T&
build (const T& t) build (const T& t)
{]b4_parse_assert_if([ {]b4_parse_assert_if([
YYASSERT (!yytname_); YYASSERT (!tname);
YYASSERT (sizeof (T) <= S); YYASSERT (sizeof (T) <= S);
yytname_ = typeid (T).name ();])[ tname = typeid (T).name ();])[
return *new (yyas_<T> ()) T (t); return *new (buffer.raw) T (t);
} }
/// Accessor to a built \a T. /// Accessor to a built \a T.
@@ -140,9 +140,9 @@ m4_define([b4_variant_define],
T& T&
as () as ()
{]b4_parse_assert_if([ {]b4_parse_assert_if([
YYASSERT (yytname_ == typeid (T).name ()); YYASSERT (tname == typeid (T).name ());
YYASSERT (sizeof (T) <= S);])[ YYASSERT (sizeof (T) <= S);])[
return *yyas_<T> (); return reinterpret_cast<T&> (buffer.raw);
} }
/// Const accessor to a built \a T (for %printer). /// Const accessor to a built \a T (for %printer).
@@ -150,9 +150,9 @@ m4_define([b4_variant_define],
const T& const T&
as () const as () const
{]b4_parse_assert_if([ {]b4_parse_assert_if([
YYASSERT (yytname_ == typeid (T).name ()); YYASSERT (tname == typeid (T).name ());
YYASSERT (sizeof (T) <= S);])[ YYASSERT (sizeof (T) <= S);])[
return *yyas_<T> (); return reinterpret_cast<const T&> (buffer.raw);
} }
/// Swap the content with \a other, of same type. /// Swap the content with \a other, of same type.
@@ -167,9 +167,9 @@ m4_define([b4_variant_define],
void void
swap (self_type& other) swap (self_type& other)
{]b4_parse_assert_if([ {]b4_parse_assert_if([
YYASSERT (yytname_); YYASSERT (tname);
YYASSERT (yytname_ == other.yytname_);])[ YYASSERT (tname == other.tname);])[
std::swap (as<T> (), other.as<T> ()); std::swap (as<T>(), other.as<T>());
} }
/// Move the content of \a other to this. /// Move the content of \a other to this.
@@ -179,10 +179,10 @@ m4_define([b4_variant_define],
void void
move (self_type& other) move (self_type& other)
{]b4_parse_assert_if([ {]b4_parse_assert_if([
YYASSERT (!yytname_);])[ YYASSERT (!tname);])[
build<T> (); build<T>();
swap<T> (other); swap<T>(other);
other.destroy<T> (); other.destroy<T>();
} }
/// Copy the content of \a other to this. /// Copy the content of \a other to this.
@@ -199,7 +199,7 @@ m4_define([b4_variant_define],
destroy () destroy ()
{ {
as<T> ().~T ();]b4_parse_assert_if([ as<T> ().~T ();]b4_parse_assert_if([
yytname_ = YY_NULL;])[ tname = YY_NULL;])[
} }
private: private:
@@ -207,34 +207,17 @@ m4_define([b4_variant_define],
self_type& operator=(const self_type&); self_type& operator=(const self_type&);
variant (const self_type&); variant (const self_type&);
/// Accessor to raw memory as \a T. /// A buffer large enough to store any of the semantic values.
template <typename T> /// Long double is chosen as it has the strongest alignment
T* /// constraints.
yyas_ ()
{
void *yyp = yybuffer_.yyraw;
return static_cast<T*> (yyp);
}
/// Const accessor to raw memory as \a T.
template <typename T>
const T*
yyas_ () const
{
const void *yyp = yybuffer_.yyraw;
return static_cast<const T*> (yyp);
}
union union
{ {
/// Strongest alignment constraints. long double align_me;
long double yyalign_me; char raw[S];
/// A buffer large enough to store any of the semantic values. } buffer;]b4_parse_assert_if([
char yyraw[S];
} yybuffer_;]b4_parse_assert_if([
/// Whether the content is built: if defined, the name of the stored type. /// Whether the content is built: if defined, the name of the stored type.
const char *yytname_;])[ const char* tname;])[
}; };
]]) ]])
@@ -244,16 +227,16 @@ m4_define([b4_variant_define],
## -------------------------- ## ## -------------------------- ##
# b4_value_type_declare # b4_semantic_type_declare
# --------------------- # ------------------------
# Declare semantic_type. # Declare semantic_type.
m4_define([b4_value_type_declare], m4_define([b4_semantic_type_declare],
[[ /// An auxiliary type to compute the largest semantic type. [ /// An auxiliary type to compute the largest semantic type.
union union_type union union_type
{]b4_type_foreach([b4_char_sizeof])[}; {]b4_type_foreach([b4_char_sizeof])[};
/// Symbol semantic values. /// Symbol semantic values.
typedef variant<sizeof(union_type)> semantic_type;][]dnl typedef variant<sizeof(union_type)> semantic_type;dnl
]) ])
@@ -263,7 +246,7 @@ m4_define([b4_value_type_declare],
# ---------------------------- # ----------------------------
m4_define([b4_symbol_value], m4_define([b4_symbol_value],
[m4_ifval([$2], [m4_ifval([$2],
[$1.as< $2 > ()], [$1.as< $2 >()],
[$1])]) [$1])])
# b4_symbol_value_template(VAL, [TYPE]) # b4_symbol_value_template(VAL, [TYPE])
@@ -271,7 +254,7 @@ m4_define([b4_symbol_value],
# Same as b4_symbol_value, but used in a template method. # Same as b4_symbol_value, but used in a template method.
m4_define([b4_symbol_value_template], m4_define([b4_symbol_value_template],
[m4_ifval([$2], [m4_ifval([$2],
[$1.template as< $2 > ()], [$1.template as< $2 >()],
[$1])]) [$1])])
@@ -328,7 +311,7 @@ b4_join(b4_symbol_if([$1], [has_type],
# b4_basic_symbol_constructor_declare # b4_basic_symbol_constructor_declare
# ----------------------------------- # ----------------------------------
# Generate a constructor declaration for basic_symbol from given type. # Generate a constructor declaration for basic_symbol from given type.
m4_define([b4_basic_symbol_constructor_declare], m4_define([b4_basic_symbol_constructor_declare],
[[ [[
+1 -1
View File
@@ -373,7 +373,7 @@
</xsl:template> </xsl:template>
<xsl:template match="empty"> <xsl:template match="empty">
<xsl:text> %empty</xsl:text> <xsl:text> /* empty */</xsl:text>
</xsl:template> </xsl:template>
<xsl:template match="lookaheads"> <xsl:template match="lookaheads">
+39 -16
View File
@@ -143,6 +143,7 @@ m4_define([b4_rhs_value],
[b4_symbol_value([yyvsp@{b4_subtract([$2], [$1])@}], [$3])]) [b4_symbol_value([yyvsp@{b4_subtract([$2], [$1])@}], [$3])])
## ----------- ## ## ----------- ##
## Locations. ## ## Locations. ##
## ----------- ## ## ----------- ##
@@ -175,19 +176,36 @@ m4_define([b4_declare_scanner_communication_variables], [[
int yychar; int yychar;
]b4_pure_if([[ ]b4_pure_if([[
/* The semantic value of the lookahead symbol. */ #if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
_Pragma ("GCC diagnostic push") \
_Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
_Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
_Pragma ("GCC diagnostic pop")
#else
/* Default value used for initialization, for pacifying older GCCs /* Default value used for initialization, for pacifying older GCCs
or non-GCC compilers. */ or non-GCC compilers. */
YY_INITIAL_VALUE (static YYSTYPE yyval_default;) static YYSTYPE yyval_default;
YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);]b4_locations_if([[ # define YY_INITIAL_VALUE(Value) = Value
#endif]b4_locations_if([[
static YYLTYPE yyloc_default][]b4_yyloc_default[;]])])[
#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
# define YY_IGNORE_MAYBE_UNINITIALIZED_END
#endif
#ifndef YY_INITIAL_VALUE
# define YY_INITIAL_VALUE(Value) /* Nothing. */
#endif
/* The semantic value of the lookahead symbol. */
YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);]b4_locations_if([[
/* Location data for the lookahead symbol. */ /* Location data for the lookahead symbol. */
static YYLTYPE yyloc_default]b4_yyloc_default[; YYLTYPE yylloc]b4_pure_if([ = yyloc_default], [b4_yyloc_default])[;
YYLTYPE yylloc = yyloc_default;]])], ]])b4_pure_if([], [[
[[/* The semantic value of the lookahead symbol. */
YYSTYPE yylval;]b4_locations_if([[
/* Location data for the lookahead symbol. */
YYLTYPE yylloc]b4_yyloc_default[;]])[
/* Number of syntax errors so far. */ /* Number of syntax errors so far. */
int yynerrs;]])]) int yynerrs;]])])
@@ -205,9 +223,9 @@ m4_define([b4_declare_parser_state_variables], [b4_pure_if([[
int yyerrstatus; int yyerrstatus;
/* The stacks and their tools: /* The stacks and their tools:
'yyss': related to states. `yyss': related to states.
'yyvs': related to semantic values.]b4_locations_if([[ `yyvs': related to semantic values.]b4_locations_if([[
'yyls': related to locations.]])[ `yyls': related to locations.]])[
Refer to the stacks through separate pointers, to allow yyoverflow Refer to the stacks through separate pointers, to allow yyoverflow
to reallocate them elsewhere. */ to reallocate them elsewhere. */
@@ -413,7 +431,12 @@ typedef short int yytype_int16;
# endif # endif
#endif #endif
]b4_attribute_define[ /* Suppress unused-variable warnings by "using" E. */
#ifdef __GNUC__
# define YYUSE(E) ((void) (E))
#else
# define YYUSE(E) /* empty */
#endif
#if ]b4_lac_if([[1]], [[! defined yyoverflow || YYERROR_VERBOSE]])[ #if ]b4_lac_if([[1]], [[! defined yyoverflow || YYERROR_VERBOSE]])[
@@ -445,7 +468,7 @@ b4_push_if([], [b4_lac_if([], [[
# endif]])])[ # endif]])])[
# ifdef YYSTACK_ALLOC # ifdef YYSTACK_ALLOC
/* Pacify GCC's 'empty if-body' warning. */ /* Pacify GCC's `empty if-body' warning. */
# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) # define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
# ifndef YYSTACK_ALLOC_MAXIMUM # ifndef YYSTACK_ALLOC_MAXIMUM
/* The OS might guarantee only one guard page at the bottom of the stack, /* The OS might guarantee only one guard page at the bottom of the stack,
@@ -1631,7 +1654,7 @@ yyreduce:
yylen = yyr2[yyn]; yylen = yyr2[yyn];
/* If YYLEN is nonzero, implement the default value of the action: /* If YYLEN is nonzero, implement the default value of the action:
'$$ = $1'. `$$ = $1'.
Otherwise, the following line sets YYVAL to garbage. Otherwise, the following line sets YYVAL to garbage.
This behavior is undocumented and Bison This behavior is undocumented and Bison
@@ -1679,7 +1702,7 @@ yyreduce:
*++yyvsp = yyval;]b4_locations_if([ *++yyvsp = yyval;]b4_locations_if([
*++yylsp = yyloc;])[ *++yylsp = yyloc;])[
/* Now 'shift' the result of the reduction. Determine what state /* Now `shift' the result of the reduction. Determine what state
that goes to, based on the state we popped back to and the rule that goes to, based on the state we popped back to and the rule
number reduced by. */ number reduced by. */
+304 -704
View File
File diff suppressed because it is too large Load Diff
-2
View File
@@ -1,2 +0,0 @@
This file is a stub, not used by the documentation. If you feel like
contributing ASCII art for example.gv, please step forward!
+14 -15
View File
@@ -23,10 +23,9 @@ doc_bison_TEXINFOS = \
# Cannot express dependencies directly on file names because of Automake. # Cannot express dependencies directly on file names because of Automake.
# Obfuscate with a variable. # Obfuscate with a variable.
doc_bison = doc/bison doc_bison = doc/bison
$(doc_bison).dvi: $(FIGS_GV:.gv=.eps) $(doc_bison).dvi: $(FIGS_DOT:.dot=.eps)
$(doc_bison).info: $(FIGS_GV:.gv=.txt) $(doc_bison).pdf: $(FIGS_DOT:.dot=.pdf)
$(doc_bison).pdf: $(FIGS_GV:.gv=.pdf) $(doc_bison).html: $(FIGS_DOT:.dot=.png)
$(doc_bison).html: $(FIGS_GV:.gv=.png)
TEXI2DVI = texi2dvi --build-dir=doc/bison.t2d -I doc TEXI2DVI = texi2dvi --build-dir=doc/bison.t2d -I doc
CLEANDIRS = doc/bison.t2d CLEANDIRS = doc/bison.t2d
@@ -38,7 +37,7 @@ MOSTLYCLEANFILES += $(top_srcdir)/doc/*.t
CROSS_OPTIONS_PL = $(top_srcdir)/build-aux/cross-options.pl CROSS_OPTIONS_PL = $(top_srcdir)/build-aux/cross-options.pl
CROSS_OPTIONS_TEXI = $(top_srcdir)/doc/cross-options.texi CROSS_OPTIONS_TEXI = $(top_srcdir)/doc/cross-options.texi
$(CROSS_OPTIONS_TEXI): doc/bison.help $(CROSS_OPTIONS_PL) $(CROSS_OPTIONS_TEXI): doc/bison.help $(CROSS_OPTIONS_PL)
# Create $@~ which is the previous contents. Don't use 'mv' here so # Create $@~ which is the previous contents. Don't use `mv' here so
# that even if we are interrupted, the file is still available for # that even if we are interrupted, the file is still available for
# diff in the next run. Note that $@ might not exist yet. # diff in the next run. Note that $@ might not exist yet.
$(AM_V_GEN){ test ! -f $@ || cat $@; } >$@~ $(AM_V_GEN){ test ! -f $@ || cat $@; } >$@~
@@ -125,25 +124,25 @@ nodist_man_MANS = doc/yacc.1
## ----------------------------- ## ## ----------------------------- ##
CLEANDIRS += doc/figs CLEANDIRS += doc/figs
FIGS_GV = \ FIGS_DOT = \
doc/figs/example.gv \ doc/figs/example.dot \
doc/figs/example-reduce.gv doc/figs/example-shift.gv doc/figs/example-reduce.dot doc/figs/example-shift.dot
EXTRA_DIST += \ EXTRA_DIST += \
$(FIGS_GV) $(FIGS_GV:.gv=.txt) \ $(FIGS_DOT) \
$(FIGS_GV:.gv=.eps) $(FIGS_GV:.gv=.pdf) $(FIGS_GV:.gv=.png) $(FIGS_DOT:.dot=.eps) $(FIGS_DOT:.dot=.pdf) $(FIGS_DOT:.dot=.png)
SUFFIXES += .gv .eps .pdf .png SUFFIXES += .dot .eps .pdf .png
.gv.eps: .dot.eps:
$(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'` $(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'`
$(AM_V_at) $(DOT) -Gmargin=0 -Teps $< >$@.tmp $(AM_V_at) $(DOT) -Gmargin=0 -Teps $< >$@.tmp
$(AM_V_at) mv $@.tmp $@ $(AM_V_at) mv $@.tmp $@
.gv.pdf: .dot.pdf:
$(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'` $(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'`
$(AM_V_at) $(DOT) -Gmargin=0 -Tpdf $< >$@.tmp $(AM_V_at) $(DOT) -Gmargin=0 -Tpdf $< >$@.tmp
$(AM_V_at) mv $@.tmp $@ $(AM_V_at) mv $@.tmp $@
.gv.png: .dot.png:
$(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'` $(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'`
$(AM_V_at) $(DOT) -Gmargin=0 -Tpng $< >$@.tmp $(AM_V_at) $(DOT) -Gmargin=0 -Tpng $< >$@.tmp
$(AM_V_at) mv $@.tmp $@ $(AM_V_at) mv $@.tmp $@
+2 -2
View File
@@ -204,9 +204,9 @@ Format the list of directives for Bison for bench named C<$bench>.
sub directives($@) sub directives($@)
{ {
my ($bench, @directive) = @_; my ($bench, @directive) = @_;
my $res = "/* Directives for bench '$bench'. */\n"; my $res = "/* Directives for bench `$bench'. */\n";
$res .= join ("\n", @directive) . "\n"; $res .= join ("\n", @directive) . "\n";
$res .= "/* End of directives for bench '$bench'. */\n"; $res .= "/* End of directives for bench `$bench'. */\n";
return $res; return $res;
} }
+16 -17
View File
@@ -44,33 +44,32 @@ CLEANFILES += \
# Avoid using BUILT_SOURCES which is too global. # Avoid using BUILT_SOURCES which is too global.
$(examples_calc___calc___OBJECTS): $(calc_sources_generated) $(examples_calc___calc___OBJECTS): $(calc_sources_generated)
calc_sources_extracted = \ calc_sources_extracted = \
examples/calc++/calc++-driver.cc \ examples/calc++/calc++-driver.cc \
examples/calc++/calc++-driver.hh \ examples/calc++/calc++-driver.hh \
examples/calc++/calc++-scanner.ll \ examples/calc++/calc++-scanner.ll \
examples/calc++/calc++.cc examples/calc++/calc++.cc
calc_extracted = \ calc_extracted = \
$(calc_sources_extracted) \ $(calc_sources_extracted) \
examples/calc++/calc++-parser.yy examples/calc++/calc++-parser.yy
extracted += $(calc_extracted) extracted += $(calc_extracted)
calc_sources_generated = \ calc_sources_generated = \
examples/calc++/calc++-parser.cc \ examples/calc++/calc++-parser.cc \
examples/calc++/calc++-parser.hh \ examples/calc++/calc++-parser.hh \
examples/calc++/location.hh \ examples/calc++/location.hh \
examples/calc++/position.hh \ examples/calc++/position.hh \
examples/calc++/stack.hh examples/calc++/stack.hh
calc_sources = \ calc_sources = \
$(calc_sources_extracted) \ $(calc_sources_extracted) \
$(calc_sources_generated) $(calc_sources_generated)
if BISON_CXX_WORKS if BISON_CXX_WORKS
check_PROGRAMS += examples/calc++/calc++ check_PROGRAMS += examples/calc++/calc++
nodist_examples_calc___calc___SOURCES = \ nodist_examples_calc___calc___SOURCES = \
$(calc_sources) $(calc_sources)
examples_calc___calc___CPPFLAGS = -I$(top_builddir)/examples/calc++ examples_calc___calc___CPPFLAGS = -I$(top_builddir)/examples/calc++
examples_calc___calc___CXXFLAGS = $(AM_CXXFLAGS) $(FLEX_SCANNER_CXXFLAGS) examples_calc___calc___CXXFLAGS = \
$(AM_CXXFLAGS) $(WARN_NO_NULL_CONVERSION_CXXFLAGS)
dist_TESTS += examples/calc++/calc++.test dist_TESTS += examples/calc++/calc++.test
else
EXTRA_DIST += examples/calc++/calc++.test
endif endif
+1
View File
@@ -17,6 +17,7 @@ dist_noinst_SCRIPTS = examples/extexi examples/test
TEST_LOG_COMPILER = $(top_srcdir)/examples/test TEST_LOG_COMPILER = $(top_srcdir)/examples/test
AM_CXXFLAGS = \ AM_CXXFLAGS = \
$(NO_STRICT_ALIAS_CXXFLAGS) \
$(WARN_CXXFLAGS) $(WARN_CXXFLAGS_TEST) $(WERROR_CXXFLAGS) $(WARN_CXXFLAGS) $(WARN_CXXFLAGS_TEST) $(WERROR_CXXFLAGS)
## ------------ ## ## ------------ ##
+1 -1
Submodule gnulib updated: 03e96cc338...c67e3c0414
+1 -1
View File
@@ -17,7 +17,7 @@
/* Bison depends on libiberty's implementation of bitsets, which /* Bison depends on libiberty's implementation of bitsets, which
requires a 'libiberty.h' file. This file provides the minimum requires a `libiberty.h' file. This file provides the minimum
services. */ services. */
#ifndef BISON_LIBIBERTY_H_ #ifndef BISON_LIBIBERTY_H_
+1 -1
View File
@@ -36,7 +36,7 @@
Timing variables may be pushed onto the stack; elapsed time is Timing variables may be pushed onto the stack; elapsed time is
attributed to the topmost timing variable on the stack. When attributed to the topmost timing variable on the stack. When
another variable is pushed on, the previous topmost variable is another variable is pushed on, the previous topmost variable is
'paused' until the pushed variable is popped back off. `paused' until the pushed variable is popped back off.
- As a standalone timer, using timevar_start and timevar_stop. - As a standalone timer, using timevar_start and timevar_stop.
All time elapsed between the two calls is attributed to the All time elapsed between the two calls is attributed to the
+8 -9
View File
@@ -242,7 +242,7 @@ AnnotationList__computePredecessorAnnotations (AnnotationList *self, state *s,
{ {
symbol_number contribution_token = symbol_number contribution_token =
InadequacyList__getContributionToken (self->inadequacyNode, ci) InadequacyList__getContributionToken (self->inadequacyNode, ci)
->content->number; ->number;
if (AnnotationList__isContributionAlways (self, ci)) if (AnnotationList__isContributionAlways (self, ci))
{ {
annotation_node->contributions[ci] = NULL; annotation_node->contributions[ci] = NULL;
@@ -549,7 +549,7 @@ AnnotationList__compute_from_inadequacies (
does discard annotations in the simplest case of a S/R does discard annotations in the simplest case of a S/R
conflict with no token precedence. */ conflict with no token precedence. */
aver (!bitset_test (shift_tokens, conflicted_token) aver (!bitset_test (shift_tokens, conflicted_token)
|| symbols[conflicted_token]->content->prec); || symbols[conflicted_token]->prec);
++annotation_counts[s->number]; ++annotation_counts[s->number];
if (contribution_count > *max_contributionsp) if (contribution_count > *max_contributionsp)
*max_contributionsp = contribution_count; *max_contributionsp = contribution_count;
@@ -595,7 +595,7 @@ AnnotationList__debug (AnnotationList const *self, size_t nitems, int spaces)
{ {
symbol_number token = symbol_number token =
InadequacyList__getContributionToken (a->inadequacyNode, ci) InadequacyList__getContributionToken (a->inadequacyNode, ci)
->content->number; ->number;
{ {
int j; int j;
for (j = 0; j < spaces+2; ++j) for (j = 0; j < spaces+2; ++j)
@@ -644,7 +644,7 @@ AnnotationList__computeLookaheadFilter (AnnotationList const *self,
Sbitset biter; Sbitset biter;
symbol_number token = symbol_number token =
InadequacyList__getContributionToken (self->inadequacyNode, ci) InadequacyList__getContributionToken (self->inadequacyNode, ci)
->content->number; ->number;
SBITSET__FOR_EACH (self->contributions[ci], nitems, biter, item) SBITSET__FOR_EACH (self->contributions[ci], nitems, biter, item)
bitset_set (lookahead_filter[item], token); bitset_set (lookahead_filter[item], token);
} }
@@ -679,8 +679,7 @@ AnnotationList__stateMakesContribution (AnnotationList const *self,
return false; return false;
{ {
symbol_number token = symbol_number token =
InadequacyList__getContributionToken (self->inadequacyNode, ci) InadequacyList__getContributionToken (self->inadequacyNode, ci)->number;
->content->number;
Sbitset__Index item; Sbitset__Index item;
Sbitset biter; Sbitset biter;
SBITSET__FOR_EACH (self->contributions[ci], nitems, biter, item) SBITSET__FOR_EACH (self->contributions[ci], nitems, biter, item)
@@ -710,7 +709,7 @@ AnnotationList__computeDominantContribution (AnnotationList const *self,
ContributionIndex ci; ContributionIndex ci;
int actioni; int actioni;
ContributionIndex ci_rr_dominator = ContributionIndex__none; ContributionIndex ci_rr_dominator = ContributionIndex__none;
int shift_precedence = token->content->prec; int shift_precedence = token->prec;
/* If the token has no precedence set, shift is always chosen. */ /* If the token has no precedence set, shift is always chosen. */
if (!shift_precedence) if (!shift_precedence)
@@ -740,7 +739,7 @@ AnnotationList__computeDominantContribution (AnnotationList const *self,
if (reduce_precedence if (reduce_precedence
&& (reduce_precedence < shift_precedence && (reduce_precedence < shift_precedence
|| (reduce_precedence == shift_precedence || (reduce_precedence == shift_precedence
&& token->content->prec_node->assoc == right_assoc))) && token->assoc == right_assoc)))
continue; continue;
if (!AnnotationList__stateMakesContribution (self, nitems, ci, if (!AnnotationList__stateMakesContribution (self, nitems, ci,
lookaheads)) lookaheads))
@@ -748,7 +747,7 @@ AnnotationList__computeDominantContribution (AnnotationList const *self,
/* This uneliminated reduction contributes, so see if it can cause /* This uneliminated reduction contributes, so see if it can cause
an error action. */ an error action. */
if (reduce_precedence == shift_precedence if (reduce_precedence == shift_precedence
&& token->content->prec_node->assoc == non_assoc) && token->assoc == non_assoc)
{ {
/* It's not possible to find split-stable domination over /* It's not possible to find split-stable domination over
shift after a potential %nonassoc. */ shift after a potential %nonassoc. */
+1 -1
View File
@@ -60,7 +60,7 @@ Sbitset__isEmpty (Sbitset self, Sbitset__Index nbits)
} }
void void
Sbitset__fprint (Sbitset self, Sbitset__Index nbits, FILE *file) Sbitset__fprint(Sbitset self, Sbitset__Index nbits, FILE *file)
{ {
Sbitset__Index i; Sbitset__Index i;
Sbitset itr; Sbitset itr;
+6 -6
View File
@@ -44,31 +44,31 @@ void Sbitset__delete (Sbitset self);
bool Sbitset__isEmpty (Sbitset self, Sbitset__Index nbits); bool Sbitset__isEmpty (Sbitset self, Sbitset__Index nbits);
void Sbitset__fprint (Sbitset self, Sbitset__Index nbits, FILE *file); void Sbitset__fprint(Sbitset self, Sbitset__Index nbits, FILE *file);
# define Sbitset__set(SELF, INDEX) \ # define Sbitset__set(SELF, INDEX) \
do { \ do { \
*Sbitset__byteAddress ((SELF), (INDEX)) = \ *Sbitset__byteAddress ((SELF), (INDEX)) = \
*Sbitset__byteAddress ((SELF), (INDEX)) | Sbitset__bit_mask (INDEX); \ *Sbitset__byteAddress ((SELF), (INDEX)) | Sbitset__bit_mask (INDEX); \
} while (0) } while(0)
# define Sbitset__reset(SELF, INDEX) \ # define Sbitset__reset(SELF, INDEX) \
do { \ do { \
*Sbitset__byteAddress ((SELF), (INDEX)) = \ *Sbitset__byteAddress ((SELF), (INDEX)) = \
*Sbitset__byteAddress ((SELF), (INDEX)) & ~Sbitset__bit_mask (INDEX); \ *Sbitset__byteAddress ((SELF), (INDEX)) & ~Sbitset__bit_mask (INDEX); \
} while (0) } while(0)
/* NBITS is the size of the bitset. More than NBITS bits might be reset. */ /* NBITS is the size of the bitset. More than NBITS bits might be reset. */
# define Sbitset__zero(SELF, NBITS) \ # define Sbitset__zero(SELF, NBITS) \
do { \ do { \
memset (SELF, 0, Sbitset__nbytes (NBITS)); \ memset (SELF, 0, Sbitset__nbytes (NBITS)); \
} while (0) } while(0)
/* NBITS is the size of the bitset. More than NBITS bits might be set. */ /* NBITS is the size of the bitset. More than NBITS bits might be set. */
# define Sbitset__ones(SELF, NBITS) \ # define Sbitset__ones(SELF, NBITS) \
do { \ do { \
memset (SELF, UCHAR_MAX, Sbitset__nbytes (NBITS)); \ memset (SELF, UCHAR_MAX, Sbitset__nbytes (NBITS)); \
} while (0) } while(0)
/* NBITS is the size of every bitset. More than NBITS bits might be set. */ /* NBITS is the size of every bitset. More than NBITS bits might be set. */
# define Sbitset__or(SELF, OTHER1, OTHER2, NBITS) \ # define Sbitset__or(SELF, OTHER1, OTHER2, NBITS) \
@@ -79,7 +79,7 @@ void Sbitset__fprint (Sbitset self, Sbitset__Index nbits, FILE *file);
Sbitset end_self = ptr_self + Sbitset__nbytes (NBITS); \ Sbitset end_self = ptr_self + Sbitset__nbytes (NBITS); \
for (; ptr_self < end_self; ++ptr_self, ++ptr_other1, ++ptr_other2) \ for (; ptr_self < end_self; ++ptr_self, ++ptr_other1, ++ptr_other2) \
*ptr_self = *ptr_other1 | *ptr_other2; \ *ptr_self = *ptr_other1 | *ptr_other2; \
} while (0) } while(0)
# define SBITSET__FOR_EACH(SELF, NBITS, ITER, INDEX) \ # define SBITSET__FOR_EACH(SELF, NBITS, ITER, INDEX) \
for ((ITER) = (SELF); (ITER) < (SELF) + Sbitset__nbytes (NBITS); ++(ITER)) \ for ((ITER) = (SELF); (ITER) < (SELF) + Sbitset__nbytes (NBITS); ++(ITER)) \
+41 -214
View File
@@ -22,7 +22,6 @@
#include <config.h> #include <config.h>
#include "system.h" #include "system.h"
#include <argmatch.h>
#include <stdarg.h> #include <stdarg.h>
#include <progname.h> #include <progname.h>
@@ -31,199 +30,42 @@
#include "getargs.h" #include "getargs.h"
#include "quote.h" #include "quote.h"
warnings warnings_flag =
Wconflicts_sr | Wconflicts_rr | Wdeprecated | Wother;
warnings errors_flag;
err_status complaint_status = status_none; err_status complaint_status = status_none;
bool warnings_are_errors = false;
/** Diagnostics severity. */
typedef enum
{
severity_disabled = 0,
severity_unset = 1,
severity_warning = 2,
severity_error = 3,
severity_fatal = 4
} severity;
/** For each warning type, its severity. */
static severity warnings_flag[warnings_size];
static unsigned *indent_ptr = 0; static unsigned *indent_ptr = 0;
/*------------------------.
| --warnings's handling. |
`------------------------*/
static const char * const warnings_args[] =
{
"none",
"midrule-values",
"yacc",
"conflicts-sr",
"conflicts-rr",
"deprecated",
"empty-rule",
"precedence",
"other",
"all",
"error",
"everything",
0
};
static const int warnings_types[] =
{
Wnone,
Wmidrule_values,
Wyacc,
Wconflicts_sr,
Wconflicts_rr,
Wdeprecated,
Wempty_rule,
Wprecedence,
Wother,
Wall,
Werror,
Weverything
};
ARGMATCH_VERIFY (warnings_args, warnings_types);
void void
warning_argmatch (char const *arg, size_t no, size_t err) warnings_print_categories (warnings warn_flags)
{ {
int value = XARGMATCH ("--warning", arg + no + err, if (! (warn_flags & silent))
warnings_args, warnings_types);
/* -Wnone == -Wno-everything, and -Wno-none == -Weverything. */
if (!value)
{ {
value = Weverything; char const *warn_names[] =
no = !no; {
} "midrule-values",
"yacc",
"conflicts-sr",
"conflicts-rr",
"deprecated",
"other"
};
if (no) bool any = false;
{ int i;
size_t b; for (i = 0; i < ARRAY_CARDINALITY (warn_names); ++i)
for (b = 0; b < warnings_size; ++b) if (warn_flags & 1 << i)
if (value & 1 << b)
{ {
if (err) bool err = warn_flags & errors_flag;
{ fprintf (stderr, "%s-W", any ? ", " : " [");
/* -Wno-error=foo: if foo enabled as an error, fprintf (stderr, "%s%s", err ? "error=" : "" , warn_names[i]);
make it a warning. */ any = true;
if (warnings_flag[b] == severity_error)
warnings_flag[b] = severity_warning;
}
else
/* -Wno-foo. */
warnings_flag[b] = severity_disabled;
} }
if (any)
fprintf (stderr, "]");
} }
else
{
size_t b;
for (b = 0; b < warnings_size; ++b)
if (value & 1 << b)
/* -Wfoo and -Werror=foo. */
warnings_flag[b] = err ? severity_error : severity_warning;
}
}
/** Decode a comma-separated list of arguments from -W.
*
* \param args comma separated list of effective subarguments to decode.
* If 0, then activate all the flags.
*/
void
warnings_argmatch (char *args)
{
if (args)
for (args = strtok (args, ","); args; args = strtok (NULL, ","))
if (STREQ (args, "error"))
warnings_are_errors = true;
else if (STREQ (args, "no-error"))
{
warnings_are_errors = false;
warning_argmatch ("no-error=everything", 3, 6);
}
else
{
size_t no = STRPREFIX_LIT ("no-", args) ? 3 : 0;
size_t err = STRPREFIX_LIT ("error=", args + no) ? 6 : 0;
warning_argmatch (args, no, err);
}
else
warning_argmatch ("all", 0, 0);
}
/*-----------.
| complain. |
`-----------*/
void
complain_init (void)
{
warnings warnings_default =
Wconflicts_sr | Wconflicts_rr | Wdeprecated | Wother;
size_t b;
for (b = 0; b < warnings_size; ++b)
warnings_flag[b] = (1 << b & warnings_default
? severity_warning
: severity_unset);
}
static severity
warning_severity (warnings flags)
{
if (flags & fatal)
return severity_fatal;
else if (flags & complaint)
return severity_error;
else
{
severity res = severity_disabled;
size_t b;
for (b = 0; b < warnings_size; ++b)
if (flags & 1 << b)
res = res < warnings_flag[b] ? warnings_flag[b] : res;
if (res == severity_warning && warnings_are_errors)
res = severity_error;
return res;
}
}
bool
warning_is_unset (warnings flags)
{
size_t b;
for (b = 0; b < warnings_size; ++b)
if (flags & 1 << b && warnings_flag[b] != severity_unset)
return false;
return true;
}
/** Display a "[-Wyacc]" like message on \a f. */
static void
warnings_print_categories (warnings warn_flags, FILE *f)
{
/* Display only the first match, the second is "-Wall". */
size_t i;
for (i = 0; warnings_args[i]; ++i)
if (warn_flags & warnings_types[i])
{
severity s = warning_severity (warnings_types[i]);
fprintf (f, " [-W%s%s]",
s == severity_error ? "error=" : "",
warnings_args[i]);
return;
}
} }
/** Report an error message. /** Report an error message.
@@ -246,7 +88,7 @@ error_message (const location *loc, warnings flags, const char *prefix,
unsigned pos = 0; unsigned pos = 0;
if (loc) if (loc)
pos += location_print (*loc, stderr); pos += location_print (stderr, *loc);
else else
pos += fprintf (stderr, "%s", current_file ? current_file : program_name); pos += fprintf (stderr, "%s", current_file ? current_file : program_name);
pos += fprintf (stderr, ": "); pos += fprintf (stderr, ": ");
@@ -266,8 +108,7 @@ error_message (const location *loc, warnings flags, const char *prefix,
fprintf (stderr, "%s: ", prefix); fprintf (stderr, "%s: ", prefix);
vfprintf (stderr, message, args); vfprintf (stderr, message, args);
if (! (flags & silent)) warnings_print_categories (flags);
warnings_print_categories (flags, stderr);
{ {
size_t l = strlen (message); size_t l = strlen (message);
if (l < 2 || message[l - 2] != ':' || message[l - 1] != ' ') if (l < 2 || message[l - 2] != ':' || message[l - 1] != ' ')
@@ -275,34 +116,29 @@ error_message (const location *loc, warnings flags, const char *prefix,
putc ('\n', stderr); putc ('\n', stderr);
fflush (stderr); fflush (stderr);
if (loc && feature_flag & feature_caret && !(flags & no_caret)) if (loc && feature_flag & feature_caret && !(flags & no_caret))
location_caret (*loc, stderr); location_caret (stderr, *loc);
} }
} }
fflush (stderr); fflush (stderr);
} }
/** Raise a complaint. That can be a fatal error, an error or just a /** Raise a complaint. That can be a fatal error, a complaint or just a
warning. */ warning. */
static inline void
static void
complains (const location *loc, warnings flags, const char *message, complains (const location *loc, warnings flags, const char *message,
va_list args) va_list args)
{ {
severity s = warning_severity (flags); const char* prefix =
flags & fatal ? _("fatal error")
: flags & (errors_flag | complaint) ? _("error")
: _("warning");
if ((flags & complaint) && complaint_status < status_complaint) if ((flags & complaint) && complaint_status < status_complaint)
complaint_status = status_complaint; complaint_status = status_complaint;
else if ((flags & (warnings_flag & errors_flag)) && ! complaint_status)
if (severity_warning <= s) complaint_status = status_warning_as_error;
{ if (flags & (warnings_flag | fatal | complaint))
const char* prefix = error_message (loc, flags, prefix, message, args);
s == severity_fatal ? _("fatal error")
: s == severity_error ? _("error")
: _("warning");
if (severity_error <= s && ! complaint_status)
complaint_status = status_warning_as_error;
error_message (loc, flags, prefix, message, args);
}
if (flags & fatal) if (flags & fatal)
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
} }
@@ -353,6 +189,7 @@ complain_args (location const *loc, warnings w, unsigned *indent,
complain (loc, fatal, "too many arguments for complains"); complain (loc, fatal, "too many arguments for complains");
break; break;
} }
} }
void void
@@ -367,13 +204,3 @@ deprecated_directive (location const *loc, char const *old, char const *upd)
_("deprecated directive: %s, use %s"), _("deprecated directive: %s, use %s"),
quote (old), quote_n (1, upd)); quote (old), quote_n (1, upd));
} }
void
duplicate_directive (char const *directive,
location first, location second)
{
unsigned i = 0;
complain (&second, complaint, _("only one %s allowed per rule"), directive);
i += SUB_INDENT;
complain_indent (&first, complaint, &i, _("previous declaration"));
}
+16 -68
View File
@@ -28,67 +28,15 @@
| --warnings. | | --warnings. |
`-------------*/ `-------------*/
/** The bits assigned to each warning type. */
typedef enum typedef enum
{ {
warning_midrule_values, /**< Unset or unused midrule values. */ Wnone = 0, /**< Issue no warnings. */
warning_yacc, /**< POSIXME. */ Wmidrule_values = 1 << 0, /**< Unset or unused midrule values. */
warning_conflicts_sr, /**< S/R conflicts. */ Wyacc = 1 << 1, /**< POSIXME. */
warning_conflicts_rr, /**< R/R conflicts. */ Wconflicts_sr = 1 << 2, /**< S/R conflicts. */
warning_empty_rule, /**< Implicitly empty rules. */ Wconflicts_rr = 1 << 3, /**< R/R conflicts. */
warning_deprecated, /**< Obsolete constructs. */ Wdeprecated = 1 << 4, /**< Obsolete constructs. */
warning_precedence, /**< Useless precedence and associativity. */ Wother = 1 << 5, /**< All other warnings. */
warning_other, /**< All other warnings. */
warnings_size /**< The number of warnings. Must be last. */
} warning_bit;
/** Whether -Werror was set. */
extern bool warnings_are_errors;
/** Decode a single argument from -W.
*
* \param arg the subarguments to decode.
* If null, then activate all the flags.
* \param no length of the potential "no-" prefix.
* Can be 0 or 3. If 3, negate the action of the subargument.
* \param err length of a potential "error=".
* Can be 0 or 6. If 6, treat the subargument as a CATEGORY.
*
* If VALUE != 0 then KEY sets flags and no-KEY clears them.
* If VALUE == 0 then KEY clears all flags from \c all and no-KEY sets all
* flags from \c all. Thus no-none = all and no-all = none.
*/
void warning_argmatch (char const *arg, size_t no, size_t err);
/** Decode a comma-separated list of arguments from -W.
*
* \param args comma separated list of effective subarguments to decode.
* If 0, then activate all the flags.
*/
void warnings_argmatch (char *args);
/*-----------.
| complain. |
`-----------*/
/** Initialize this module. */
void complain_init (void);
typedef enum
{
/**< Issue no warnings. */
Wnone = 0,
Wmidrule_values = 1 << warning_midrule_values,
Wyacc = 1 << warning_yacc,
Wconflicts_sr = 1 << warning_conflicts_sr,
Wconflicts_rr = 1 << warning_conflicts_rr,
Wdeprecated = 1 << warning_deprecated,
Wempty_rule = 1 << warning_empty_rule,
Wprecedence = 1 << warning_precedence,
Wother = 1 << warning_other,
Werror = 1 << 10, /** This bit is no longer used. */ Werror = 1 << 10, /** This bit is no longer used. */
@@ -98,13 +46,17 @@ typedef enum
no_caret = 1 << 14, /**< Do not display caret location. */ no_caret = 1 << 14, /**< Do not display caret location. */
/**< All above warnings. */ /**< All above warnings. */
Weverything = ~complaint & ~fatal & ~silent, Wall = ~complaint & ~fatal & ~silent
Wall = Weverything & ~Wyacc
} warnings; } warnings;
/** Whether the warnings of \a flags are all unset. /** What warnings are issued. */
(Never enabled, never disabled). */ extern warnings warnings_flag;
bool warning_is_unset (warnings flags);
/** What warnings are made errors. */
extern warnings errors_flag;
/** Display a "[-Wyacc]" like message on stderr. */
void warnings_print_categories (warnings warn_flags);
/** Make a complaint, with maybe a location. */ /** Make a complaint, with maybe a location. */
void complain (location const *loc, warnings flags, char const *message, ...) void complain (location const *loc, warnings flags, char const *message, ...)
@@ -124,10 +76,6 @@ void complain_indent (location const *loc, warnings flags, unsigned *indent,
void deprecated_directive (location const *loc, void deprecated_directive (location const *loc,
char const *obsolete, char const *updated); char const *obsolete, char const *updated);
/** Report a repeated directive for a rule. */
void duplicate_directive (char const *directive,
location first, location second);
/** Warnings treated as errors shouldn't stop the execution as regular errors /** Warnings treated as errors shouldn't stop the execution as regular errors
should (because due to their nature, it is safe to go on). Thus, there are should (because due to their nature, it is safe to go on). Thus, there are
three possible execution statuses. */ three possible execution statuses. */
+61 -82
View File
@@ -53,8 +53,7 @@ enum conflict_resolution
reduce_resolution, reduce_resolution,
left_resolution, left_resolution,
right_resolution, right_resolution,
nonassoc_resolution, nonassoc_resolution
uncomparable_resolution
}; };
@@ -91,7 +90,6 @@ log_resolution (rule *r, symbol_number token,
break; break;
case nonassoc_resolution: case nonassoc_resolution:
case uncomparable_resolution:
obstack_printf (&solved_conflicts_obstack, obstack_printf (&solved_conflicts_obstack,
_(" Conflict between rule %d and token %s" _(" Conflict between rule %d and token %s"
" resolved as an error"), " resolved as an error"),
@@ -106,7 +104,7 @@ log_resolution (rule *r, symbol_number token,
case shift_resolution: case shift_resolution:
obstack_printf (&solved_conflicts_obstack, obstack_printf (&solved_conflicts_obstack,
" (%s < %s)", " (%s < %s)",
r->prec->symbol->tag, r->prec->tag,
symbols[token]->tag); symbols[token]->tag);
break; break;
@@ -114,7 +112,7 @@ log_resolution (rule *r, symbol_number token,
obstack_printf (&solved_conflicts_obstack, obstack_printf (&solved_conflicts_obstack,
" (%s < %s)", " (%s < %s)",
symbols[token]->tag, symbols[token]->tag,
r->prec->symbol->tag); r->prec->tag);
break; break;
case left_resolution: case left_resolution:
@@ -134,12 +132,6 @@ log_resolution (rule *r, symbol_number token,
" (%%nonassoc %s)", " (%%nonassoc %s)",
symbols[token]->tag); symbols[token]->tag);
break; break;
case uncomparable_resolution:
obstack_printf (&solved_conflicts_obstack,
" (%s uncomparable with %s)",
r->prec->symbol->tag,
symbols[token]->tag);
break;
} }
obstack_sgrow (&solved_conflicts_obstack, ".\n"); obstack_sgrow (&solved_conflicts_obstack, ".\n");
@@ -169,7 +161,6 @@ log_resolution (rule *r, symbol_number token,
xml_escape (symbols[token]->tag)); xml_escape (symbols[token]->tag));
break; break;
case uncomparable_resolution:
case nonassoc_resolution: case nonassoc_resolution:
obstack_printf (&solved_conflicts_xml_obstack, obstack_printf (&solved_conflicts_xml_obstack,
" <resolution rule=\"%d\" symbol=\"%s\"" " <resolution rule=\"%d\" symbol=\"%s\""
@@ -185,7 +176,7 @@ log_resolution (rule *r, symbol_number token,
case shift_resolution: case shift_resolution:
obstack_printf (&solved_conflicts_xml_obstack, obstack_printf (&solved_conflicts_xml_obstack,
"%s &lt; %s", "%s &lt; %s",
xml_escape_n (0, r->prec->symbol->tag), xml_escape_n (0, r->prec->tag),
xml_escape_n (1, symbols[token]->tag)); xml_escape_n (1, symbols[token]->tag));
break; break;
@@ -193,7 +184,7 @@ log_resolution (rule *r, symbol_number token,
obstack_printf (&solved_conflicts_xml_obstack, obstack_printf (&solved_conflicts_xml_obstack,
"%s &lt; %s", "%s &lt; %s",
xml_escape_n (0, symbols[token]->tag), xml_escape_n (0, symbols[token]->tag),
xml_escape_n (1, r->prec->symbol->tag)); xml_escape_n (1, r->prec->tag));
break; break;
case left_resolution: case left_resolution:
@@ -212,13 +203,7 @@ log_resolution (rule *r, symbol_number token,
obstack_printf (&solved_conflicts_xml_obstack, obstack_printf (&solved_conflicts_xml_obstack,
"%%nonassoc %s", "%%nonassoc %s",
xml_escape (symbols[token]->tag)); xml_escape (symbols[token]->tag));
break; break;
case uncomparable_resolution:
obstack_printf (&solved_conflicts_xml_obstack,
"%s uncomparable with %s",
xml_escape_n (0, symbols[token]->tag),
xml_escape_n (1, r->prec->symbol->tag));
break;
} }
obstack_sgrow (&solved_conflicts_xml_obstack, "</resolution>\n"); obstack_sgrow (&solved_conflicts_xml_obstack, "</resolution>\n");
@@ -258,6 +243,7 @@ flush_reduce (bitset lookahead_tokens, int token)
bitset_reset (lookahead_tokens, token); bitset_reset (lookahead_tokens, token);
} }
/*------------------------------------------------------------------. /*------------------------------------------------------------------.
| Attempt to resolve shift-reduce conflict for one rule by means of | | Attempt to resolve shift-reduce conflict for one rule by means of |
| precedence declarations. It has already been checked that the | | precedence declarations. It has already been checked that the |
@@ -277,73 +263,66 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
reductions *reds = s->reductions; reductions *reds = s->reductions;
/* Find the rule to reduce by to get precedence of reduction. */ /* Find the rule to reduce by to get precedence of reduction. */
rule *redrule = reds->rules[ruleno]; rule *redrule = reds->rules[ruleno];
prec_node *redprecsym = redrule->prec->prec_node; int redprec = redrule->prec->prec;
bitset lookahead_tokens = reds->lookahead_tokens[ruleno]; bitset lookahead_tokens = reds->lookahead_tokens[ruleno];
for (i = 0; i < ntokens; i++) for (i = 0; i < ntokens; i++)
if (bitset_test (lookahead_tokens, i) if (bitset_test (lookahead_tokens, i)
&& bitset_test (lookahead_set, i)) && bitset_test (lookahead_set, i)
&& symbols[i]->prec)
{ {
if (redprecsym && symbols[i]->content->prec_node) /* Shift-reduce conflict occurs for token number i
and it has a precedence.
The precedence of shifting is that of token i. */
if (symbols[i]->prec < redprec)
{ {
/* Shift-reduce conflict occurs for token number i register_precedence (redrule->prec->number, i);
and it has a precedence. log_resolution (redrule, i, reduce_resolution);
The precedence of shifting is that of token i. */ flush_shift (s, i);
if (is_prec_superior (redprecsym, symbols[i]->content->prec_node)) }
{ else if (symbols[i]->prec > redprec)
register_precedence (redrule->prec->number, i); {
log_resolution (redrule, i, reduce_resolution); register_precedence (i, redrule->prec->number);
flush_shift (s, i); log_resolution (redrule, i, shift_resolution);
} flush_reduce (lookahead_tokens, i);
else if (is_prec_superior (symbols[i]->content->prec_node,
redprecsym))
{
register_precedence (i, redrule->prec->number);
log_resolution (redrule, i, shift_resolution);
flush_reduce (lookahead_tokens, i);
}
else if (is_prec_equal (redprecsym, symbols[i]->content->prec_node))
/* Matching precedence levels.
For non-defined associativity, keep both: unexpected
associativity conflict.
For left associativity, keep only the reduction.
For right associativity, keep only the shift.
For nonassociativity, keep neither. */
switch (symbols[i]->content->prec_node->assoc)
{
case undef_assoc:
break;
case precedence_assoc:
break;
case right_assoc:
register_assoc (i, redrule->prec->number);
log_resolution (redrule, i, right_resolution);
flush_reduce (lookahead_tokens, i);
break;
case left_assoc:
register_assoc (i, redrule->prec->number);
log_resolution (redrule, i, left_resolution);
flush_shift (s, i);
break;
case non_assoc:
register_assoc (i, redrule->prec->number);
log_resolution (redrule, i, nonassoc_resolution);
flush_shift (s, i);
flush_reduce (lookahead_tokens, i);
/* Record an explicit error for this token. */
errors[(*nerrs)++] = symbols[i];
break;
}
else
log_resolution (redrule, i, uncomparable_resolution);
} }
else else
log_resolution (redrule, i, uncomparable_resolution); /* Matching precedence levels.
For non-defined associativity, keep both: unexpected
associativity conflict.
For left associativity, keep only the reduction.
For right associativity, keep only the shift.
For nonassociativity, keep neither. */
switch (symbols[i]->assoc)
{
case undef_assoc:
abort ();
case precedence_assoc:
break;
case right_assoc:
register_assoc (i, redrule->prec->number);
log_resolution (redrule, i, right_resolution);
flush_reduce (lookahead_tokens, i);
break;
case left_assoc:
register_assoc (i, redrule->prec->number);
log_resolution (redrule, i, left_resolution);
flush_shift (s, i);
break;
case non_assoc:
register_assoc (i, redrule->prec->number);
log_resolution (redrule, i, nonassoc_resolution);
flush_shift (s, i);
flush_reduce (lookahead_tokens, i);
/* Record an explicit error for this token. */
errors[(*nerrs)++] = symbols[i];
break;
}
} }
} }
@@ -375,7 +354,7 @@ set_conflicts (state *s, symbol **errors)
check for shift-reduce conflict, and try to resolve using check for shift-reduce conflict, and try to resolve using
precedence. */ precedence. */
for (i = 0; i < reds->num; ++i) for (i = 0; i < reds->num; ++i)
if (reds->rules[i]->prec /* && reds->rules[i]->prec->prec */ if (reds->rules[i]->prec && reds->rules[i]->prec->prec
&& !bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set)) && !bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set))
resolve_sr_conflict (s, i, errors, &nerrs); resolve_sr_conflict (s, i, errors, &nerrs);
@@ -424,7 +403,7 @@ conflicts_solve (void)
set_conflicts (states[i], errors); set_conflicts (states[i], errors);
/* For uniformity of the code, make sure all the states have a valid /* For uniformity of the code, make sure all the states have a valid
'errs' member. */ `errs' member. */
if (!states[i]->errs) if (!states[i]->errs)
states[i]->errs = errs_new (0, 0); states[i]->errs = errs_new (0, 0);
} }
+13 -13
View File
@@ -34,7 +34,7 @@
#include "getargs.h" #include "getargs.h"
#include "gram.h" #include "gram.h"
/* Initializing some values below (such SPEC_NAME_PREFIX to 'yy') is /* Initializing some values below (such SPEC_NAME_PREFIX to `yy') is
tempting, but don't do that: for the time being our handling of the tempting, but don't do that: for the time being our handling of the
%directive vs --option leaves precedence to the options by deciding %directive vs --option leaves precedence to the options by deciding
that if a %directive sets a variable which is really set (i.e., not that if a %directive sets a variable which is really set (i.e., not
@@ -58,20 +58,20 @@ uniqstr grammar_file = NULL;
uniqstr current_file = NULL; uniqstr current_file = NULL;
/* If --output=dir/foo.c was specified, /* If --output=dir/foo.c was specified,
DIR_PREFIX is 'dir/' and ALL_BUT_EXT and ALL_BUT_TAB_EXT are 'dir/foo'. DIR_PREFIX is `dir/' and ALL_BUT_EXT and ALL_BUT_TAB_EXT are `dir/foo'.
If --output=dir/foo.tab.c was specified, DIR_PREFIX is 'dir/', If --output=dir/foo.tab.c was specified, DIR_PREFIX is `dir/',
ALL_BUT_EXT is 'dir/foo.tab', and ALL_BUT_TAB_EXT is 'dir/foo'. ALL_BUT_EXT is `dir/foo.tab', and ALL_BUT_TAB_EXT is `dir/foo'.
If --output was not specified but --file-prefix=dir/foo was specified, If --output was not specified but --file-prefix=dir/foo was specified,
ALL_BUT_EXT = 'foo.tab' and ALL_BUT_TAB_EXT = 'foo'. ALL_BUT_EXT = `foo.tab' and ALL_BUT_TAB_EXT = `foo'.
If neither --output nor --file was specified but the input grammar If neither --output nor --file was specified but the input grammar
is name dir/foo.y, ALL_BUT_EXT and ALL_BUT_TAB_EXT are 'foo'. is name dir/foo.y, ALL_BUT_EXT and ALL_BUT_TAB_EXT are `foo'.
If neither --output nor --file was specified, DIR_PREFIX is the If neither --output nor --file was specified, DIR_PREFIX is the
empty string (meaning the current directory); otherwise it is empty string (meaning the current directory); otherwise it is
'dir/'. */ `dir/'. */
char *all_but_ext; char *all_but_ext;
static char *all_but_tab_ext; static char *all_but_tab_ext;
@@ -79,7 +79,7 @@ char *dir_prefix;
/* C source file extension (the parser source). */ /* C source file extension (the parser source). */
static char *src_extension = NULL; static char *src_extension = NULL;
/* Header file extension (if option '`-d'' is specified). */ /* Header file extension (if option ``-d'' is specified). */
static char *header_extension = NULL; static char *header_extension = NULL;
/*-----------------------------------------------------------------. /*-----------------------------------------------------------------.
@@ -191,7 +191,7 @@ compute_exts_from_src (const char *ext)
*EXT points to the last period in the basename, or NULL if none. *EXT points to the last period in the basename, or NULL if none.
If there is no *EXT, *TAB is NULL. Otherwise, *TAB points to If there is no *EXT, *TAB is NULL. Otherwise, *TAB points to
'.tab' or '_tab' if present right before *EXT, or is NULL. *TAB `.tab' or `_tab' if present right before *EXT, or is NULL. *TAB
cannot be equal to *BASE. cannot be equal to *BASE.
None are allocated, they are simply pointers to parts of FILE_NAME. None are allocated, they are simply pointers to parts of FILE_NAME.
@@ -222,7 +222,7 @@ file_name_split (const char *file_name,
*ext = strrchr (*base, '.'); *ext = strrchr (*base, '.');
*tab = NULL; *tab = NULL;
/* If there is an extension, check if there is a '.tab' part right /* If there is an extension, check if there is a `.tab' part right
before. */ before. */
if (*ext) if (*ext)
{ {
@@ -270,7 +270,7 @@ compute_file_name_parts (void)
if (spec_file_prefix) if (spec_file_prefix)
{ {
/* If --file-prefix=foo was specified, ALL_BUT_TAB_EXT = 'foo'. */ /* If --file-prefix=foo was specified, ALL_BUT_TAB_EXT = `foo'. */
dir_prefix = dir_prefix =
xstrndup (spec_file_prefix, xstrndup (spec_file_prefix,
last_component (spec_file_prefix) - spec_file_prefix); last_component (spec_file_prefix) - spec_file_prefix);
@@ -278,14 +278,14 @@ compute_file_name_parts (void)
} }
else if (yacc_flag) else if (yacc_flag)
{ {
/* If --yacc, then the output is 'y.tab.c'. */ /* If --yacc, then the output is `y.tab.c'. */
dir_prefix = xstrdup (""); dir_prefix = xstrdup ("");
all_but_tab_ext = xstrdup ("y"); all_but_tab_ext = xstrdup ("y");
} }
else else
{ {
/* Otherwise, ALL_BUT_TAB_EXT is computed from the input /* Otherwise, ALL_BUT_TAB_EXT is computed from the input
grammar: 'foo/bar.yy' => 'bar'. */ grammar: `foo/bar.yy' => `bar'. */
dir_prefix = xstrdup (""); dir_prefix = xstrdup ("");
all_but_tab_ext = all_but_tab_ext =
xstrndup (base, (strlen (base) - (ext ? strlen (ext) : 0))); xstrndup (base, (strlen (base) - (ext ? strlen (ext) : 0)));
+109 -64
View File
@@ -61,6 +61,7 @@ int skeleton_prio = default_prio;
const char *skeleton = NULL; const char *skeleton = NULL;
int language_prio = default_prio; int language_prio = default_prio;
struct bison_language const *language = &valid_languages[0]; struct bison_language const *language = &valid_languages[0];
const char *include = NULL;
/** Decode an option's key. /** Decode an option's key.
* *
@@ -73,6 +74,8 @@ struct bison_language const *language = &valid_languages[0];
* If null, then activate all the flags. * If null, then activate all the flags.
* \param no length of the potential "no-" prefix. * \param no length of the potential "no-" prefix.
* Can be 0 or 3. If 3, negate the action of the subargument. * Can be 0 or 3. If 3, negate the action of the subargument.
* \param err length of a potential "error=".
* Can be 0 or 6. If 6, treat the subargument as a CATEGORY
* *
* If VALUE != 0 then KEY sets flags and no-KEY clears them. * If VALUE != 0 then KEY sets flags and no-KEY clears them.
* If VALUE == 0 then KEY clears all flags from \c all and no-KEY sets all * If VALUE == 0 then KEY clears all flags from \c all and no-KEY sets all
@@ -81,23 +84,36 @@ struct bison_language const *language = &valid_languages[0];
static void static void
flag_argmatch (const char *option, flag_argmatch (const char *option,
const char * const keys[], const int values[], const char * const keys[], const int values[],
int all, int *flags, char *arg, size_t no) int all, int *flags, char *arg, size_t no, size_t err)
{ {
int value = XARGMATCH (option, arg + no, keys, values); int value = 0;
if (!err || arg[no + err++] != '\0')
value = XARGMATCH (option, arg + no + err, keys, values);
/* -rnone == -rno-all, and -rno-none == -rall. */ if (value)
if (!value)
{ {
value = all; if (no)
no = !no; *flags &= ~value;
else
{
if (err)
warnings_flag |= value;
*flags |= value;
}
} }
if (no)
*flags &= ~value;
else else
*flags |= value; {
/* With a simpler 'if (no)' version, -Werror means -Werror=all
(or rather, -Werror=no-none, but that syntax is invalid).
The difference is:
- Werror activates all errors, but not the warnings
- Werror=all activates errors, and all warnings */
if (no ? !err : err)
*flags |= all;
else
*flags &= ~all;
}
} }
/** Decode an option's set of keys. /** Decode an option's set of keys.
* *
* \param option option being decoded. * \param option option being decoded.
@@ -117,14 +133,16 @@ flags_argmatch (const char *option,
for (args = strtok (args, ","); args; args = strtok (NULL, ",")) for (args = strtok (args, ","); args; args = strtok (NULL, ","))
{ {
size_t no = STRPREFIX_LIT ("no-", args) ? 3 : 0; size_t no = STRPREFIX_LIT ("no-", args) ? 3 : 0;
size_t err = STRPREFIX_LIT ("error", args + no) ? 5 : 0;
flag_argmatch (option, keys, flag_argmatch (option, keys,
values, all, flags, args, no); values, all, err ? &errors_flag : flags,
args, no, err);
} }
else else
*flags |= all; *flags |= all;
} }
/** Decode a set of sub arguments. /** Decode a set of sub arguments.
* *
* \param FlagName the flag familly to update. * \param FlagName the flag familly to update.
@@ -178,6 +196,8 @@ ARGMATCH_VERIFY (report_args, report_types);
static const char * const trace_args[] = static const char * const trace_args[] =
{ {
/* In a series of synonyms, present the most meaningful first, so
that argmatch_valid be more readable. */
"none - no traces", "none - no traces",
"scan - grammar scanner traces", "scan - grammar scanner traces",
"parse - grammar parser traces", "parse - grammar parser traces",
@@ -218,6 +238,41 @@ static const int trace_types[] =
ARGMATCH_VERIFY (trace_args, trace_types); ARGMATCH_VERIFY (trace_args, trace_types);
/*------------------------.
| --warnings's handling. |
`------------------------*/
static const char * const warnings_args[] =
{
/* In a series of synonyms, present the most meaningful first, so
that argmatch_valid be more readable. */
"none - no warnings",
"midrule-values - unset or unused midrule values",
"yacc - incompatibilities with POSIX Yacc",
"conflicts-sr - S/R conflicts",
"conflicts-rr - R/R conflicts",
"deprecated - obsolete constructs",
"other - all other warnings",
"all - all of the above",
"error - warnings are errors",
0
};
static const int warnings_types[] =
{
Wnone,
Wmidrule_values,
Wyacc,
Wconflicts_sr,
Wconflicts_rr,
Wdeprecated,
Wother,
Wall,
Werror
};
ARGMATCH_VERIFY (warnings_args, warnings_types);
/*-----------------------. /*-----------------------.
| --feature's handling. | | --feature's handling. |
`-----------------------*/ `-----------------------*/
@@ -249,7 +304,7 @@ static void
usage (int status) usage (int status)
{ {
if (status != 0) if (status != 0)
fprintf (stderr, _("Try '%s --help' for more information.\n"), fprintf (stderr, _("Try `%s --help' for more information.\n"),
program_name); program_name);
else else
{ {
@@ -291,7 +346,7 @@ Parser:\n\
-L, --language=LANGUAGE specify the output programming language\n\ -L, --language=LANGUAGE specify the output programming language\n\
-S, --skeleton=FILE specify the skeleton to use\n\ -S, --skeleton=FILE specify the skeleton to use\n\
-t, --debug instrument the parser for tracing\n\ -t, --debug instrument the parser for tracing\n\
same as '-Dparse.trace'\n\ same as `-Dparse.trace'\n\
--locations enable location support\n\ --locations enable location support\n\
-D, --define=NAME[=VALUE] similar to '%define NAME \"VALUE\"'\n\ -D, --define=NAME[=VALUE] similar to '%define NAME \"VALUE\"'\n\
-F, --force-define=NAME[=VALUE] override '%define NAME \"VALUE\"'\n\ -F, --force-define=NAME[=VALUE] override '%define NAME \"VALUE\"'\n\
@@ -310,7 +365,7 @@ Output:\n\
-d likewise but cannot specify FILE (for POSIX Yacc)\n\ -d likewise but cannot specify FILE (for POSIX Yacc)\n\
-r, --report=THINGS also produce details on the automaton\n\ -r, --report=THINGS also produce details on the automaton\n\
--report-file=FILE write report to FILE\n\ --report-file=FILE write report to FILE\n\
-v, --verbose same as '--report=state'\n\ -v, --verbose same as `--report=state'\n\
-b, --file-prefix=PREFIX specify a PREFIX for output files\n\ -b, --file-prefix=PREFIX specify a PREFIX for output files\n\
-o, --output=FILE leave output to FILE\n\ -o, --output=FILE leave output to FILE\n\
-g, --graph[=FILE] also output a graph of the automaton\n\ -g, --graph[=FILE] also output a graph of the automaton\n\
@@ -321,37 +376,35 @@ Output:\n\
fputs (_("\ fputs (_("\
Warning categories include:\n\ Warning categories include:\n\
'midrule-values' unset or unused midrule values\n\ `midrule-values' unset or unused midrule values\n\
'yacc' incompatibilities with POSIX Yacc\n\ `yacc' incompatibilities with POSIX Yacc\n\
'conflicts-sr' S/R conflicts (enabled by default)\n\ `conflicts-sr' S/R conflicts (enabled by default)\n\
'conflicts-rr' R/R conflicts (enabled by default)\n\ `conflicts-rr' R/R conflicts (enabled by default)\n\
'deprecated' obsolete constructs\n\ `deprecated' obsolete constructs\n\
'empty-rule' empty rules without %empty\n\ `other' all other warnings (enabled by default)\n\
'precedence' useless precedence and associativity\n\ `all' all the warnings\n\
'other' all other warnings (enabled by default)\n\ `no-CATEGORY' turn off warnings in CATEGORY\n\
'all' all the warnings except 'yacc'\n\ `none' turn off all the warnings\n\
'no-CATEGORY' turn off warnings in CATEGORY\n\ `error[=CATEGORY]' treat warnings as errors\n\
'none' turn off all the warnings\n\
'error[=CATEGORY]' treat warnings as errors\n\
"), stdout); "), stdout);
putc ('\n', stdout); putc ('\n', stdout);
fputs (_("\ fputs (_("\
THINGS is a list of comma separated words that can include:\n\ THINGS is a list of comma separated words that can include:\n\
'state' describe the states\n\ `state' describe the states\n\
'itemset' complete the core item sets with their closure\n\ `itemset' complete the core item sets with their closure\n\
'lookahead' explicitly associate lookahead tokens to items\n\ `lookahead' explicitly associate lookahead tokens to items\n\
'solved' describe shift/reduce conflicts solving\n\ `solved' describe shift/reduce conflicts solving\n\
'all' include all the above information\n\ `all' include all the above information\n\
'none' disable the report\n\ `none' disable the report\n\
"), stdout); "), stdout);
putc ('\n', stdout); putc ('\n', stdout);
fputs (_("\ fputs (_("\
FEATURE is a list of comma separated words that can include:\n\ FEATURE is a list of comma separated words that can include:\n\
'caret' show errors with carets\n\ `caret' show errors with carets\n\
'all' all of the above\n\ `all' all of the above\n\
'none' disable all of the above\n\ `none' disable all of the above\n\
"), stdout); "), stdout);
putc ('\n', stdout); putc ('\n', stdout);
@@ -464,10 +517,12 @@ static char const short_options[] =
"b:" "b:"
"d" "d"
"f::" "f::"
"e"
"g::" "g::"
"h" "h"
"k" "k"
"l" "l"
"n"
"o:" "o:"
"p:" "p:"
"r:" "r:"
@@ -497,6 +552,7 @@ static struct option const long_options[] =
/* Parser. */ /* Parser. */
{ "name-prefix", required_argument, 0, 'p' }, { "name-prefix", required_argument, 0, 'p' },
{ "include", required_argument, 0, 'I' },
/* Output. */ /* Output. */
{ "file-prefix", required_argument, 0, 'b' }, { "file-prefix", required_argument, 0, 'b' },
@@ -525,6 +581,7 @@ static struct option const long_options[] =
{ "force-define", required_argument, 0, 'F' }, { "force-define", required_argument, 0, 'F' },
{ "locations", no_argument, 0, LOCATIONS_OPTION }, { "locations", no_argument, 0, LOCATIONS_OPTION },
{ "no-lines", no_argument, 0, 'l' }, { "no-lines", no_argument, 0, 'l' },
{ "raw", no_argument, 0, 0 },
{ "skeleton", required_argument, 0, 'S' }, { "skeleton", required_argument, 0, 'S' },
{ "language", required_argument, 0, 'L' }, { "language", required_argument, 0, 'L' },
{ "token-table", no_argument, 0, 'k' }, { "token-table", no_argument, 0, 'k' },
@@ -533,7 +590,7 @@ static struct option const long_options[] =
}; };
/* Under DOS, there is no difference on the case. This can be /* Under DOS, there is no difference on the case. This can be
troublesome when looking for '.tab' etc. */ troublesome when looking for `.tab' etc. */
#ifdef MSDOS #ifdef MSDOS
# define AS_FILE_NAME(File) (strlwr (File), (File)) # define AS_FILE_NAME(File) (strlwr (File), (File))
#else #else
@@ -569,36 +626,24 @@ getargs (int argc, char *argv[])
/* Certain long options cause getopt_long to return 0. */ /* Certain long options cause getopt_long to return 0. */
break; break;
case 'D': /* -DNAME[=(VALUE|"VALUE"|{VALUE})]. */ case 'D': /* -DNAME[=VALUE]. */
case 'F': /* -FNAME[=(VALUE|"VALUE"|{VALUE})]. */ case 'F': /* -FNAME[=VALUE]. */
{ {
char *name = optarg; char* name = optarg;
char *value = strchr (optarg, '='); char* value = strchr (optarg, '=');
muscle_kind kind = muscle_keyword;
if (value) if (value)
{ *value++ = 0;
char *end = value + strlen (value) - 1;
*value++ = 0;
if (*value == '{' && *end == '}')
{
kind = muscle_code;
++value;
*end = 0;
}
else if (*value == '"' && *end == '"')
{
kind = muscle_string;
++value;
*end = 0;
}
}
muscle_percent_define_insert (name, command_line_location (), muscle_percent_define_insert (name, command_line_location (),
kind, value ? value : "", value ? value : "",
c == 'D' ? MUSCLE_PERCENT_DEFINE_D c == 'D' ? MUSCLE_PERCENT_DEFINE_D
: MUSCLE_PERCENT_DEFINE_F); : MUSCLE_PERCENT_DEFINE_F);
} }
break; break;
case 'I':
include = AS_FILE_NAME (optarg);
break;
case 'L': case 'L':
language_argmatch (optarg, command_line_prio, language_argmatch (optarg, command_line_prio,
command_line_location ()); command_line_location ());
@@ -622,7 +667,7 @@ getargs (int argc, char *argv[])
break; break;
case 'W': case 'W':
warnings_argmatch (optarg); FLAGS_ARGMATCH (warnings, optarg, Wall);
break; break;
case 'b': case 'b':
@@ -673,8 +718,7 @@ getargs (int argc, char *argv[])
case 't': case 't':
muscle_percent_define_insert ("parse.trace", muscle_percent_define_insert ("parse.trace",
command_line_location (), command_line_location (), "",
muscle_keyword, "",
MUSCLE_PERCENT_DEFINE_D); MUSCLE_PERCENT_DEFINE_D);
break; break;
@@ -692,7 +736,8 @@ getargs (int argc, char *argv[])
break; break;
case 'y': case 'y':
warning_argmatch ("error=yacc", 0, 6); warnings_flag |= Wyacc;
errors_flag |= Wyacc;
yacc_flag = true; yacc_flag = true;
break; break;
-1
View File
@@ -121,7 +121,6 @@ enum feature
/** What additional features to use. */ /** What additional features to use. */
extern int feature_flag; extern int feature_flag;
/** Process the command line arguments. /** Process the command line arguments.
* *
* \param argc size of \a argv * \param argc size of \a argv
+39 -18
View File
@@ -44,8 +44,6 @@ int nvars = 0;
symbol_number *token_translations = NULL; symbol_number *token_translations = NULL;
enum braces_state prec_braces = 0;
int max_user_token_number = 256; int max_user_token_number = 256;
bool bool
@@ -67,19 +65,19 @@ rule_useless_in_parser_p (rule const *r)
} }
void void
rule_lhs_print (rule const *r, sym_content const *previous_lhs, FILE *out) rule_lhs_print (rule const *r, symbol const *previous_lhs, FILE *out)
{ {
fprintf (out, " %3d ", r->number); fprintf (out, " %3d ", r->number);
if (previous_lhs != r->lhs) if (previous_lhs != r->lhs)
fprintf (out, "%s:", r->lhs->symbol->tag); fprintf (out, "%s:", r->lhs->tag);
else else
fprintf (out, "%*s|", (int) strlen (previous_lhs->symbol->tag), ""); fprintf (out, "%*s|", (int) strlen (previous_lhs->tag), "");
} }
void void
rule_lhs_print_xml (rule const *r, FILE *out, int level) rule_lhs_print_xml (rule const *r, FILE *out, int level)
{ {
xml_printf (out, level, "<lhs>%s</lhs>", r->lhs->symbol->tag); xml_printf (out, level, "<lhs>%s</lhs>", r->lhs->tag);
} }
size_t size_t
@@ -95,14 +93,16 @@ rule_rhs_length (rule const *r)
void void
rule_rhs_print (rule const *r, FILE *out) rule_rhs_print (rule const *r, FILE *out)
{ {
if (0 <= *r->rhs) if (*r->rhs >= 0)
{ {
item_number *rp; item_number *rp;
for (rp = r->rhs; *rp >= 0; rp++) for (rp = r->rhs; *rp >= 0; rp++)
fprintf (out, " %s", symbols[*rp]->tag); fprintf (out, " %s", symbols[*rp]->tag);
} }
else else
fputs (" %empty", out); {
fprintf (out, " /* %s */", _("empty"));
}
} }
static void static void
@@ -125,6 +125,13 @@ rule_rhs_print_xml (rule const *r, FILE *out, int level)
} }
} }
static void
rule_print (rule const *r, FILE *out)
{
fprintf (out, "%s:", r->lhs->tag);
rule_rhs_print (r, out);
}
void void
ritem_print (FILE *out) ritem_print (FILE *out)
{ {
@@ -160,7 +167,7 @@ grammar_rules_partial_print (FILE *out, const char *title,
{ {
rule_number r; rule_number r;
bool first = true; bool first = true;
sym_content *previous_lhs = NULL; symbol *previous_lhs = NULL;
/* rule # : LHS -> RHS */ /* rule # : LHS -> RHS */
for (r = 0; r < nrules + nuseless_productions; r++) for (r = 0; r < nrules + nuseless_productions; r++)
@@ -211,7 +218,7 @@ grammar_rules_print_xml (FILE *out, int level)
rules[r].number, usefulness); rules[r].number, usefulness);
if (rules[r].precsym) if (rules[r].precsym)
fprintf (out, " percent_prec=\"%s\"", fprintf (out, " percent_prec=\"%s\"",
xml_escape (rules[r].precsym->symbol->tag)); xml_escape (rules[r].precsym->tag));
fputs (">\n", out); fputs (">\n", out);
} }
rule_lhs_print_xml (&rules[r], out, level + 3); rule_lhs_print_xml (&rules[r], out, level + 3);
@@ -241,7 +248,7 @@ grammar_dump (FILE *out, const char *title)
for (i = ntokens; i < nsyms; i++) for (i = ntokens; i < nsyms; i++)
fprintf (out, "%5d %5d %5d %s\n", fprintf (out, "%5d %5d %5d %s\n",
i, i,
symbols[i]->content->prec, symbols[i]->content->prec_node->assoc, symbols[i]->prec, symbols[i]->assoc,
symbols[i]->tag); symbols[i]->tag);
fprintf (out, "\n\n"); fprintf (out, "\n\n");
} }
@@ -264,7 +271,7 @@ grammar_dump (FILE *out, const char *title)
fprintf (out, "%3d (%2d, %2d, %2d, %2u-%2u) %2d ->", fprintf (out, "%3d (%2d, %2d, %2d, %2u-%2u) %2d ->",
i, i,
rule_i->prec ? rule_i->prec->prec : 0, rule_i->prec ? rule_i->prec->prec : 0,
rule_i->prec ? rule_i->prec->prec_node->assoc : 0, rule_i->prec ? rule_i->prec->assoc : 0,
rule_i->useful, rule_i->useful,
rhs_itemno, rhs_itemno,
rhs_itemno + rhs_count - 1, rhs_itemno + rhs_count - 1,
@@ -282,8 +289,8 @@ grammar_dump (FILE *out, const char *title)
rule_number r; rule_number r;
for (r = 0; r < nrules + nuseless_productions; r++) for (r = 0; r < nrules + nuseless_productions; r++)
{ {
fprintf (out, "%-5d %s:", r, rules[r].lhs->symbol->tag); fprintf (out, "%-5d ", r);
rule_rhs_print (&rules[r], out); rule_print (&rules[r], out);
fprintf (out, "\n"); fprintf (out, "\n");
} }
} }
@@ -293,10 +300,24 @@ grammar_dump (FILE *out, const char *title)
void void
grammar_rules_useless_report (const char *message) grammar_rules_useless_report (const char *message)
{ {
rule_number r; warnings w = Wother;
for (r = 0; r < nrules ; ++r) if (warnings_flag & w)
if (!rules[r].useful) {
complain (&rules[r].location, Wother, "%s", message); rule_number r;
for (r = 0; r < nrules ; ++r)
if (!rules[r].useful)
{
if (feature_flag & feature_caret)
complain (&rules[r].location, w, "%s", message);
else
{
complain (&rules[r].location, w | silent, "%s: ", message);
rule_print (&rules[r], stderr);
warnings_print_categories (w);
fprintf (stderr, "\n");
}
}
}
} }
void void
+10 -22
View File
@@ -35,7 +35,7 @@
The rules receive rule numbers 1 to NRULES in the order they are The rules receive rule numbers 1 to NRULES in the order they are
written. More precisely Bison augments the grammar with the written. More precisely Bison augments the grammar with the
initial rule, '$accept: START-SYMBOL $end', which is numbered 1, initial rule, `$accept: START-SYMBOL $end', which is numbered 1,
all the user rules are 2, 3 etc. Each time a rule number is all the user rules are 2, 3 etc. Each time a rule number is
presented to the user, we subtract 1, so *displayed* rule numbers presented to the user, we subtract 1, so *displayed* rule numbers
are 0, 1, 2... are 0, 1, 2...
@@ -61,7 +61,7 @@
RULES[R].prec -- the symbol providing the precedence level of R. RULES[R].prec -- the symbol providing the precedence level of R.
RULES[R].precsym -- the symbol attached (via %prec) to give its RULES[R].precsym -- the symbol attached (via %prec) to give its
precedence to R. Of course, if set, it is equal to 'prec', but we precedence to R. Of course, if set, it is equal to `prec', but we
need to distinguish one from the other when reducing: a symbol used need to distinguish one from the other when reducing: a symbol used
in a %prec is not useless. in a %prec is not useless.
@@ -117,17 +117,6 @@ typedef int item_number;
extern item_number *ritem; extern item_number *ritem;
extern unsigned int nritems; extern unsigned int nritems;
enum braces_state
{
default_braces_state,
gprec_seen,
group_name_seen,
braces_seen
};
/* Marker for the lexer and parser, to correctly interpret braces. */
extern enum braces_state prec_braces;
/* There is weird relationship between OT1H item_number and OTOH /* There is weird relationship between OT1H item_number and OTOH
symbol_number and rule_number: we store the latter in symbol_number and rule_number: we store the latter in
item_number. symbol_number values are stored as-is, while item_number. symbol_number values are stored as-is, while
@@ -191,17 +180,17 @@ typedef struct
except if some rules are useless. */ except if some rules are useless. */
rule_number number; rule_number number;
sym_content *lhs; symbol *lhs;
item_number *rhs; item_number *rhs;
/* This symbol provides both the associativity, and the precedence. */ /* This symbol provides both the associativity, and the precedence. */
sym_content *prec; symbol *prec;
int dprec; int dprec;
int merger; int merger;
/* This symbol was attached to the rule via %prec. */ /* This symbol was attached to the rule via %prec. */
sym_content *precsym; symbol *precsym;
location location; location location;
bool useful; bool useful;
@@ -216,11 +205,11 @@ extern rule *rules;
/* A function that selects a rule. */ /* A function that selects a rule. */
typedef bool (*rule_filter) (rule const *); typedef bool (*rule_filter) (rule const *);
/* Return true IFF the rule has a 'number' smaller than NRULES. That is, it is /* Return true IFF the rule has a `number' smaller than NRULES. That is, it is
useful in the grammar. */ useful in the grammar. */
bool rule_useful_in_grammar_p (rule const *r); bool rule_useful_in_grammar_p (rule const *r);
/* Return true IFF the rule has a 'number' higher than NRULES. That is, it is /* Return true IFF the rule has a `number' higher than NRULES. That is, it is
useless in the grammar. */ useless in the grammar. */
bool rule_useless_in_grammar_p (rule const *r); bool rule_useless_in_grammar_p (rule const *r);
@@ -231,8 +220,7 @@ bool rule_useless_in_parser_p (rule const *r);
/* Print this rule's number and lhs on OUT. If a PREVIOUS_LHS was /* Print this rule's number and lhs on OUT. If a PREVIOUS_LHS was
already displayed (by a previous call for another rule), avoid already displayed (by a previous call for another rule), avoid
useless repetitions. */ useless repetitions. */
void rule_lhs_print (rule const *r, sym_content const *previous_lhs, void rule_lhs_print (rule const *r, symbol const *previous_lhs, FILE *out);
FILE *out);
void rule_lhs_print_xml (rule const *r, FILE *out, int level); void rule_lhs_print_xml (rule const *r, FILE *out, int level);
/* Return the length of the RHS. */ /* Return the length of the RHS. */
@@ -274,8 +262,8 @@ void grammar_rules_print_xml (FILE *out, int level);
void grammar_dump (FILE *out, const char *title); void grammar_dump (FILE *out, const char *title);
/* Report on STDERR the rules that are not flagged USEFUL, using the /* Report on STDERR the rules that are not flagged USEFUL, using the
MESSAGE (which can be 'rule useless in grammar' when invoked after grammar MESSAGE (which can be `rule useless in grammar' when invoked after grammar
reduction, or 'rule useless in parser due to conflicts' after conflicts reduction, or `rule useless in parser due to conflicts' after conflicts
were taken into account). */ were taken into account). */
void grammar_rules_useless_report (const char *message); void grammar_rules_useless_report (const char *message);
+1 -1
View File
@@ -93,7 +93,7 @@ no_reduce_bitset_init (state const *s, bitset *no_reduce_set)
bitset_set (*no_reduce_set, TRANSITION_SYMBOL (s->transitions, n)); bitset_set (*no_reduce_set, TRANSITION_SYMBOL (s->transitions, n));
for (n = 0; n < s->errs->num; ++n) for (n = 0; n < s->errs->num; ++n)
if (s->errs->symbols[n]) if (s->errs->symbols[n])
bitset_set (*no_reduce_set, s->errs->symbols[n]->content->number); bitset_set (*no_reduce_set, s->errs->symbols[n]->number);
} }
static void static void
+2 -2
View File
@@ -424,7 +424,7 @@ ielr_item_has_lookahead (state *s, symbol_number lhs, size_t item,
if (item_number_is_rule_number (ritem[s->items[item] - 2])) if (item_number_is_rule_number (ritem[s->items[item] - 2]))
{ {
state **predecessor; state **predecessor;
aver (lhs != accept->content->number); aver (lhs != accept->number);
for (predecessor = predecessors[s->number]; for (predecessor = predecessors[s->number];
*predecessor; *predecessor;
++predecessor) ++predecessor)
@@ -580,7 +580,7 @@ typedef struct state_list {
static void static void
ielr_compute_goto_follow_set (bitsetv follow_kernel_items, ielr_compute_goto_follow_set (bitsetv follow_kernel_items,
bitsetv always_follows, state_list *s, bitsetv always_follows, state_list *s,
sym_content *n, bitset follow_set) symbol *n, bitset follow_set)
{ {
goto_number n_goto = map_goto (s->lr0Isocore->state->number, n->number); goto_number n_goto = map_goto (s->lr0Isocore->state->number, n->number);
bitset_copy (follow_set, always_follows[n_goto]); bitset_copy (follow_set, always_follows[n_goto]);
+1 -1
View File
@@ -342,7 +342,7 @@ state_lookahead_tokens_count (state *s, bool default_reduction_only_for_accept)
/* We need a lookahead either to distinguish different reductions /* We need a lookahead either to distinguish different reductions
(i.e., there are two or more), or to distinguish a reduction from a (i.e., there are two or more), or to distinguish a reduction from a
shift. Otherwise, it is straightforward, and the state is shift. Otherwise, it is straightforward, and the state is
'consistent'. However, do not treat a state with any reductions as `consistent'. However, do not treat a state with any reductions as
consistent unless it is the accepting state (because there is never consistent unless it is the accepting state (because there is never
a lookahead token that makes sense there, and so no lookahead token a lookahead token that makes sense there, and so no lookahead token
should be read) if the user has otherwise disabled default should be read) if the user has otherwise disabled default
+5 -3
View File
@@ -96,8 +96,10 @@ location_compute (location *loc, boundary *cur, char const *token, size_t size)
} }
/* Output to OUT the location LOC.
Warning: it uses quotearg's slot 3. */
unsigned unsigned
location_print (location loc, FILE *out) location_print (FILE *out, location loc)
{ {
unsigned res = 0; unsigned res = 0;
int end_col = 0 != loc.end.column ? loc.end.column - 1 : 0; int end_col = 0 != loc.end.column ? loc.end.column - 1 : 0;
@@ -159,7 +161,7 @@ cleanup_caret ()
} }
void void
location_caret (location loc, FILE *out) location_caret (FILE *out, location loc)
{ {
/* FIXME: find a way to support multifile locations, and only open once each /* FIXME: find a way to support multifile locations, and only open once each
file. That would make the procedure future-proof. */ file. That would make the procedure future-proof. */
@@ -219,7 +221,7 @@ void
boundary_set_from_string (boundary *bound, char *loc_str) boundary_set_from_string (boundary *bound, char *loc_str)
{ {
/* Must search in reverse since the file name field may /* Must search in reverse since the file name field may
* contain '.' or ':'. */ * contain `.' or `:'. */
char *delim = strrchr (loc_str, '.'); char *delim = strrchr (loc_str, '.');
aver (delim); aver (delim);
*delim = '\0'; *delim = '\0';
+5 -10
View File
@@ -20,10 +20,6 @@
#ifndef LOCATION_H_ #ifndef LOCATION_H_
# define LOCATION_H_ # define LOCATION_H_
# include <stdbool.h>
# include <stdio.h>
# include <string.h> /* strcmp */
# include "uniqstr.h" # include "uniqstr.h"
/* A boundary between two characters. */ /* A boundary between two characters. */
@@ -102,17 +98,16 @@ extern location const empty_location;
void location_compute (location *loc, void location_compute (location *loc,
boundary *cur, char const *token, size_t size); boundary *cur, char const *token, size_t size);
/* Print location to file. /* Print location to file. Return number of actually printed
Return number of actually printed characters. characters. */
Warning: uses quotearg's slot 3. */ unsigned location_print (FILE *out, location loc);
unsigned location_print (location loc, FILE *out);
/* Free any allocated ressources and close any open file handles that are /* Free any allocated ressources and close any open file handles that are
left-over by the usage of location_caret. */ left-over by the usage of location_caret. */
void cleanup_caret (void); void cleanup_caret (void);
/* Output to OUT the line and caret corresponding to location LOC. */ /* Output to OUT the line and caret corresponding to location LOC. */
void location_caret (location loc, FILE *out); void location_caret (FILE *out, location loc);
/* Return -1, 0, 1, depending whether a is before, equal, or /* Return -1, 0, 1, depending whether a is before, equal, or
after b. */ after b. */
@@ -125,7 +120,7 @@ location_cmp (location a, location b)
return res; return res;
} }
/* LOC_STR must be formatted as 'file:line.column', it will be modified. */ /* LOC_STR must be formatted as `file:line.column', it will be modified. */
void boundary_set_from_string (boundary *bound, char *loc_str); void boundary_set_from_string (boundary *bound, char *loc_str);
#endif /* ! defined LOCATION_H_ */ #endif /* ! defined LOCATION_H_ */
+2 -1
View File
@@ -76,7 +76,6 @@ main (int argc, char *argv[])
uniqstrs_new (); uniqstrs_new ();
muscle_init (); muscle_init ();
complain_init ();
getargs (argc, argv); getargs (argc, argv);
@@ -147,6 +146,8 @@ main (int argc, char *argv[])
print_precedence_warnings (); print_precedence_warnings ();
print_assoc_warnings ();
/* Output file names. */ /* Output file names. */
compute_output_file_names (); compute_output_file_names ();
+160 -208
View File
@@ -28,31 +28,6 @@
#include "muscle-tab.h" #include "muscle-tab.h"
#include "quote.h" #include "quote.h"
muscle_kind
muscle_kind_new (char const *k)
{
if (STREQ (k, "code"))
return muscle_code;
else if (STREQ (k, "keyword"))
return muscle_keyword;
else if (STREQ (k, "string"))
return muscle_string;
aver (0);
}
char const *
muscle_kind_string (muscle_kind k)
{
switch (k)
{
case muscle_code: return "code";
case muscle_keyword: return "keyword";
case muscle_string: return "string";
}
aver (0);
}
/* A key-value pair, along with storage that can be reclaimed when /* A key-value pair, along with storage that can be reclaimed when
this pair is no longer needed. */ this pair is no longer needed. */
typedef struct typedef struct
@@ -60,21 +35,8 @@ typedef struct
char const *key; char const *key;
char const *value; char const *value;
char *storage; char *storage;
muscle_kind kind;
} muscle_entry; } muscle_entry;
/* The name of muscle for the %define variable VAR (corresponding to
FIELD, if defined). */
static uniqstr
muscle_name (char const *var, char const *field)
{
if (field)
return UNIQSTR_CONCAT ("percent_define_", field, "(", var, ")");
else
return UNIQSTR_CONCAT ("percent_define(", var, ")");
}
/* An obstack used to create some entries. */ /* An obstack used to create some entries. */
struct obstack muscle_obstack; struct obstack muscle_obstack;
@@ -98,18 +60,10 @@ hash_muscle (const void *x, size_t tablesize)
return hash_string (m->key, tablesize); return hash_string (m->key, tablesize);
} }
/* Create a fresh muscle name KEY, and insert in the hash table. */ /*-----------------------------------------------------------------.
static void * | Create the MUSCLE_TABLE, and initialize it with default values. |
muscle_entry_new (char const *key) | Also set up the MUSCLE_OBSTACK. |
{ `-----------------------------------------------------------------*/
muscle_entry *res = xmalloc (sizeof *res);
res->key = key;
res->value = NULL;
res->storage = NULL;
if (!hash_insert (muscle_table, res))
xalloc_die ();
return res;
}
static void static void
muscle_entry_free (void *entry) muscle_entry_free (void *entry)
@@ -133,6 +87,10 @@ muscle_init (void)
} }
/*------------------------------------------------------------.
| Free all the memory consumed by the muscle machinery only. |
`------------------------------------------------------------*/
void void
muscle_free (void) muscle_free (void)
{ {
@@ -140,64 +98,71 @@ muscle_free (void)
obstack_free (&muscle_obstack, NULL); obstack_free (&muscle_obstack, NULL);
} }
/* Look for the muscle named KEY. Return NULL if does not exist. */
static
muscle_entry *
muscle_lookup (char const *key)
{
muscle_entry probe;
probe.key = key;
return hash_lookup (muscle_table, &probe);
}
/*------------------------------------------------------------.
| Insert (KEY, VALUE). If KEY already existed, overwrite the |
| previous value. |
`------------------------------------------------------------*/
void void
muscle_insert (char const *key, char const *value) muscle_insert (char const *key, char const *value)
{ {
muscle_entry *entry = muscle_lookup (key); muscle_entry probe;
if (entry) muscle_entry *entry;
free (entry->storage);
probe.key = key;
entry = hash_lookup (muscle_table, &probe);
if (!entry)
{
/* First insertion in the hash. */
entry = xmalloc (sizeof *entry);
entry->key = key;
if (!hash_insert (muscle_table, entry))
xalloc_die ();
}
else else
/* First insertion in the hash. */ free (entry->storage);
entry = muscle_entry_new (key);
entry->value = value; entry->value = value;
entry->storage = NULL; entry->storage = NULL;
} }
/* Append VALUE to the current value of KEY. If KEY did not already /*-------------------------------------------------------------------.
exist, create it. Use MUSCLE_OBSTACK. De-allocate the previously | Append VALUE to the current value of KEY. If KEY did not already |
associated value. Copy VALUE and SEPARATOR. If VALUE does not end | exist, create it. Use MUSCLE_OBSTACK. De-allocate the previously |
with TERMINATOR, append one. */ | associated value. Copy VALUE and SEPARATOR. |
`-------------------------------------------------------------------*/
static void void
muscle_grow (const char *key, const char *val, muscle_grow (const char *key, const char *val, const char *separator)
const char *separator, const char *terminator)
{ {
muscle_entry *entry = muscle_lookup (key); muscle_entry probe;
size_t vals = strlen (val); muscle_entry *entry = NULL;
size_t terms = strlen (terminator);
if (entry) probe.key = key;
entry = hash_lookup (muscle_table, &probe);
if (!entry)
{ {
obstack_sgrow (&muscle_obstack, entry->value); /* First insertion in the hash. */
obstack_sgrow (&muscle_obstack, separator); entry = xmalloc (sizeof *entry);
free (entry->storage); entry->key = key;
if (!hash_insert (muscle_table, entry))
xalloc_die ();
entry->value = entry->storage = xstrdup (val);
} }
else else
entry = muscle_entry_new (key); {
/* Grow the current value. */
obstack_sgrow (&muscle_obstack, val); char *new_val;
obstack_printf (&muscle_obstack, "%s%s%s", entry->value, separator, val);
if (terms <= vals free (entry->storage);
&& STRNEQ (val + vals - terms, terminator)) new_val = obstack_finish0 (&muscle_obstack);
obstack_sgrow (&muscle_obstack, terminator); entry->value = entry->storage = xstrdup (new_val);
obstack_free (&muscle_obstack, new_val);
{ }
char *new_val = obstack_finish0 (&muscle_obstack);
entry->value = entry->storage = xstrdup (new_val);
obstack_free (&muscle_obstack, new_val);
}
} }
/*------------------------------------------------------------------. /*------------------------------------------------------------------.
@@ -214,7 +179,7 @@ muscle_syncline_grow (char const *key, location loc)
quotearg_style (c_quoting_style, loc.start.file)); quotearg_style (c_quoting_style, loc.start.file));
obstack_sgrow (&muscle_obstack, ")["); obstack_sgrow (&muscle_obstack, ")[");
extension = obstack_finish0 (&muscle_obstack); extension = obstack_finish0 (&muscle_obstack);
muscle_grow (key, extension, "", ""); muscle_grow (key, extension, "");
obstack_free (&muscle_obstack, extension); obstack_free (&muscle_obstack, extension);
} }
@@ -228,13 +193,12 @@ void
muscle_code_grow (const char *key, const char *val, location loc) muscle_code_grow (const char *key, const char *val, location loc)
{ {
muscle_syncline_grow (key, loc); muscle_syncline_grow (key, loc);
muscle_grow (key, val, "\n", "\n"); muscle_grow (key, val, "\n");
} }
void void muscle_pair_list_grow (const char *muscle,
muscle_pair_list_grow (const char *muscle, const char *a1, const char *a2)
const char *a1, const char *a2)
{ {
char *pair; char *pair;
obstack_sgrow (&muscle_obstack, "["); obstack_sgrow (&muscle_obstack, "[");
@@ -243,33 +207,54 @@ muscle_pair_list_grow (const char *muscle,
obstack_quote (&muscle_obstack, a2); obstack_quote (&muscle_obstack, a2);
obstack_sgrow (&muscle_obstack, "]"); obstack_sgrow (&muscle_obstack, "]");
pair = obstack_finish0 (&muscle_obstack); pair = obstack_finish0 (&muscle_obstack);
muscle_grow (muscle, pair, ",\n", ""); muscle_grow (muscle, pair, ",\n");
obstack_free (&muscle_obstack, pair); obstack_free (&muscle_obstack, pair);
} }
/*----------------------------------------------------------------------------.
| Find the value of muscle KEY. Unlike MUSCLE_FIND, this is always reliable |
| to determine whether KEY has a value. |
`----------------------------------------------------------------------------*/
char const * char const *
muscle_find_const (char const *key) muscle_find_const (char const *key)
{ {
muscle_entry *entry = muscle_lookup (key); muscle_entry probe;
return entry ? entry->value : NULL; muscle_entry *result = NULL;
probe.key = key;
result = hash_lookup (muscle_table, &probe);
if (result)
return result->value;
return NULL;
} }
/*----------------------------------------------------------------------------.
| Find the value of muscle KEY. Abort if muscle_insert was invoked more |
| recently than muscle_grow for KEY since muscle_find can't return a |
| char const *. |
`----------------------------------------------------------------------------*/
char * char *
muscle_find (char const *key) muscle_find (char const *key)
{ {
muscle_entry *entry = muscle_lookup (key); muscle_entry probe;
if (entry) muscle_entry *result = NULL;
probe.key = key;
result = hash_lookup (muscle_table, &probe);
if (result)
{ {
aver (entry->value == entry->storage); aver (result->value == result->storage);
return entry->storage; return result->storage;
} }
return NULL; return NULL;
} }
/* In the format 'file_name:line.column', append BOUND to MUSCLE. Use /* In the format `file_name:line.column', append BOUND to MUSCLE. Use
digraphs for special characters in the file name. */ digraphs for special characters in the file name. */
static void static void
@@ -280,12 +265,12 @@ muscle_boundary_grow (char const *key, boundary bound)
obstack_escape (&muscle_obstack, bound.file); obstack_escape (&muscle_obstack, bound.file);
obstack_printf (&muscle_obstack, ":%d.%d]]", bound.line, bound.column); obstack_printf (&muscle_obstack, ":%d.%d]]", bound.line, bound.column);
extension = obstack_finish0 (&muscle_obstack); extension = obstack_finish0 (&muscle_obstack);
muscle_grow (key, extension, "", ""); muscle_grow (key, extension, "");
obstack_free (&muscle_obstack, extension); obstack_free (&muscle_obstack, extension);
} }
/* In the format '[[file_name:line.column]], [[file_name:line.column]]', /* In the format `[[file_name:line.column]], [[file_name:line.column]]',
append LOC to MUSCLE. Use digraphs for special characters in each append LOC to MUSCLE. Use digraphs for special characters in each
file name. */ file name. */
@@ -293,7 +278,7 @@ static void
muscle_location_grow (char const *key, location loc) muscle_location_grow (char const *key, location loc)
{ {
muscle_boundary_grow (key, loc.start); muscle_boundary_grow (key, loc.start);
muscle_grow (key, "", ", ", ""); muscle_grow (key, "", ", ");
muscle_boundary_grow (key, loc.end); muscle_boundary_grow (key, loc.end);
} }
@@ -344,9 +329,10 @@ string_decode (char const *key)
/* Reverse of muscle_location_grow. */ /* Reverse of muscle_location_grow. */
static location static location
location_decode (char const *value) location_decode (char const *key)
{ {
location loc; location loc;
char const *value = muscle_find_const (key);
aver (value); aver (value);
aver (*value == '['); aver (*value == '[');
aver (*++value == '['); aver (*++value == '[');
@@ -391,11 +377,11 @@ void
muscle_user_name_list_grow (char const *key, char const *user_name, muscle_user_name_list_grow (char const *key, char const *user_name,
location loc) location loc)
{ {
muscle_grow (key, "[[[[", ",", ""); muscle_grow (key, "[[[[", ",");
muscle_grow (key, user_name, "", ""); muscle_grow (key, user_name, "");
muscle_grow (key, "]], ", "", ""); muscle_grow (key, "]], ", "");
muscle_location_grow (key, loc); muscle_location_grow (key, loc);
muscle_grow (key, "]]", "", ""); muscle_grow (key, "]]", "");
} }
@@ -489,17 +475,16 @@ muscle_percent_variable_update (char const *variable, location variable_loc,
void void
muscle_percent_define_insert (char const *var, location variable_loc, muscle_percent_define_insert (char const *var, location variable_loc,
muscle_kind kind,
char const *value, char const *value,
muscle_percent_define_how how) muscle_percent_define_how how)
{ {
/* Backward compatibility. */ /* Backward compatibility. */
char *variable = muscle_percent_variable_update (var, variable_loc, &value); char *variable = muscle_percent_variable_update (var, variable_loc, &value);
uniqstr name = muscle_name (variable, NULL); char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
uniqstr loc_name = muscle_name (variable, "loc"); char const *loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
uniqstr syncline_name = muscle_name (variable, "syncline"); char const *syncline_name =
uniqstr how_name = muscle_name (variable, "how"); UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
uniqstr kind_name = muscle_name (variable, "kind"); char const *how_name = UNIQSTR_CONCAT ("percent_define_how(", variable, ")");
/* Command-line options are processed before the grammar file. */ /* Command-line options are processed before the grammar file. */
if (how == MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE if (how == MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE
@@ -525,7 +510,6 @@ muscle_percent_define_insert (char const *var, location variable_loc,
muscle_user_name_list_grow ("percent_define_user_variables", variable, muscle_user_name_list_grow ("percent_define_user_variables", variable,
variable_loc); variable_loc);
MUSCLE_INSERT_INT (how_name, how); MUSCLE_INSERT_INT (how_name, how);
MUSCLE_INSERT_STRING (kind_name, muscle_kind_string (kind));
end: end:
free (variable); free (variable);
} }
@@ -536,120 +520,85 @@ void
muscle_percent_define_ensure (char const *variable, location loc, muscle_percent_define_ensure (char const *variable, location loc,
bool value) bool value)
{ {
uniqstr name = muscle_name (variable, NULL);
char const *val = value ? "" : "false"; char const *val = value ? "" : "false";
char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
/* Don't complain is VARIABLE is already defined, but be sure to set /* %pure-parser is deprecated in favor of `%define api.pure', so use
its value to VAL. */ `%define api.pure' in a backward-compatible manner here. First,
if (!muscle_find_const (name) don't complain if %pure-parser is specified multiple times. */
|| muscle_percent_define_flag_if (variable) != value) if (!muscle_find_const (name))
muscle_percent_define_insert (variable, loc, muscle_keyword, val, muscle_percent_define_insert (variable, loc, val,
MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
/* In all cases, use api.pure now so that the backend doesn't complain if
the skeleton ignores api.pure, but do warn now if there's a previous
conflicting definition from an actual %define. */
if (muscle_percent_define_flag_if (variable) != value)
muscle_percent_define_insert (variable, loc, val,
MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
}
/* Mark %define VARIABLE as used. */
static void
muscle_percent_define_use (char const *variable)
{
muscle_insert (muscle_name (variable, "bison_variables"), "");
}
/* The value of %define variable VARIABLE (corresponding to FIELD, if
defined). Do not register as used, but diagnose unset variables. */
static
char const *
muscle_percent_define_get_raw (char const *variable, char const *field)
{
uniqstr name = muscle_name (variable, field);
char const *res = muscle_find_const (name);
if (!res)
complain (NULL, fatal, _("%s: undefined %%define variable %s"),
"muscle_percent_define_get_raw", quote (variable));
return res;
} }
char * char *
muscle_percent_define_get (char const *variable) muscle_percent_define_get (char const *variable)
{ {
uniqstr name = muscle_name (variable, NULL); char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
char const *usage_name =
UNIQSTR_CONCAT ("percent_define_bison_variables(", variable, ")");
char *value = string_decode (name); char *value = string_decode (name);
if (!value) if (!value)
value = xstrdup (""); value = xstrdup ("");
muscle_percent_define_use (variable);
muscle_insert (usage_name, "");
return value; return value;
} }
/* The kind of VARIABLE. An error if undefined. */
static muscle_kind
muscle_percent_define_get_kind (char const *variable)
{
return muscle_kind_new (muscle_percent_define_get_raw (variable, "kind"));
}
/* Check the kind of VARIABLE. An error if undefined. */
static void
muscle_percent_define_check_kind (char const *variable, muscle_kind kind)
{
if (muscle_percent_define_get_kind (variable) != kind)
{
location loc = muscle_percent_define_get_loc (variable);
switch (kind)
{
case muscle_code:
complain (&loc, Wdeprecated,
"%%define variable '%s' requires '{...}' values",
variable);
break;
case muscle_keyword:
complain (&loc, Wdeprecated,
"%%define variable '%s' requires keyword values",
variable);
break;
case muscle_string:
complain (&loc, Wdeprecated,
"%%define variable '%s' requires '\"...\"' values",
variable);
break;
}
}
}
location location
muscle_percent_define_get_loc (char const *variable) muscle_percent_define_get_loc (char const *variable)
{ {
return location_decode (muscle_percent_define_get_raw (variable, "loc")); char const *loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
if (!muscle_find_const (loc_name))
complain (NULL, fatal, _("%s: undefined %%define variable %s"),
"muscle_percent_define_get_loc", quote (variable));
return location_decode (loc_name);
} }
char const * char const *
muscle_percent_define_get_syncline (char const *variable) muscle_percent_define_get_syncline (char const *variable)
{ {
return muscle_percent_define_get_raw (variable, "syncline"); char const *syncline_name =
UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
char const *syncline = muscle_find_const (syncline_name);
if (!syncline)
complain (NULL, fatal, _("%s: undefined %%define variable %s"),
"muscle_percent_define_get_syncline", quote (variable));
return syncline;
} }
bool bool
muscle_percent_define_ifdef (char const *variable) muscle_percent_define_ifdef (char const *variable)
{ {
if (muscle_find_const (muscle_name (variable, NULL))) char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
char const *usage_name =
UNIQSTR_CONCAT ("percent_define_bison_variables(", variable, ")");
char const *value = muscle_find_const (name);
if (value)
{ {
muscle_percent_define_use (variable); muscle_insert (usage_name, "");
return true; return true;
} }
else
return false; return false;
} }
bool bool
muscle_percent_define_flag_if (char const *variable) muscle_percent_define_flag_if (char const *variable)
{ {
uniqstr invalid_boolean_name = muscle_name (variable, "invalid_boolean"); char const *invalid_boolean_name =
UNIQSTR_CONCAT ("percent_define_invalid_boolean(", variable, ")");
bool result = false; bool result = false;
if (muscle_percent_define_ifdef (variable)) if (muscle_percent_define_ifdef (variable))
{ {
char *value = muscle_percent_define_get (variable); char *value = muscle_percent_define_get (variable);
muscle_percent_define_check_kind (variable, muscle_keyword);
if (value[0] == '\0' || STREQ (value, "true")) if (value[0] == '\0' || STREQ (value, "true"))
result = true; result = true;
else if (STREQ (value, "false")) else if (STREQ (value, "false"))
@@ -674,21 +623,20 @@ muscle_percent_define_flag_if (char const *variable)
void void
muscle_percent_define_default (char const *variable, char const *value) muscle_percent_define_default (char const *variable, char const *value)
{ {
uniqstr name = muscle_name (variable, NULL); char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
char const *loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
char const *syncline_name =
UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
if (!muscle_find_const (name)) if (!muscle_find_const (name))
{ {
location loc;
MUSCLE_INSERT_STRING (name, value); MUSCLE_INSERT_STRING (name, value);
MUSCLE_INSERT_STRING (muscle_name (variable, "kind"), "keyword"); loc.start.file = loc.end.file = "<default value>";
{ loc.start.line = loc.end.line = -1;
uniqstr loc_name = muscle_name (variable, "loc"); loc.start.column = loc.end.column = -1;
location loc; muscle_insert (loc_name, "");
loc.start.file = loc.end.file = "<default value>"; muscle_location_grow (loc_name, loc);
loc.start.line = loc.end.line = -1; muscle_insert (syncline_name, "");
loc.start.column = loc.end.column = -1;
muscle_insert (loc_name, "");
muscle_location_grow (loc_name, loc);
}
muscle_insert (muscle_name (variable, "syncline"), "");
} }
} }
@@ -698,9 +646,8 @@ muscle_percent_define_check_values (char const * const *values)
for (; *values; ++values) for (; *values; ++values)
{ {
char const * const *variablep = values; char const * const *variablep = values;
uniqstr name = muscle_name (*variablep, NULL); char const *name = UNIQSTR_CONCAT ("percent_define(", *variablep, ")");
char *value = string_decode (name); char *value = string_decode (name);
muscle_percent_define_check_kind (*variablep, muscle_keyword);
if (value) if (value)
{ {
for (++values; *values; ++values) for (++values; *values; ++values)
@@ -717,7 +664,7 @@ muscle_percent_define_check_values (char const * const *values)
quote (*variablep), quote_n (1, value)); quote (*variablep), quote_n (1, value));
i += SUB_INDENT; i += SUB_INDENT;
for (values = variablep + 1; *values; ++values) for (values = variablep + 1; *values; ++values)
complain_indent (&loc, complaint | no_caret | silent, &i, complain_indent (&loc, complaint | no_caret, &i,
_("accepted value: %s"), quote (*values)); _("accepted value: %s"), quote (*values));
} }
else else
@@ -764,6 +711,11 @@ muscle_m4_output_processor (void *entry, void *out)
} }
/*----------------------------------------------------------------.
| Output the definition of all the current muscles into a list of |
| m4_defines. |
`----------------------------------------------------------------*/
void void
muscles_m4_output (FILE *out) muscles_m4_output (FILE *out)
{ {
+18 -44
View File
@@ -24,41 +24,10 @@
# include "location.h" # include "location.h"
/* The kind of value associated to this muscle, depending on the
syntax of the value: keyword (no delimiter, e.g., true), string
(double quotes, e.g., "foo.h"), or code (braces, e.g., {int}). */
typedef enum
{
muscle_code,
muscle_keyword,
muscle_string
} muscle_kind;
/* Conversion from string. */
muscle_kind muscle_kind_new (char const *k);
/* Conversion to string. */
char const *muscle_kind_string (muscle_kind k);
/* Create the MUSCLE_TABLE, and initialize it with default values.
Also set up the MUSCLE_OBSTACK. */
void muscle_init (void); void muscle_init (void);
/* Insert (KEY, VALUE). If KEY already existed, overwrite the
previous value. Otherwise create as a muscle_string type. */
void muscle_insert (char const *key, char const *value); void muscle_insert (char const *key, char const *value);
/* Find the value of muscle KEY. Unlike MUSCLE_FIND, this is always
reliable to determine whether KEY has a value. */
char const *muscle_find_const (char const *key); char const *muscle_find_const (char const *key);
/* Find the value of muscle KEY. Abort if muscle_insert was invoked
more recently than muscle_grow for KEY since muscle_find can't
return a char const *. */
char *muscle_find (char const *key); char *muscle_find (char const *key);
/* Free all the memory consumed by the muscle machinery only. */
void muscle_free (void); void muscle_free (void);
@@ -78,14 +47,14 @@ extern struct obstack muscle_obstack;
} while (0) } while (0)
# define MUSCLE_INSERT_INT(Key, Value) \ # define MUSCLE_INSERT_INT(Key, Value) \
MUSCLE_INSERTF (Key, "%d", Value) MUSCLE_INSERTF(Key, "%d", Value)
# define MUSCLE_INSERT_LONG_INT(Key, Value) \ # define MUSCLE_INSERT_LONG_INT(Key, Value) \
MUSCLE_INSERTF (Key, "%ld", Value) MUSCLE_INSERTF(Key, "%ld", Value)
/* Key -> Value, but don't apply escaping to Value. */ /* Key -> Value, but don't apply escaping to Value. */
# define MUSCLE_INSERT_STRING_RAW(Key, Value) \ # define MUSCLE_INSERT_STRING_RAW(Key, Value) \
MUSCLE_INSERTF (Key, "%s", Value) MUSCLE_INSERTF(Key, "%s", Value)
/* Key -> Value, applying M4 escaping to Value. */ /* Key -> Value, applying M4 escaping to Value. */
# define MUSCLE_INSERT_STRING(Key, Value) \ # define MUSCLE_INSERT_STRING(Key, Value) \
@@ -94,14 +63,23 @@ extern struct obstack muscle_obstack;
muscle_insert (Key, obstack_finish0 (&muscle_obstack)); \ muscle_insert (Key, obstack_finish0 (&muscle_obstack)); \
} while (0) } while (0)
/* Key -> Value, applying C escaping to Value (and then M4). */
# define MUSCLE_INSERT_C_STRING(Key, Value) \ # define MUSCLE_INSERT_C_STRING(Key, Value) \
MUSCLE_INSERT_STRING (Key, quotearg_style (c_quoting_style, Value)) do { \
obstack_escape (&muscle_obstack, \
quotearg_style (c_quoting_style, Value)); \
muscle_insert (Key, obstack_finish0 (&muscle_obstack)); \
} while (0)
/* Append VALUE to the current value of KEY. If KEY did not already
exist, create it. Use MUSCLE_OBSTACK. De-allocate the previously
associated value. Copy VALUE and SEPARATOR. */
void muscle_grow (const char *key, const char *value, const char *separator);
/* Append VALUE to the current value of KEY, using muscle_grow. But /* Append VALUE to the current value of KEY, using muscle_grow. But
in addition, issue a synchronization line for the location LOC. in addition, issue a synchronization line for the location LOC. */
Be sure to append on a new line. */
void muscle_code_grow (const char *key, const char *value, location loc); void muscle_code_grow (const char *key, const char *value, location loc);
@@ -114,15 +92,14 @@ void muscle_pair_list_grow (const char *muscle,
/* Grow KEY for the occurrence of the name USER_NAME at LOC appropriately for /* Grow KEY for the occurrence of the name USER_NAME at LOC appropriately for
use with b4_check_user_names in ../data/bison.m4. USER_NAME is not escaped use with b4_check_user_names in ../data/bison.m4. USER_NAME is not escaped
with digraphs, so it must not contain '[' or ']'. */ with digraphs, so it must not contain `[' or `]'. */
void muscle_user_name_list_grow (char const *key, char const *user_name, void muscle_user_name_list_grow (char const *key, char const *user_name,
location loc); location loc);
/* Indicates whether a variable's value was specified with -D/--define, with /* Indicates whether a variable's value was specified with -D/--define, with
-F/--force-define, or in the grammar file. */ -F/--force-define, or in the grammar file. */
typedef enum { typedef enum {
MUSCLE_PERCENT_DEFINE_D = 0, MUSCLE_PERCENT_DEFINE_D = 0, MUSCLE_PERCENT_DEFINE_F,
MUSCLE_PERCENT_DEFINE_F,
MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE
} muscle_percent_define_how; } muscle_percent_define_how;
@@ -136,7 +113,6 @@ typedef enum {
this as a user occurrence of VARIABLE by invoking this as a user occurrence of VARIABLE by invoking
muscle_user_name_list_grow. */ muscle_user_name_list_grow. */
void muscle_percent_define_insert (char const *variable, location variable_loc, void muscle_percent_define_insert (char const *variable, location variable_loc,
muscle_kind kind,
char const *value, char const *value,
muscle_percent_define_how how); muscle_percent_define_how how);
@@ -210,8 +186,6 @@ void muscle_percent_define_check_values (char const * const *values);
void muscle_percent_code_grow (char const *qualifier, location qualifier_loc, void muscle_percent_code_grow (char const *qualifier, location qualifier_loc,
char const *code, location code_loc); char const *code, location code_loc);
/* Output the definition of all the current muscles into a list of
m4_defines. */
void muscles_m4_output (FILE *out); void muscles_m4_output (FILE *out);
#endif /* not MUSCLE_TAB_H_ */ #endif /* not MUSCLE_TAB_H_ */
+31 -32
View File
@@ -90,19 +90,20 @@ Name (char const *name, \
\ \
lmin = min; \ lmin = min; \
lmax = max; \ lmax = max; \
/* Build 'NAME_min' and 'NAME_max' in the obstack. */ \ /* Build `NAME_min' and `NAME_max' in the obstack. */ \
obstack_printf (&format_obstack, "%s_min", name); \ obstack_printf (&format_obstack, "%s_min", name); \
MUSCLE_INSERT_LONG_INT (obstack_finish0 (&format_obstack), lmin); \ MUSCLE_INSERT_LONG_INT (obstack_finish0 (&format_obstack), lmin); \
obstack_printf (&format_obstack, "%s_max", name); \ obstack_printf (&format_obstack, "%s_max", name); \
MUSCLE_INSERT_LONG_INT (obstack_finish0 (&format_obstack), lmax); \ MUSCLE_INSERT_LONG_INT (obstack_finish0 (&format_obstack), lmax); \
} }
GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_unsigned_int_table, unsigned int) GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_unsigned_int_table, unsigned int)
GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_int_table, int) GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_int_table, int)
GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_base_table, base_number) GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_base_table, base_number)
GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_rule_number_table, rule_number) GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_rule_number_table, rule_number)
GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_symbol_number_table, symbol_number) GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_symbol_number_table, symbol_number)
GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_state_number_table, state_number) GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_state_number_table, state_number)
/*----------------------------------------------------------------. /*----------------------------------------------------------------.
| Print to OUT a representation of CP quoted and escaped for M4. | | Print to OUT a representation of CP quoted and escaped for M4. |
@@ -149,7 +150,7 @@ prepare_symbols (void)
MUSCLE_INSERT_INT ("tokens_number", ntokens); MUSCLE_INSERT_INT ("tokens_number", ntokens);
MUSCLE_INSERT_INT ("nterms_number", nvars); MUSCLE_INSERT_INT ("nterms_number", nvars);
MUSCLE_INSERT_INT ("symbols_number", nsyms); MUSCLE_INSERT_INT ("symbols_number", nsyms);
MUSCLE_INSERT_INT ("undef_token_number", undeftoken->content->number); MUSCLE_INSERT_INT ("undef_token_number", undeftoken->number);
MUSCLE_INSERT_INT ("user_token_number_max", max_user_token_number); MUSCLE_INSERT_INT ("user_token_number_max", max_user_token_number);
muscle_insert_symbol_number_table ("translate", muscle_insert_symbol_number_table ("translate",
@@ -197,7 +198,7 @@ prepare_symbols (void)
int i; int i;
int *values = xnmalloc (ntokens, sizeof *values); int *values = xnmalloc (ntokens, sizeof *values);
for (i = 0; i < ntokens; ++i) for (i = 0; i < ntokens; ++i)
values[i] = symbols[i]->content->user_token_number; values[i] = symbols[i]->user_token_number;
muscle_insert_int_table ("toknum", values, muscle_insert_int_table ("toknum", values,
values[0], 1, ntokens); values[0], 1, ntokens);
free (values); free (values);
@@ -226,7 +227,7 @@ prepare_rules (void)
/* LHS of the rule R. */ /* LHS of the rule R. */
r1[r] = rules[r].lhs->number; r1[r] = rules[r].lhs->number;
/* Length of rule R's RHS. */ /* Length of rule R's RHS. */
r2[r] = rule_rhs_length (&rules[r]); r2[r] = rule_rhs_length(&rules[r]);
/* Line where rule was defined. */ /* Line where rule was defined. */
rline[r] = rules[r].location.start.line; rline[r] = rules[r].location.start.line;
/* Dynamic precedence (GLR). */ /* Dynamic precedence (GLR). */
@@ -283,9 +284,9 @@ prepare_states (void)
static int static int
symbol_type_name_cmp (const symbol **lhs, const symbol **rhs) symbol_type_name_cmp (const symbol **lhs, const symbol **rhs)
{ {
int res = uniqstr_cmp ((*lhs)->content->type_name, (*rhs)->content->type_name); int res = uniqstr_cmp ((*lhs)->type_name, (*rhs)->type_name);
if (!res) if (!res)
res = (*lhs)->content->number - (*rhs)->content->number; res = (*lhs)->number - (*rhs)->number;
return res; return res;
} }
@@ -320,9 +321,8 @@ type_names_output (FILE *out)
/* The index of the first symbol of the current type-name. */ /* The index of the first symbol of the current type-name. */
int i0 = i; int i0 = i;
fputs (i ? ",\n[" : "[", out); fputs (i ? ",\n[" : "[", out);
for (; i < nsyms for (; i < nsyms && syms[i]->type_name == syms[i0]->type_name; ++i)
&& syms[i]->content->type_name == syms[i0]->content->type_name; ++i) fprintf (out, "%s%d", i != i0 ? ", " : "", syms[i]->number);
fprintf (out, "%s%d", i != i0 ? ", " : "", syms[i]->content->number);
fputs ("]", out); fputs ("]", out);
} }
fputs ("])\n\n", out); fputs ("])\n\n", out);
@@ -417,33 +417,32 @@ prepare_symbol_definitions (void)
/* Whether the symbol has an identifier. */ /* Whether the symbol has an identifier. */
value = symbol_id_get (sym); value = symbol_id_get (sym);
SET_KEY ("has_id"); SET_KEY("has_id");
MUSCLE_INSERT_INT (key, !!value); MUSCLE_INSERT_INT (key, !!value);
/* Its identifier. */ /* Its identifier. */
SET_KEY ("id"); SET_KEY("id");
MUSCLE_INSERT_STRING (key, value ? value : ""); MUSCLE_INSERT_STRING (key, value ? value : "");
/* Its tag. Typically for documentation purpose. */ /* Its tag. Typically for documentation purpose. */
SET_KEY ("tag"); SET_KEY("tag");
MUSCLE_INSERT_STRING (key, sym->tag); MUSCLE_INSERT_STRING (key, sym->tag);
SET_KEY ("user_number"); SET_KEY("user_number");
MUSCLE_INSERT_INT (key, sym->content->user_token_number); MUSCLE_INSERT_INT (key, sym->user_token_number);
SET_KEY ("is_token"); SET_KEY("is_token");
MUSCLE_INSERT_INT (key, MUSCLE_INSERT_INT (key,
i < ntokens && sym != errtoken && sym != undeftoken); i < ntokens && sym != errtoken && sym != undeftoken);
SET_KEY ("number"); SET_KEY("number");
MUSCLE_INSERT_INT (key, sym->content->number); MUSCLE_INSERT_INT (key, sym->number);
SET_KEY ("has_type"); SET_KEY("has_type");
MUSCLE_INSERT_INT (key, !!sym->content->type_name); MUSCLE_INSERT_INT (key, !!sym->type_name);
SET_KEY ("type"); SET_KEY("type");
MUSCLE_INSERT_STRING (key, sym->content->type_name MUSCLE_INSERT_STRING (key, sym->type_name ? sym->type_name : "");
? sym->content->type_name : "");
{ {
int j; int j;
@@ -452,18 +451,18 @@ prepare_symbol_definitions (void)
/* "printer", not "%printer". */ /* "printer", not "%printer". */
char const *pname = code_props_type_string (j) + 1; char const *pname = code_props_type_string (j) + 1;
code_props const *p = symbol_code_props_get (sym, j); code_props const *p = symbol_code_props_get (sym, j);
SET_KEY2 ("has", pname); SET_KEY2("has", pname);
MUSCLE_INSERT_INT (key, !!p->code); MUSCLE_INSERT_INT (key, !!p->code);
if (p->code) if (p->code)
{ {
SET_KEY2 (pname, "file"); SET_KEY2(pname, "file");
MUSCLE_INSERT_STRING (key, p->location.start.file); MUSCLE_INSERT_STRING (key, p->location.start.file);
SET_KEY2 (pname, "line"); SET_KEY2(pname, "line");
MUSCLE_INSERT_INT (key, p->location.start.line); MUSCLE_INSERT_INT (key, p->location.start.line);
SET_KEY (pname); SET_KEY(pname);
MUSCLE_INSERT_STRING_RAW (key, p->code); MUSCLE_INSERT_STRING_RAW (key, p->code);
} }
} }
+865 -1002
View File
File diff suppressed because it is too large Load Diff
+134 -97
View File
@@ -1,4 +1,4 @@
/* A Bison parser, made by GNU Bison 3.0. */ /* A Bison parser, made by GNU Bison 2.7.1021-bb417-dirty. */
/* Bison interface for Yacc-like parsers in C /* Bison interface for Yacc-like parsers in C
@@ -48,12 +48,10 @@
extern int gram_debug; extern int gram_debug;
#endif #endif
/* "%code requires" blocks. */ /* "%code requires" blocks. */
#line 21 "src/parse-gram.y" /* yacc.c:1909 */ #line 223 "src/parse-gram.y" /* yacc.c:1932 */
#include "symlist.h"
#include "symtab.h"
#line 233 "src/parse-gram.y" /* yacc.c:1909 */
# ifndef PARAM_TYPE
# define PARAM_TYPE
typedef enum typedef enum
{ {
param_none = 0, param_none = 0,
@@ -61,10 +59,10 @@ extern int gram_debug;
param_parse = 1 << 1, param_parse = 1 << 1,
param_both = param_lex | param_parse param_both = param_lex | param_parse
} param_type; } param_type;
#line 723 "src/parse-gram.y" /* yacc.c:1909 */ # endif
#include "muscle-tab.h"
#line 68 "src/parse-gram.h" /* yacc.c:1909 */
#line 66 "src/parse-gram.h" /* yacc.c:1932 */
/* Token type. */ /* Token type. */
#ifndef GRAM_TOKENTYPE #ifndef GRAM_TOKENTYPE
@@ -73,104 +71,143 @@ extern int gram_debug;
{ {
GRAM_EOF = 0, GRAM_EOF = 0,
STRING = 258, STRING = 258,
PERCENT_TOKEN = 259, INT = 259,
PERCENT_NTERM = 260, PERCENT_TOKEN = 260,
PERCENT_TYPE = 261, PERCENT_NTERM = 261,
PERCENT_DESTRUCTOR = 262, PERCENT_TYPE = 262,
PERCENT_PRINTER = 263, PERCENT_DESTRUCTOR = 263,
PERCENT_LEFT = 264, PERCENT_PRINTER = 264,
PERCENT_RIGHT = 265, PERCENT_LEFT = 265,
PERCENT_NONASSOC = 266, PERCENT_RIGHT = 266,
PERCENT_PRECEDENCE = 267, PERCENT_NONASSOC = 267,
PERCENT_PREC = 268, PERCENT_PRECEDENCE = 268,
PERCENT_DPREC = 269, PERCENT_PREC = 269,
PERCENT_GPREC = 270, PERCENT_DPREC = 270,
PERCENT_PRECR = 271, PERCENT_MERGE = 271,
PERCENT_MERGE = 272, PERCENT_CODE = 272,
PERCENT_CODE = 273, PERCENT_DEFAULT_PREC = 273,
PERCENT_DEFAULT_PREC = 274, PERCENT_DEFINE = 274,
PERCENT_DEFINE = 275, PERCENT_DEFINES = 275,
PERCENT_DEFINES = 276, PERCENT_ERROR_VERBOSE = 276,
PERCENT_ERROR_VERBOSE = 277, PERCENT_EXPECT = 277,
PERCENT_EXPECT = 278, PERCENT_EXPECT_RR = 278,
PERCENT_EXPECT_RR = 279, PERCENT_FLAG = 279,
PERCENT_FLAG = 280, PERCENT_FILE_PREFIX = 280,
PERCENT_FILE_PREFIX = 281, PERCENT_GLR_PARSER = 281,
PERCENT_GLR_PARSER = 282, PERCENT_INITIAL_ACTION = 282,
PERCENT_INITIAL_ACTION = 283, PERCENT_LANGUAGE = 283,
PERCENT_LANGUAGE = 284, PERCENT_NAME_PREFIX = 284,
PERCENT_NAME_PREFIX = 285, PERCENT_NO_DEFAULT_PREC = 285,
PERCENT_NO_DEFAULT_PREC = 286, PERCENT_NO_LINES = 286,
PERCENT_NO_LINES = 287, PERCENT_NONDETERMINISTIC_PARSER = 287,
PERCENT_NONDETERMINISTIC_PARSER = 288, PERCENT_OUTPUT = 288,
PERCENT_OUTPUT = 289, PERCENT_REQUIRE = 289,
PERCENT_REQUIRE = 290, PERCENT_SKELETON = 290,
PERCENT_SKELETON = 291, PERCENT_START = 291,
PERCENT_START = 292, PERCENT_TOKEN_TABLE = 292,
PERCENT_TOKEN_TABLE = 293, PERCENT_VERBOSE = 293,
PERCENT_VERBOSE = 294, PERCENT_YACC = 294,
PERCENT_YACC = 295, BRACED_CODE = 295,
BRACED_CODE = 296, BRACED_PREDICATE = 296,
BRACED_PREDICATE = 297, BRACKETED_ID = 297,
BRACKETED_ID = 298, CHAR = 298,
CHAR = 299, EPILOGUE = 299,
EPILOGUE = 300, EQUAL = 300,
EQUAL = 301, ID = 301,
ID = 302, ID_COLON = 302,
ID_COLON = 303, PERCENT_PERCENT = 303,
PERCENT_PERCENT = 304, PIPE = 304,
PIPE = 305, PROLOGUE = 305,
PROLOGUE = 306, SEMICOLON = 306,
SEMICOLON = 307, TAG = 307,
GT = 308, TAG_ANY = 308,
TAG = 309, TAG_NONE = 309,
TAG_ANY = 310, PERCENT_PARAM = 310,
TAG_NONE = 311, PERCENT_UNION = 311
LBRACE = 312,
RBRACE = 313,
INT = 314,
PERCENT_PARAM = 315,
PERCENT_UNION = 316,
PERCENT_EMPTY = 317
}; };
#endif #endif
/* Tokens. */
#define GRAM_EOF 0
#define STRING 258
#define INT 259
#define PERCENT_TOKEN 260
#define PERCENT_NTERM 261
#define PERCENT_TYPE 262
#define PERCENT_DESTRUCTOR 263
#define PERCENT_PRINTER 264
#define PERCENT_LEFT 265
#define PERCENT_RIGHT 266
#define PERCENT_NONASSOC 267
#define PERCENT_PRECEDENCE 268
#define PERCENT_PREC 269
#define PERCENT_DPREC 270
#define PERCENT_MERGE 271
#define PERCENT_CODE 272
#define PERCENT_DEFAULT_PREC 273
#define PERCENT_DEFINE 274
#define PERCENT_DEFINES 275
#define PERCENT_ERROR_VERBOSE 276
#define PERCENT_EXPECT 277
#define PERCENT_EXPECT_RR 278
#define PERCENT_FLAG 279
#define PERCENT_FILE_PREFIX 280
#define PERCENT_GLR_PARSER 281
#define PERCENT_INITIAL_ACTION 282
#define PERCENT_LANGUAGE 283
#define PERCENT_NAME_PREFIX 284
#define PERCENT_NO_DEFAULT_PREC 285
#define PERCENT_NO_LINES 286
#define PERCENT_NONDETERMINISTIC_PARSER 287
#define PERCENT_OUTPUT 288
#define PERCENT_REQUIRE 289
#define PERCENT_SKELETON 290
#define PERCENT_START 291
#define PERCENT_TOKEN_TABLE 292
#define PERCENT_VERBOSE 293
#define PERCENT_YACC 294
#define BRACED_CODE 295
#define BRACED_PREDICATE 296
#define BRACKETED_ID 297
#define CHAR 298
#define EPILOGUE 299
#define EQUAL 300
#define ID 301
#define ID_COLON 302
#define PERCENT_PERCENT 303
#define PIPE 304
#define PROLOGUE 305
#define SEMICOLON 306
#define TAG 307
#define TAG_ANY 308
#define TAG_NONE 309
#define PERCENT_PARAM 310
#define PERCENT_UNION 311
/* Value type. */ /* Value type. */
#if ! defined GRAM_STYPE && ! defined GRAM_STYPE_IS_DECLARED #if ! defined GRAM_STYPE && ! defined GRAM_STYPE_IS_DECLARED
typedef union GRAM_STYPE GRAM_STYPE; typedef union GRAM_STYPE GRAM_STYPE;
union GRAM_STYPE union GRAM_STYPE
{ {
#line 187 "src/parse-gram.y" /* yacc.c:1909 */ #line 109 "src/parse-gram.y" /* yacc.c:1932 */
unsigned char character;
#line 191 "src/parse-gram.y" /* yacc.c:1909 */ assoc assoc;
char *code; char *code;
#line 196 "src/parse-gram.y" /* yacc.c:1909 */ char const *chars;
uniqstr uniqstr; int integer;
#line 204 "src/parse-gram.y" /* yacc.c:1909 */ named_ref *named_ref;
int integer; symbol *symbol;
#line 208 "src/parse-gram.y" /* yacc.c:1909 */ symbol_list *list;
symbol *symbol; uniqstr uniqstr;
#line 213 "src/parse-gram.y" /* yacc.c:1909 */ unsigned char character;
assoc assoc;
#line 216 "src/parse-gram.y" /* yacc.c:1909 */ #line 247 "src/parse-gram.y" /* yacc.c:1932 */
symbol_list *list;
#line 219 "src/parse-gram.y" /* yacc.c:1909 */ param_type param;
named_ref *named_ref;
#line 224 "src/parse-gram.y" /* yacc.c:1909 */ #line 423 "src/parse-gram.y" /* yacc.c:1932 */
prec_rel_comparator prec_rel_comparator;
#line 253 "src/parse-gram.y" /* yacc.c:1909 */
param_type param;
#line 423 "src/parse-gram.y" /* yacc.c:1909 */
code_props_type code_type; code_props_type code_type;
#line 725 "src/parse-gram.y" /* yacc.c:1909 */
struct #line 211 "src/parse-gram.h" /* yacc.c:1932 */
{
char const *chars;
muscle_kind kind;
} value;
#line 174 "src/parse-gram.h" /* yacc.c:1909 */
}; };
# define GRAM_STYPE_IS_TRIVIAL 1 # define GRAM_STYPE_IS_TRIVIAL 1
# define GRAM_STYPE_IS_DECLARED 1 # define GRAM_STYPE_IS_DECLARED 1
+146 -263
View File
@@ -1,4 +1,4 @@
/* Bison Grammar Parser -*- C -*- %{/* Bison Grammar Parser -*- C -*-
Copyright (C) 2002-2013 Free Software Foundation, Inc. Copyright (C) 2002-2013 Free Software Foundation, Inc.
@@ -17,35 +17,45 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */ along with this program. If not, see <http://www.gnu.org/licenses/>. */
%code requires
{
#include "symlist.h"
#include "symtab.h"
}
%code top
{
/* On column 0 to please syntax-check. */
#include <config.h> #include <config.h>
} #include "system.h"
#include "c-ctype.h"
#include "complain.h"
#include "conflicts.h"
#include "files.h"
#include "getargs.h"
#include "gram.h"
#include "muscle-tab.h"
#include "named-ref.h"
#include "quotearg.h"
#include "reader.h"
#include "symlist.h"
#include "symtab.h"
#include "scan-gram.h"
#include "scan-code.h"
#include "xmemdup0.h"
#define YYLLOC_DEFAULT(Current, Rhs, N) (Current) = lloc_default (Rhs, N)
static YYLTYPE lloc_default (YYLTYPE const *, int);
#define YY_LOCATION_PRINT(File, Loc) \
location_print (File, Loc)
static void version_check (location const *loc, char const *version);
/* Request detailed syntax error messages, and pass them to GRAM_ERROR.
FIXME: depends on the undocumented availability of YYLLOC. */
#undef yyerror
#define yyerror(Msg) \
gram_error (&yylloc, Msg)
static void gram_error (location const *, char const *);
static char const *char_name (char);
%}
%code %code
{ {
#include "system.h"
#include "c-ctype.h"
#include "complain.h"
#include "conflicts.h"
#include "files.h"
#include "getargs.h"
#include "gram.h"
#include "named-ref.h"
#include "quotearg.h"
#include "reader.h"
#include "scan-gram.h"
#include "scan-code.h"
#include "xmemdup0.h"
static int current_prec = 0; static int current_prec = 0;
static location current_lhs_location; static location current_lhs_location;
static named_ref *current_lhs_named_ref; static named_ref *current_lhs_named_ref;
@@ -56,37 +66,20 @@
/** Set the new current left-hand side symbol, possibly common /** Set the new current left-hand side symbol, possibly common
* to several right-hand side parts of rule. * to several right-hand side parts of rule.
*/ */
static void current_lhs (symbol *sym, location loc, named_ref *ref); static
void
#define YYLLOC_DEFAULT(Current, Rhs, N) \ current_lhs(symbol *sym, location loc, named_ref *ref)
(Current) = lloc_default (Rhs, N) {
static YYLTYPE lloc_default (YYLTYPE const *, int); current_lhs_symbol = sym;
current_lhs_location = loc;
#define YY_LOCATION_PRINT(File, Loc) \ /* In order to simplify memory management, named references for lhs
location_print (Loc, File) are always assigned by deep copy into the current symbol_list
node. This is because a single named-ref in the grammar may
/* Strip initial '{' and final '}' (must be first and last characters). result in several uses when the user factors lhs between several
Return the result. */ rules using "|". Therefore free the parser's original copy. */
static char *strip_braces (char *code); free (current_lhs_named_ref);
current_lhs_named_ref = ref;
/* Convert CODE by calling code_props_plain_init if PLAIN, otherwise }
code_props_symbol_action_init. Call
gram_scanner_last_string_free to release the latest string from
the scanner (should be CODE). */
static char const *translate_code (char *code, location loc, bool plain);
/* Convert CODE by calling code_props_plain_init after having
stripped the first and last characters (expected to be '{', and
'}'). Call gram_scanner_last_string_free to release the latest
string from the scanner (should be CODE). */
static char const *translate_code_braceless (char *code, location loc);
static void version_check (location const *loc, char const *version);
static void gram_error (location const *, char const *);
/* A string that describes a char (e.g., 'a' -> "'a'"). */
static char const *char_name (char);
#define YYTYPE_INT16 int_fast16_t #define YYTYPE_INT16 int_fast16_t
#define YYTYPE_INT8 int_fast8_t #define YYTYPE_INT8 int_fast8_t
@@ -94,8 +87,8 @@
#define YYTYPE_UINT8 uint_fast8_t #define YYTYPE_UINT8 uint_fast8_t
} }
%define api.prefix {gram_} %define api.prefix "gram_"
%define api.pure full %define api.pure
%define locations %define locations
%define parse.error verbose %define parse.error verbose
%define parse.lac full %define parse.lac full
@@ -112,9 +105,23 @@
boundary_set (&@$.end, current_file, 1, 1); boundary_set (&@$.end, current_file, 1, 1);
} }
%union
{
assoc assoc;
char *code;
char const *chars;
int integer;
named_ref *named_ref;
symbol *symbol;
symbol_list *list;
uniqstr uniqstr;
unsigned char character;
};
/* Define the tokens together with their human representation. */ /* Define the tokens together with their human representation. */
%token GRAM_EOF 0 "end of file" %token GRAM_EOF 0 "end of file"
%token STRING "string" %token STRING "string"
%token INT "integer"
%token PERCENT_TOKEN "%token" %token PERCENT_TOKEN "%token"
%token PERCENT_NTERM "%nterm" %token PERCENT_NTERM "%nterm"
@@ -130,8 +137,6 @@
%token PERCENT_PREC "%prec" %token PERCENT_PREC "%prec"
%token PERCENT_DPREC "%dprec" %token PERCENT_DPREC "%dprec"
%token PERCENT_GPREC "%gprec"
%token PERCENT_PRECR "%precr"
%token PERCENT_MERGE "%merge" %token PERCENT_MERGE "%merge"
/*----------------------. /*----------------------.
@@ -177,23 +182,22 @@
%token PIPE "|" %token PIPE "|"
%token PROLOGUE "%{...%}" %token PROLOGUE "%{...%}"
%token SEMICOLON ";" %token SEMICOLON ";"
%token GT ">"
%token TAG "<tag>" %token TAG "<tag>"
%token TAG_ANY "<*>" %token TAG_ANY "<*>"
%token TAG_NONE "<>" %token TAG_NONE "<>"
%token LBRACE "{"
%token RBRACE "}"
%union {unsigned char character;}
%type <character> CHAR %type <character> CHAR
%printer { fputs (char_name ($$), yyo); } CHAR %printer { fputs (char_name ($$), yyo); } CHAR
%union {char *code;}; /* braceless is not to be used for rule or symbol actions, as it
%type <code> "{...}" "%?{...}" "%{...%}" EPILOGUE STRING calls code_props_plain_init. */
%printer { fputs (quotearg_style (c_quoting_style, $$), yyo); } STRING %type <chars> STRING "%{...%}" EPILOGUE braceless content.opt
%printer { fprintf (yyo, "{\n%s\n}", $$); } <code> %type <code> "{...}" "%?{...}"
%printer { fputs (quotearg_style (c_quoting_style, $$), yyo); }
STRING
%printer { fprintf (yyo, "{\n%s\n}", $$); }
braceless content.opt "{...}" "%{...%}" EPILOGUE
%union {uniqstr uniqstr;}
%type <uniqstr> BRACKETED_ID ID ID_COLON PERCENT_FLAG TAG tag variable %type <uniqstr> BRACKETED_ID ID ID_COLON PERCENT_FLAG TAG tag variable
%printer { fputs ($$, yyo); } <uniqstr> %printer { fputs ($$, yyo); } <uniqstr>
%printer { fprintf (yyo, "[%s]", $$); } BRACKETED_ID %printer { fprintf (yyo, "[%s]", $$); } BRACKETED_ID
@@ -201,36 +205,24 @@
%printer { fprintf (yyo, "%%%s", $$); } PERCENT_FLAG %printer { fprintf (yyo, "%%%s", $$); } PERCENT_FLAG
%printer { fprintf (yyo, "<%s>", $$); } TAG tag %printer { fprintf (yyo, "<%s>", $$); } TAG tag
%union {int integer;}; %type <integer> INT
%token <integer> INT "integer"
%printer { fprintf (yyo, "%d", $$); } <integer> %printer { fprintf (yyo, "%d", $$); } <integer>
%union {symbol *symbol;}
%type <symbol> id id_colon string_as_id symbol symbol.prec %type <symbol> id id_colon string_as_id symbol symbol.prec
%printer { fprintf (yyo, "%s", $$->tag); } <symbol> %printer { fprintf (yyo, "%s", $$->tag); } <symbol>
%printer { fprintf (yyo, "%s:", $$->tag); } id_colon %printer { fprintf (yyo, "%s:", $$->tag); } id_colon
%union {assoc assoc;};
%type <assoc> precedence_declarator %type <assoc> precedence_declarator
%union {symbol_list *list;}
%type <list> symbols.1 symbols.prec generic_symlist generic_symlist_item %type <list> symbols.1 symbols.prec generic_symlist generic_symlist_item
%union {named_ref *named_ref;}
%type <named_ref> named_ref.opt %type <named_ref> named_ref.opt
%type <uniqstr> prec_group_name.opt string_or_id
%union {prec_rel_comparator prec_rel_comparator;}
%type <prec_rel_comparator> prec_rel_comparator
%type <list> precedence_relation_symbols precedence_symbol
/*---------. /*---------.
| %param. | | %param. |
`---------*/ `---------*/
%code requires %code requires
{ {
# ifndef PARAM_TYPE
# define PARAM_TYPE
typedef enum typedef enum
{ {
param_none = 0, param_none = 0,
@@ -238,6 +230,7 @@
param_parse = 1 << 1, param_parse = 1 << 1,
param_both = param_lex | param_parse param_both = param_lex | param_parse
} param_type; } param_type;
# endif
}; };
%code %code
{ {
@@ -250,17 +243,20 @@
static void add_param (param_type type, char *decl, location loc); static void add_param (param_type type, char *decl, location loc);
static param_type current_param = param_none; static param_type current_param = param_none;
}; };
%union {param_type param;} %union
{
param_type param;
}
%token <param> PERCENT_PARAM "%param"; %token <param> PERCENT_PARAM "%param";
%printer %printer
{ {
switch ($$) switch ($$)
{ {
#define CASE(In, Out) \ #define CASE(In, Out) \
case param_ ## In: fputs ("%" #Out, yyo); break case param_ ## In: fputs ("%" #Out, stderr); break
CASE (lex, lex-param); CASE(lex, lex-param);
CASE (parse, parse-param); CASE(parse, parse-param);
CASE (both, param); CASE(both, param);
#undef CASE #undef CASE
case param_none: aver (false); break; case param_none: aver (false); break;
} }
@@ -282,7 +278,7 @@ input:
`------------------------------------*/ `------------------------------------*/
prologue_declarations: prologue_declarations:
%empty /* Nothing */
| prologue_declarations prologue_declaration | prologue_declarations prologue_declaration
; ;
@@ -290,17 +286,21 @@ prologue_declaration:
grammar_declaration grammar_declaration
| "%{...%}" | "%{...%}"
{ {
code_props plain_code;
code_props_plain_init (&plain_code, $1, @1);
code_props_translate_code (&plain_code);
gram_scanner_last_string_free ();
muscle_code_grow (union_seen ? "post_prologue" : "pre_prologue", muscle_code_grow (union_seen ? "post_prologue" : "pre_prologue",
translate_code ($1, @1, true), @1); plain_code.code, @1);
code_scanner_last_string_free (); code_scanner_last_string_free ();
} }
| "%<flag>" | "%<flag>"
{ {
muscle_percent_define_ensure ($1, @1, true); muscle_percent_define_ensure ($1, @1, true);
} }
| "%define" variable value | "%define" variable content.opt
{ {
muscle_percent_define_insert ($2, @2, $3.kind, $3.chars, muscle_percent_define_insert ($2, @2, $3,
MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
} }
| "%defines" { defines_flag = true; } | "%defines" { defines_flag = true; }
@@ -311,8 +311,7 @@ prologue_declaration:
} }
| "%error-verbose" | "%error-verbose"
{ {
muscle_percent_define_insert ("parse.error", @1, muscle_keyword, muscle_percent_define_insert ("parse.error", @1, "verbose",
"verbose",
MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
} }
| "%expect" INT { expected_sr_conflicts = $2; } | "%expect" INT { expected_sr_conflicts = $2; }
@@ -325,7 +324,11 @@ prologue_declaration:
} }
| "%initial-action" "{...}" | "%initial-action" "{...}"
{ {
muscle_code_grow ("initial_action", translate_code ($2, @2, false), @2); code_props action;
code_props_symbol_action_init (&action, $2, @2);
code_props_translate_code (&action);
gram_scanner_last_string_free ();
muscle_code_grow ("initial_action", action.code, @2);
code_scanner_last_string_free (); code_scanner_last_string_free ();
} }
| "%language" STRING { language_argmatch ($2, grammar_prio, @1); } | "%language" STRING { language_argmatch ($2, grammar_prio, @1); }
@@ -377,8 +380,6 @@ params:
grammar_declaration: grammar_declaration:
precedence_declaration precedence_declaration
| precedence_group_declaration
| precedence_relation_declaration
| symbol_declaration | symbol_declaration
| "%start" symbol | "%start" symbol
{ {
@@ -404,17 +405,16 @@ grammar_declaration:
{ {
default_prec = false; default_prec = false;
} }
| "%code" "{...}" | "%code" braceless
{ {
/* Do not invoke muscle_percent_code_grow here since it invokes /* Do not invoke muscle_percent_code_grow here since it invokes
muscle_user_name_list_grow. */ muscle_user_name_list_grow. */
muscle_code_grow ("percent_code()", muscle_code_grow ("percent_code()", $2, @2);
translate_code_braceless ($2, @2), @2);
code_scanner_last_string_free (); code_scanner_last_string_free ();
} }
| "%code" ID "{...}" | "%code" ID braceless
{ {
muscle_percent_code_grow ($2, @2, translate_code_braceless ($3, @3), @3); muscle_percent_code_grow ($2, @2, $3, @3);
code_scanner_last_string_free (); code_scanner_last_string_free ();
} }
; ;
@@ -434,15 +434,15 @@ code_props_type:
%token PERCENT_UNION "%union"; %token PERCENT_UNION "%union";
union_name: union_name:
%empty {} /* Nothing. */ {}
| ID { muscle_code_grow ("union_name", $1, @1); } | ID { muscle_code_grow ("union_name", $1, @1); }
; ;
grammar_declaration: grammar_declaration:
"%union" union_name "{...}" "%union" union_name braceless
{ {
union_seen = true; union_seen = true;
muscle_code_grow ("union_members", translate_code_braceless ($3, @3), @3); muscle_code_grow ("stype", $3, @3);
code_scanner_last_string_free (); code_scanner_last_string_free ();
} }
; ;
@@ -471,30 +471,6 @@ symbol_declaration:
} }
; ;
/* A group of symbols for precedence declaration */
precedence_group_declaration:
"%gprec" prec_group_name.opt
{
set_current_group ($2, &@2);
}
"{" precedence_declarations "}"
{
set_current_group (DEFAULT_GROUP_NAME, NULL);
}
;
/* Name for the precedence group. If none is present a new unique one is
generated. */
prec_group_name.opt:
%empty { $$ = new_anonymous_group_name (); }
| variable /* Just a string, maybe there's a better way? */
;
precedence_declarations:
precedence_declaration
| precedence_declarations precedence_declaration
;
precedence_declaration: precedence_declaration:
precedence_declarator tag.opt symbols.prec precedence_declarator tag.opt symbols.prec
{ {
@@ -518,48 +494,8 @@ precedence_declarator:
; ;
tag.opt: tag.opt:
%empty { current_type = NULL; } /* Nothing. */ { current_type = NULL; }
| TAG { current_type = $1; tag_seen = true; } | TAG { current_type = $1; tag_seen = true; }
;
/* Declaration of a precedence relation between two (lists of) tokens */
precedence_relation_declaration:
"%precr" precedence_relation_symbols
{ prec_braces = default_braces_state; }
prec_rel_comparator
precedence_relation_symbols
{ declare_precedence_relation ($2, $5, $4, @4); }
;
precedence_relation_symbols:
precedence_symbol { $$ = $1; }
| precedence_relation_symbols precedence_symbol
{ $$ = symbol_list_append ($1, $2); }
;
precedence_symbol:
string_or_id
{
if (is_prec_group ($1))
$$ = expand_symbol_group (symgroup_from_uniqstr($1, &@1), @1);
else
$$ = symbol_list_sym_new (symbol_from_uniqstr ($1, @1), @1);
}
| CHAR
{
$$ = symbol_list_sym_new (symbol_from_uniqstr (uniqstr_new (char_name ($1)), @1), @1);
}
;
string_or_id:
STRING { $$ = uniqstr_new (quotearg_style (c_quoting_style, $1)); }
| ID { $$ = $1; }
;
prec_rel_comparator:
">" { $$ = prec_superior; }
| "=" { $$ = prec_equal; }
| ">" ">" { $$ = prec_superior_strict; }
; ;
/* Just like symbols.1 but accept INT for the sake of POSIX. */ /* Just like symbols.1 but accept INT for the sake of POSIX. */
@@ -571,17 +507,8 @@ symbols.prec:
; ;
symbol.prec: symbol.prec:
symbol symbol { $$ = $1; }
{ | symbol INT { $$ = $1; symbol_user_token_number_set ($1, $2, @2); }
$$ = $1;
symbol_class_set ($1, token_sym, @1, false);
}
| symbol INT
{
$$ = $1;
symbol_user_token_number_set ($1, $2, @2);
symbol_class_set ($1, token_sym, @1, false);
}
; ;
/* One or more symbols to be %typed. */ /* One or more symbols to be %typed. */
@@ -682,9 +609,8 @@ rhses.1:
| rhses.1 ";" | rhses.1 ";"
; ;
%token PERCENT_EMPTY "%empty";
rhs: rhs:
%empty /* Nothing. */
{ grammar_current_rule_begin (current_lhs_symbol, current_lhs_location, { grammar_current_rule_begin (current_lhs_symbol, current_lhs_location,
current_lhs_named_ref); } current_lhs_named_ref); }
| rhs symbol named_ref.opt | rhs symbol named_ref.opt
@@ -693,8 +619,6 @@ rhs:
{ grammar_current_rule_action_append ($2, @2, $3, false); } { grammar_current_rule_action_append ($2, @2, $3, false); }
| rhs "%?{...}" | rhs "%?{...}"
{ grammar_current_rule_action_append ($2, @2, NULL, true); } { grammar_current_rule_action_append ($2, @2, NULL, true); }
| rhs "%empty"
{ 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
@@ -704,47 +628,44 @@ rhs:
; ;
named_ref.opt: named_ref.opt:
%empty { $$ = 0; } /* Nothing. */ { $$ = 0; }
| BRACKETED_ID { $$ = named_ref_new ($1, @1); } |
BRACKETED_ID { $$ = named_ref_new($1, @1); }
; ;
/*---------------------. /*---------------------------.
| variable and value. | | variable and content.opt. |
`---------------------*/ `---------------------------*/
/* The STRING form of variable is deprecated and is not M4-friendly. /* The STRING form of variable is deprecated and is not M4-friendly.
For example, M4 fails for '%define "[" "value"'. */ For example, M4 fails for `%define "[" "value"'. */
variable: variable:
ID ID
| STRING { $$ = uniqstr_new ($1); } | STRING { $$ = uniqstr_new ($1); }
; ;
/* Some content or empty by default. */ /* Some content or empty by default. */
%code requires {#include "muscle-tab.h"}; content.opt:
%union /* Nothing. */ { $$ = ""; }
{ | ID { $$ = $1; }
struct | STRING
{ ;
char const *chars;
muscle_kind kind;
} value;
};
%type <value> value;
%printer
{
switch ($$.kind)
{
case muscle_code: fprintf (yyo, "{%s}", $$.chars); break;
case muscle_keyword: fprintf (yyo, "%s", $$.chars); break;
case muscle_string: fprintf (yyo, "\"%s\"", $$.chars); break;
}
} <value>;
value:
%empty { $$.kind = muscle_keyword; $$.chars = ""; } /*------------.
| ID { $$.kind = muscle_keyword; $$.chars = $1; } | braceless. |
| STRING { $$.kind = muscle_string; $$.chars = $1; } `------------*/
| "{...}" { $$.kind = muscle_code; $$.chars = strip_braces ($1); }
braceless:
"{...}"
{
code_props plain_code;
$1[strlen ($1) - 1] = '\n';
code_props_plain_init (&plain_code, $1+1, @1);
code_props_translate_code (&plain_code);
gram_scanner_last_string_free ();
$$ = plain_code.code;
}
; ;
@@ -786,10 +707,14 @@ string_as_id:
; ;
epilogue.opt: epilogue.opt:
%empty /* Nothing. */
| "%%" EPILOGUE | "%%" EPILOGUE
{ {
muscle_code_grow ("epilogue", translate_code ($2, @2, true), @2); code_props plain_code;
code_props_plain_init (&plain_code, $2, @2);
code_props_translate_code (&plain_code);
gram_scanner_last_string_free ();
muscle_code_grow ("epilogue", plain_code.code, @2);
code_scanner_last_string_free (); code_scanner_last_string_free ();
} }
; ;
@@ -825,33 +750,6 @@ lloc_default (YYLTYPE const *rhs, int n)
return loc; return loc;
} }
static
char *strip_braces (char *code)
{
code[strlen (code) - 1] = 0;
return code + 1;
}
static
char const *
translate_code (char *code, location loc, bool plain)
{
code_props plain_code;
if (plain)
code_props_plain_init (&plain_code, code, loc);
else
code_props_symbol_action_init (&plain_code, code, loc);
code_props_translate_code (&plain_code);
gram_scanner_last_string_free ();
return plain_code.code;
}
static
char const *
translate_code_braceless (char *code, location loc)
{
return translate_code (strip_braces (code), loc, true);
}
static void static void
add_param (param_type type, char *decl, location loc) add_param (param_type type, char *decl, location loc)
@@ -934,18 +832,3 @@ char_name (char c)
return quotearg_style (escape_quoting_style, buf); return quotearg_style (escape_quoting_style, buf);
} }
} }
static
void
current_lhs (symbol *sym, location loc, named_ref *ref)
{
current_lhs_symbol = sym;
current_lhs_location = loc;
/* In order to simplify memory management, named references for lhs
are always assigned by deep copy into the current symbol_list
node. This is because a single named-ref in the grammar may
result in several uses when the user factors lhs between several
rules using "|". Therefore free the parser's original copy. */
free (current_lhs_named_ref);
current_lhs_named_ref = ref;
}
+11 -18
View File
@@ -45,8 +45,7 @@ struct escape_buf
char *ptr; char *ptr;
size_t size; size_t size;
}; };
enum { num_escape_bufs = 3 }; static struct escape_buf escape_bufs[3];
static struct escape_buf escape_bufs[num_escape_bufs];
/*--------------------------------. /*--------------------------------.
@@ -210,7 +209,7 @@ print_errs (FILE *out, int level, state *s)
/*-------------------------------------------------------------------------. /*-------------------------------------------------------------------------.
| Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be 'default'). | | Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be `default'). |
| If not ENABLED, the rule is masked by a shift or a reduce (S/R and | | If not ENABLED, the rule is masked by a shift or a reduce (S/R and |
| R/R conflicts). | | R/R conflicts). |
`-------------------------------------------------------------------------*/ `-------------------------------------------------------------------------*/
@@ -260,7 +259,7 @@ print_reductions (FILE *out, int level, state *s)
bitset_set (no_reduce_set, TRANSITION_SYMBOL (trans, i)); bitset_set (no_reduce_set, TRANSITION_SYMBOL (trans, i));
for (i = 0; i < s->errs->num; ++i) for (i = 0; i < s->errs->num; ++i)
if (s->errs->symbols[i]) if (s->errs->symbols[i])
bitset_set (no_reduce_set, s->errs->symbols[i]->content->number); bitset_set (no_reduce_set, s->errs->symbols[i]->number);
if (default_reduction) if (default_reduction)
report = true; report = true;
@@ -388,12 +387,11 @@ print_grammar (FILE *out, int level)
/* Terminals */ /* Terminals */
xml_puts (out, level + 1, "<terminals>"); xml_puts (out, level + 1, "<terminals>");
for (i = 0; i < max_user_token_number + 1; i++) for (i = 0; i < max_user_token_number + 1; i++)
if (token_translations[i] != undeftoken->content->number) if (token_translations[i] != undeftoken->number)
{ {
char const *tag = symbols[token_translations[i]]->tag; char const *tag = symbols[token_translations[i]]->tag;
int precedence = symbols[token_translations[i]]->content->prec; int precedence = symbols[token_translations[i]]->prec;
assoc associativity = symbols[token_translations[i]]->content->prec_node assoc associativity = symbols[token_translations[i]]->assoc;
->assoc;
xml_indent (out, level + 2); xml_indent (out, level + 2);
fprintf (out, fprintf (out,
"<terminal symbol-number=\"%d\" token-number=\"%d\"" "<terminal symbol-number=\"%d\" token-number=\"%d\""
@@ -498,6 +496,7 @@ xml_escape (char const *str)
void void
print_xml (void) print_xml (void)
{ {
state_number i;
int level = 0; int level = 0;
FILE *out = xfopen (spec_xml_file, "w"); FILE *out = xfopen (spec_xml_file, "w");
@@ -523,11 +522,8 @@ print_xml (void)
/* print automaton */ /* print automaton */
fputc ('\n', out); fputc ('\n', out);
xml_puts (out, level + 1, "<automaton>"); xml_puts (out, level + 1, "<automaton>");
{ for (i = 0; i < nstates; i++)
state_number i; print_state (out, level + 2, states[i]);
for (i = 0; i < nstates; i++)
print_state (out, level + 2, states[i]);
}
xml_puts (out, level + 1, "</automaton>"); xml_puts (out, level + 1, "</automaton>");
bitset_free (no_reduce_set); bitset_free (no_reduce_set);
@@ -535,11 +531,8 @@ print_xml (void)
xml_puts (out, 0, "</bison-xml-report>"); xml_puts (out, 0, "</bison-xml-report>");
{ free (escape_bufs[0].ptr);
int i; free (escape_bufs[1].ptr);
for (i = 0; i < num_escape_bufs; ++i)
free (escape_bufs[i].ptr);
}
xfclose (out); xfclose (out);
} }
+6 -7
View File
@@ -72,7 +72,7 @@ print_core (FILE *out, state *s)
size_t i; size_t i;
item_number *sitems = s->items; item_number *sitems = s->items;
size_t snritems = s->nitems; size_t snritems = s->nitems;
sym_content *previous_lhs = NULL; symbol *previous_lhs = NULL;
/* Output all the items of a state, not only its kernel. */ /* Output all the items of a state, not only its kernel. */
if (report_flag & report_itemsets) if (report_flag & report_itemsets)
@@ -206,7 +206,7 @@ print_errs (FILE *out, state *s)
/*-------------------------------------------------------------------------. /*-------------------------------------------------------------------------.
| Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be 'default'). | | Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be `default'). |
| If not ENABLED, the rule is masked by a shift or a reduce (S/R and | | If not ENABLED, the rule is masked by a shift or a reduce (S/R and |
| R/R conflicts). | | R/R conflicts). |
`-------------------------------------------------------------------------*/ `-------------------------------------------------------------------------*/
@@ -223,8 +223,7 @@ print_reduction (FILE *out, size_t width,
if (!enabled) if (!enabled)
fputc ('[', out); fputc ('[', out);
if (r->number) if (r->number)
fprintf (out, _("reduce using rule %d (%s)"), r->number, fprintf (out, _("reduce using rule %d (%s)"), r->number, r->lhs->tag);
r->lhs->symbol->tag);
else else
fprintf (out, _("accept")); fprintf (out, _("accept"));
if (!enabled) if (!enabled)
@@ -258,7 +257,7 @@ print_reductions (FILE *out, state *s)
bitset_set (no_reduce_set, TRANSITION_SYMBOL (trans, i)); bitset_set (no_reduce_set, TRANSITION_SYMBOL (trans, i));
for (i = 0; i < s->errs->num; ++i) for (i = 0; i < s->errs->num; ++i)
if (s->errs->symbols[i]) if (s->errs->symbols[i])
bitset_set (no_reduce_set, s->errs->symbols[i]->content->number); bitset_set (no_reduce_set, s->errs->symbols[i]->number);
/* Compute the width of the lookahead token column. */ /* Compute the width of the lookahead token column. */
if (default_reduction) if (default_reduction)
@@ -409,7 +408,7 @@ print_grammar (FILE *out)
/* TERMINAL (type #) : rule #s terminal is on RHS */ /* TERMINAL (type #) : rule #s terminal is on RHS */
fprintf (out, "%s\n\n", _("Terminals, with rules where they appear")); fprintf (out, "%s\n\n", _("Terminals, with rules where they appear"));
for (i = 0; i < max_user_token_number + 1; i++) for (i = 0; i < max_user_token_number + 1; i++)
if (token_translations[i] != undeftoken->content->number) if (token_translations[i] != undeftoken->number)
{ {
const char *tag = symbols[token_translations[i]]->tag; const char *tag = symbols[token_translations[i]]->tag;
rule_number r; rule_number r;
@@ -515,7 +514,7 @@ print_results (void)
print_grammar (out); print_grammar (out);
/* If the whole state item sets, not only the kernels, are wanted, /* If the whole state item sets, not only the kernels, are wanted,
'closure' will be run, which needs memory allocation/deallocation. */ `closure' will be run, which needs memory allocation/deallocation. */
if (report_flag & report_itemsets) if (report_flag & report_itemsets)
new_closure (nritems); new_closure (nritems);
/* Storage for print_reductions. */ /* Storage for print_reductions. */
+4 -5
View File
@@ -46,7 +46,7 @@ static void
print_core (struct obstack *oout, state *s) print_core (struct obstack *oout, state *s)
{ {
item_number const *sitems = s->items; item_number const *sitems = s->items;
sym_content *previous_lhs = NULL; symbol *previous_lhs = NULL;
size_t i; size_t i;
size_t snritems = s->nitems; size_t snritems = s->nitems;
@@ -72,12 +72,11 @@ print_core (struct obstack *oout, state *s)
r = &rules[item_number_as_rule_number (*sp)]; r = &rules[item_number_as_rule_number (*sp)];
obstack_printf (oout, "%3d ", r->number); obstack_printf (oout, "%3d ", r->number);
if (previous_lhs && UNIQSTR_EQ (previous_lhs->symbol->tag, if (previous_lhs && UNIQSTR_EQ (previous_lhs->tag, r->lhs->tag))
r->lhs->symbol->tag))
obstack_printf (oout, "%*s| ", obstack_printf (oout, "%*s| ",
(int) strlen (previous_lhs->symbol->tag), ""); (int) strlen (previous_lhs->tag), "");
else else
obstack_printf (oout, "%s: ", escape (r->lhs->symbol->tag)); obstack_printf (oout, "%s: ", escape (r->lhs->tag));
previous_lhs = r->lhs; previous_lhs = r->lhs;
for (sp = r->rhs; sp < sp1; sp++) for (sp = r->rhs; sp < sp1; sp++)
+66 -106
View File
@@ -240,13 +240,13 @@ grammar_current_rule_begin (symbol *lhs, location loc,
current_rule = grammar_end; current_rule = grammar_end;
/* Mark the rule's lhs as a nonterminal if not already so. */ /* Mark the rule's lhs as a nonterminal if not already so. */
if (lhs->content->class == unknown_sym) if (lhs->class == unknown_sym)
{ {
lhs->content->class = nterm_sym; lhs->class = nterm_sym;
lhs->content->number = nvars; lhs->number = nvars;
++nvars; ++nvars;
} }
else if (lhs->content->class == token_sym) else if (lhs->class == token_sym)
complain (&loc, complaint, _("rule given for %s, which is a token"), complain (&loc, complaint, _("rule given for %s, which is a token"),
lhs->tag); lhs->tag);
} }
@@ -267,9 +267,9 @@ symbol_should_be_used (symbol_list const *s, bool *midrule_warning)
return true; return true;
if ((s->midrule && s->midrule->action_props.is_value_used) if ((s->midrule && s->midrule->action_props.is_value_used)
|| (s->midrule_parent_rule || (s->midrule_parent_rule
&& (symbol_list_n_get (s->midrule_parent_rule, && symbol_list_n_get (s->midrule_parent_rule,
s->midrule_parent_rhs_index) s->midrule_parent_rhs_index)
->action_props.is_value_used))) ->action_props.is_value_used))
{ {
*midrule_warning = true; *midrule_warning = true;
return true; return true;
@@ -292,15 +292,15 @@ grammar_rule_check (const symbol_list *r)
Don't worry about the default action if $$ is untyped, since $$'s Don't worry about the default action if $$ is untyped, since $$'s
value can't be used. */ value can't be used. */
if (!r->action_props.code && r->content.sym->content->type_name) if (!r->action_props.code && r->content.sym->type_name)
{ {
symbol *first_rhs = r->next->content.sym; symbol *first_rhs = r->next->content.sym;
/* If $$ is being set in default way, report if any type mismatch. */ /* If $$ is being set in default way, report if any type mismatch. */
if (first_rhs) if (first_rhs)
{ {
char const *lhs_type = r->content.sym->content->type_name; char const *lhs_type = r->content.sym->type_name;
const char *rhs_type = const char *rhs_type =
first_rhs->content->type_name ? first_rhs->content->type_name : ""; first_rhs->type_name ? first_rhs->type_name : "";
if (!UNIQSTR_EQ (lhs_type, rhs_type)) if (!UNIQSTR_EQ (lhs_type, rhs_type))
complain (&r->location, Wother, complain (&r->location, Wother,
_("type clash on default action: <%s> != <%s>"), _("type clash on default action: <%s> != <%s>"),
@@ -321,7 +321,7 @@ grammar_rule_check (const symbol_list *r)
bool midrule_warning = false; bool midrule_warning = false;
if (!l->action_props.is_value_used if (!l->action_props.is_value_used
&& symbol_should_be_used (l, &midrule_warning) && symbol_should_be_used (l, &midrule_warning)
/* The default action, $$ = $1, 'uses' both. */ /* The default action, $$ = $1, `uses' both. */
&& (r->action_props.code || (n != 0 && n != 1))) && (r->action_props.code || (n != 0 && n != 1)))
{ {
warnings warn_flag = midrule_warning ? Wmidrule_values : Wother; warnings warn_flag = midrule_warning ? Wmidrule_values : Wother;
@@ -333,25 +333,12 @@ grammar_rule_check (const symbol_list *r)
} }
} }
/* Check that %empty => empty rule. */
if (r->percent_empty_loc.start.file
&& r->next && r->next->content.sym)
complain (&r->percent_empty_loc, complaint,
_("%%empty on non-empty rule"));
/* Check that empty rule => %empty. */
if (!(r->next && r->next->content.sym)
&& !r->midrule_parent_rule
&& !r->percent_empty_loc.start.file)
complain (&r->location, Wempty_rule, _("empty rule without %%empty"));
/* See comments in grammar_current_rule_prec_set for how POSIX /* See comments in grammar_current_rule_prec_set for how POSIX
mandates this complaint. It's only for identifiers, so skip mandates this complaint. It's only for identifiers, so skip
it for char literals and strings, which are always tokens. */ it for char literals and strings, which are always tokens. */
if (r->ruleprec if (r->ruleprec
&& r->ruleprec->tag[0] != '\'' && r->ruleprec->tag[0] != '"' && r->ruleprec->tag[0] != '\'' && r->ruleprec->tag[0] != '"'
&& r->ruleprec->content->status != declared && r->ruleprec->status != declared && !r->ruleprec->prec)
&& !r->ruleprec->content->prec)
complain (&r->location, Wother, complain (&r->location, Wother,
_("token for %%prec is not defined: %s"), r->ruleprec->tag); _("token for %%prec is not defined: %s"), r->ruleprec->tag);
} }
@@ -443,26 +430,8 @@ grammar_current_rule_prec_set (symbol *precsym, location loc)
token. */ token. */
symbol_class_set (precsym, token_sym, loc, false); symbol_class_set (precsym, token_sym, loc, false);
if (current_rule->ruleprec) if (current_rule->ruleprec)
duplicate_directive ("%prec", complain (&loc, complaint, _("only one %s allowed per rule"), "%prec");
current_rule->ruleprec->location, loc); current_rule->ruleprec = precsym;
else
current_rule->ruleprec = precsym;
}
/* Set %empty for the current rule. */
void
grammar_current_rule_empty_set (location loc)
{
/* If %empty is used and -Wno-empty-rule is not, then enable
-Wempty-rule. */
if (warning_is_unset (Wempty_rule))
warning_argmatch ("empty-rule", 0, 0);
if (current_rule->percent_empty_loc.start.file)
duplicate_directive ("%empty",
current_rule->percent_empty_loc, loc);
else
current_rule->percent_empty_loc = loc;
} }
/* Attach dynamic precedence DPREC to the current rule. */ /* Attach dynamic precedence DPREC to the current rule. */
@@ -477,13 +446,8 @@ grammar_current_rule_dprec_set (int dprec, location loc)
complain (&loc, complaint, _("%s must be followed by positive number"), complain (&loc, complaint, _("%s must be followed by positive number"),
"%dprec"); "%dprec");
else if (current_rule->dprec != 0) else if (current_rule->dprec != 0)
duplicate_directive ("%dprec", complain (&loc, complaint, _("only one %s allowed per rule"), "%dprec");
current_rule->dprec_location, loc); current_rule->dprec = dprec;
else
{
current_rule->dprec = dprec;
current_rule->dprec_location = loc;
}
} }
/* Attach a merge function NAME with argument type TYPE to current /* Attach a merge function NAME with argument type TYPE to current
@@ -496,13 +460,9 @@ grammar_current_rule_merge_set (uniqstr name, location loc)
complain (&loc, Wother, _("%s affects only GLR parsers"), complain (&loc, Wother, _("%s affects only GLR parsers"),
"%merge"); "%merge");
if (current_rule->merger != 0) if (current_rule->merger != 0)
duplicate_directive ("%merge", complain (&loc, complaint, _("only one %s allowed per rule"), "%merge");
current_rule->merger_declaration_location, loc); current_rule->merger = get_merge_function (name);
else current_rule->merger_declaration_location = loc;
{
current_rule->merger = get_merge_function (name);
current_rule->merger_declaration_location = loc;
}
} }
/* Attach SYM to the current rule. If needed, move the previous /* Attach SYM to the current rule. If needed, move the previous
@@ -517,9 +477,9 @@ grammar_current_rule_symbol_append (symbol *sym, location loc,
grammar_midrule_action (); grammar_midrule_action ();
p = grammar_symbol_append (sym, loc); p = grammar_symbol_append (sym, loc);
if (name) if (name)
assign_named_ref (p, name); assign_named_ref(p, name);
if (sym->content->status == undeclared || sym->content->status == used) if (sym->status == undeclared || sym->status == used)
sym->content->status = needed; sym->status = needed;
} }
/* Attach an ACTION to the current rule. */ /* Attach an ACTION to the current rule. */
@@ -547,7 +507,7 @@ packgram (void)
{ {
unsigned int itemno = 0; unsigned int itemno = 0;
rule_number ruleno = 0; rule_number ruleno = 0;
symbol_list *p; symbol_list *p = grammar;
ritem = xnmalloc (nritems + 1, sizeof *ritem); ritem = xnmalloc (nritems + 1, sizeof *ritem);
@@ -556,14 +516,15 @@ packgram (void)
rules = xnmalloc (nrules, sizeof *rules); rules = xnmalloc (nrules, sizeof *rules);
for (p = grammar; p; p = p->next) while (p)
{ {
int rule_length = 0;
symbol *ruleprec = p->ruleprec; symbol *ruleprec = p->ruleprec;
record_merge_function_type (p->merger, p->content.sym->content->type_name, record_merge_function_type (p->merger, p->content.sym->type_name,
p->merger_declaration_location); p->merger_declaration_location);
rules[ruleno].user_number = ruleno; rules[ruleno].user_number = ruleno;
rules[ruleno].number = ruleno; rules[ruleno].number = ruleno;
rules[ruleno].lhs = p->content.sym->content; rules[ruleno].lhs = p->content.sym;
rules[ruleno].rhs = ritem + itemno; rules[ruleno].rhs = ritem + itemno;
rules[ruleno].prec = NULL; rules[ruleno].prec = NULL;
rules[ruleno].dprec = p->dprec; rules[ruleno].dprec = p->dprec;
@@ -575,14 +536,14 @@ packgram (void)
rules[ruleno].action_location = p->action_props.location; rules[ruleno].action_location = p->action_props.location;
rules[ruleno].is_predicate = p->action_props.is_predicate; rules[ruleno].is_predicate = p->action_props.is_predicate;
/* If the midrule's $$ is set or its $n is used, remove the '$' from the /* If the midrule's $$ is set or its $n is used, remove the `$' from the
symbol name so that it's a user-defined symbol so that the default symbol name so that it's a user-defined symbol so that the default
%destructor and %printer apply. */ %destructor and %printer apply. */
if (p->midrule_parent_rule if (p->midrule_parent_rule
&& (p->action_props.is_value_used && (p->action_props.is_value_used
|| (symbol_list_n_get (p->midrule_parent_rule, || symbol_list_n_get (p->midrule_parent_rule,
p->midrule_parent_rhs_index) p->midrule_parent_rhs_index)
->action_props.is_value_used))) ->action_props.is_value_used))
p->content.sym->tag += 1; p->content.sym->tag += 1;
/* Don't check the generated rule 0. It has no action, so some rhs /* Don't check the generated rule 0. It has no action, so some rhs
@@ -591,40 +552,40 @@ packgram (void)
if (p != grammar) if (p != grammar)
grammar_rule_check (p); grammar_rule_check (p);
{ for (p = p->next; p && p->content.sym; p = p->next)
size_t rule_length = 0; {
for (p = p->next; p->content.sym; p = p->next) ++rule_length;
{
++rule_length;
/* Don't allow rule_length == INT_MAX, since that might /* Don't allow rule_length == INT_MAX, since that might
cause confusion with strtol if INT_MAX == LONG_MAX. */ cause confusion with strtol if INT_MAX == LONG_MAX. */
if (rule_length == INT_MAX) if (rule_length == INT_MAX)
complain (&rules[ruleno].location, fatal, _("rule is too long")); complain (&rules[ruleno].location, fatal, _("rule is too long"));
/* item_number = symbol_number. /* item_number = symbol_number.
But the former needs to contain more: negative rule numbers. */ But the former needs to contain more: negative rule numbers. */
ritem[itemno++] = ritem[itemno++] =
symbol_number_as_item_number (p->content.sym->content->number); symbol_number_as_item_number (p->content.sym->number);
/* A rule gets by default the precedence and associativity /* A rule gets by default the precedence and associativity
of its last token. */ of its last token. */
if (p->content.sym->content->class == token_sym && default_prec) if (p->content.sym->class == token_sym && default_prec)
rules[ruleno].prec = p->content.sym->content; rules[ruleno].prec = p->content.sym;
} }
}
/* If this rule has a %prec, /* If this rule has a %prec,
the specified symbol's precedence replaces the default. */ the specified symbol's precedence replaces the default. */
if (ruleprec) if (ruleprec)
{ {
rules[ruleno].precsym = ruleprec->content; rules[ruleno].precsym = ruleprec;
rules[ruleno].prec = ruleprec->content; rules[ruleno].prec = ruleprec;
} }
/* An item ends by the rule number (negated). */ /* An item ends by the rule number (negated). */
ritem[itemno++] = rule_number_as_item_number (ruleno); ritem[itemno++] = rule_number_as_item_number (ruleno);
aver (itemno < ITEM_NUMBER_MAX); aver (itemno < ITEM_NUMBER_MAX);
++ruleno; ++ruleno;
aver (ruleno < RULE_NUMBER_MAX); aver (ruleno < RULE_NUMBER_MAX);
if (p)
p = p->next;
} }
aver (itemno == nritems); aver (itemno == nritems);
@@ -648,19 +609,19 @@ reader (void)
/* Construct the accept symbol. */ /* Construct the accept symbol. */
accept = symbol_get ("$accept", empty_location); accept = symbol_get ("$accept", empty_location);
accept->content->class = nterm_sym; accept->class = nterm_sym;
accept->content->number = nvars++; accept->number = nvars++;
/* Construct the error token */ /* Construct the error token */
errtoken = symbol_get ("error", empty_location); errtoken = symbol_get ("error", empty_location);
errtoken->content->class = token_sym; errtoken->class = token_sym;
errtoken->content->number = ntokens++; errtoken->number = ntokens++;
/* Construct a token that represents all undefined literal tokens. /* Construct a token that represents all undefined literal tokens.
It is always token number 2. */ It is always token number 2. */
undeftoken = symbol_get ("$undefined", empty_location); undeftoken = symbol_get ("$undefined", empty_location);
undeftoken->content->class = token_sym; undeftoken->class = token_sym;
undeftoken->content->number = ntokens++; undeftoken->number = ntokens++;
gram_in = xfopen (grammar_file, "r"); gram_in = xfopen (grammar_file, "r");
@@ -722,10 +683,10 @@ check_and_convert_grammar (void)
if (!endtoken) if (!endtoken)
{ {
endtoken = symbol_get ("$end", empty_location); endtoken = symbol_get ("$end", empty_location);
endtoken->content->class = token_sym; endtoken->class = token_sym;
endtoken->content->number = 0; endtoken->number = 0;
/* Value specified by POSIX. */ /* Value specified by POSIX. */
endtoken->content->user_token_number = 0; endtoken->user_token_number = 0;
} }
/* Report any undefined symbols and consider them nonterminals. */ /* Report any undefined symbols and consider them nonterminals. */
@@ -752,7 +713,7 @@ check_and_convert_grammar (void)
/* Insert the initial rule, whose line is that of the first rule /* Insert the initial rule, whose line is that of the first rule
(not that of the start symbol): (not that of the start symbol):
$accept: %start $end. */ accept: %start EOF. */
{ {
symbol_list *p = symbol_list_sym_new (accept, empty_location); symbol_list *p = symbol_list_sym_new (accept, empty_location);
p->location = grammar->location; p->location = grammar->location;
@@ -765,8 +726,7 @@ check_and_convert_grammar (void)
grammar = p; grammar = p;
} }
aver (nsyms <= SYMBOL_NUMBER_MAXIMUM); aver (nsyms <= SYMBOL_NUMBER_MAXIMUM && nsyms == ntokens + nvars);
aver (nsyms == ntokens + nvars);
/* Assign the symbols their symbol numbers. Write #defines for the /* Assign the symbols their symbol numbers. Write #defines for the
token symbols into FDEFINES if requested. */ token symbols into FDEFINES if requested. */
@@ -777,11 +737,11 @@ check_and_convert_grammar (void)
action type checking. action type checking.
Before invoking grammar_rule_check (in packgram below) on any rule, make Before invoking grammar_rule_check (in packgram below) on any rule, make
sure all actions have already been scanned in order to set 'used' flags. sure all actions have already been scanned in order to set `used' flags.
Otherwise, checking that a midrule's $$ should be set will not always work Otherwise, checking that a midrule's $$ should be set will not always work
properly because the check must forward-reference the midrule's parent properly because the check must forward-reference the midrule's parent
rule. For the same reason, all the 'used' flags must be set before rule. For the same reason, all the `used' flags must be set before
checking whether to remove '$' from any midrule symbol name (also in checking whether to remove `$' from any midrule symbol name (also in
packgram). */ packgram). */
{ {
symbol_list *sym; symbol_list *sym;
-2
View File
@@ -47,8 +47,6 @@ void grammar_current_rule_begin (symbol *lhs, location loc,
named_ref *lhs_named_ref); named_ref *lhs_named_ref);
void grammar_current_rule_end (location loc); void grammar_current_rule_end (location loc);
void grammar_midrule_action (void); void grammar_midrule_action (void);
/* Apply %empty to the current rule. */
void grammar_current_rule_empty_set (location loc);
void grammar_current_rule_prec_set (symbol *precsym, location loc); void grammar_current_rule_prec_set (symbol *precsym, location loc);
void grammar_current_rule_dprec_set (int dprec, location loc); void grammar_current_rule_dprec_set (int dprec, location loc);
void grammar_current_rule_merge_set (uniqstr name, location loc); void grammar_current_rule_merge_set (uniqstr name, location loc);
+10 -10
View File
@@ -49,7 +49,7 @@ static bitset P;
static bitset V; static bitset V;
/* Set of symbols used to define rule precedence (so they are /* Set of symbols used to define rule precedence (so they are
'useless', but no warning should be issued). */ `useless', but no warning should be issued). */
static bitset V1; static bitset V1;
static rule_number nuseful_productions; static rule_number nuseful_productions;
@@ -163,9 +163,9 @@ inaccessable_symbols (void)
Pp = bitset_create (nrules, BITSET_FIXED); 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, accept->number - ntokens))
{ {
bitset_set (V, accept->content->number); bitset_set (V, accept->number);
while (1) while (1)
{ {
@@ -196,9 +196,9 @@ inaccessable_symbols (void)
V = Vp; V = Vp;
/* Tokens 0, 1, and 2 are internal to Bison. Consider them useful. */ /* Tokens 0, 1, and 2 are internal to Bison. Consider them useful. */
bitset_set (V, endtoken->content->number); /* end-of-input token */ bitset_set (V, endtoken->number); /* end-of-input token */
bitset_set (V, errtoken->content->number); /* error token */ bitset_set (V, errtoken->number); /* error token */
bitset_set (V, undeftoken->content->number); /* some undefined token */ bitset_set (V, undeftoken->number); /* some undefined token */
bitset_free (P); bitset_free (P);
P = Pp; P = Pp;
@@ -298,7 +298,7 @@ nonterminals_reduce (void)
if (!bitset_test (V, i)) if (!bitset_test (V, i))
{ {
nontermmap[i - ntokens] = n++; nontermmap[i - ntokens] = n++;
if (symbols[i]->content->status != used) if (symbols[i]->status != used)
complain (&symbols[i]->location, Wother, complain (&symbols[i]->location, Wother,
_("nonterminal useless in grammar: %s"), _("nonterminal useless in grammar: %s"),
symbols[i]->tag); symbols[i]->tag);
@@ -310,7 +310,7 @@ nonterminals_reduce (void)
symbol **symbols_sorted = xnmalloc (nvars, sizeof *symbols_sorted); symbol **symbols_sorted = xnmalloc (nvars, sizeof *symbols_sorted);
for (i = ntokens; i < nsyms; i++) for (i = ntokens; i < nsyms; i++)
symbols[i]->content->number = nontermmap[i - ntokens]; symbols[i]->number = nontermmap[i - ntokens];
for (i = ntokens; i < nsyms; i++) for (i = ntokens; i < nsyms; i++)
symbols_sorted[nontermmap[i - ntokens] - ntokens] = symbols[i]; symbols_sorted[nontermmap[i - ntokens] - ntokens] = symbols[i];
for (i = ntokens; i < nsyms; i++) for (i = ntokens; i < nsyms; i++)
@@ -328,7 +328,7 @@ nonterminals_reduce (void)
*rhsp = symbol_number_as_item_number (nontermmap[*rhsp *rhsp = symbol_number_as_item_number (nontermmap[*rhsp
- ntokens]); - ntokens]);
} }
accept->content->number = nontermmap[accept->content->number - ntokens]; accept->number = nontermmap[accept->number - ntokens];
} }
nsyms -= nuseless_nonterminals; nsyms -= nuseless_nonterminals;
@@ -415,7 +415,7 @@ reduce_grammar (void)
reduce_print (); reduce_print ();
if (!bitset_test (N, accept->content->number - ntokens)) if (!bitset_test (N, accept->number - ntokens))
complain (&startsymbol_location, fatal, complain (&startsymbol_location, fatal,
_("start symbol %s does not derive any sentence"), _("start symbol %s does not derive any sentence"),
startsymbol->tag); startsymbol->tag);
+84 -10
View File
@@ -78,9 +78,8 @@ static bool untyped_var_seen;
/* POSIX says that a tag must be both an id and a C union member, but /* POSIX says that a tag must be both an id and a C union member, but
historically almost any character is allowed in a tag. We disallow historically almost any character is allowed in a tag. We disallow
NUL and newline, as this simplifies our implementation. We allow NUL and newline, as this simplifies our implementation. */
"->" as a means to dereference a pointer. */ tag [^\0\n>]+
tag ([^\0\n>]|->)+
/* Zero or more instances of backslash-newline. Following GCC, allow /* Zero or more instances of backslash-newline. Following GCC, allow
white space between the backslash and the newline. */ white space between the backslash and the newline. */
@@ -96,6 +95,26 @@ ref -?[0-9]+|{id}|"["{id}"]"|"$"
%% %%
%{ %{
/* Nesting level of the current code in braces. */
int braces_level = 0;
/* Whether a semicolon is probably needed.
The heuristic is that a semicolon is not needed after '{', '}',
';', or a C preprocessor directive, and that whitespaces and
comments do not affect this flag. Note that '{' does not need a
semicolon because of '{}'. A semicolon may be needed before a
cpp directive, but don't bother.
While it is maintained in several start-conditions (factoring
opportunities), it is meaningful only for SC_RULE_ACTION. */
bool need_semicolon = false;
/* Whether in a C preprocessor directive. Don't use a start condition
for this because, at the end of strings and comments, we still need
to know whether we're in a directive. */
bool in_cpp = false;
/* This scanner is special: it is invoked only once, henceforth /* This scanner is special: it is invoked only once, henceforth
is expected to return only once. This initialization is is expected to return only once. This initialization is
therefore done once per action to translate. */ therefore done once per action to translate. */
@@ -148,14 +167,32 @@ ref -?[0-9]+|{id}|"["{id}"]"|"$"
<SC_RULE_ACTION,SC_SYMBOL_ACTION> <SC_RULE_ACTION,SC_SYMBOL_ACTION>
{ {
"'" STRING_GROW; BEGIN SC_CHARACTER; "'" {
"\"" STRING_GROW; BEGIN SC_STRING; STRING_GROW;
"/"{splice}"*" STRING_GROW; BEGIN SC_COMMENT; BEGIN SC_CHARACTER;
"/"{splice}"/" STRING_GROW; BEGIN SC_LINE_COMMENT; need_semicolon = true;
}
"\"" {
STRING_GROW;
BEGIN SC_STRING;
need_semicolon = true;
}
"/"{splice}"*" {
STRING_GROW;
BEGIN SC_COMMENT;
}
"/"{splice}"/" {
STRING_GROW;
BEGIN SC_LINE_COMMENT;
}
[$@] { [$@] {
complain (loc, Wother, _("stray '%s'"), yytext); complain (loc, Wother, _("stray '%s'"), yytext);
obstack_escape (&obstack_for_string, yytext); obstack_escape (&obstack_for_string, yytext);
need_semicolon = true;
}
[\[\]] {
obstack_escape (&obstack_for_string, yytext);
need_semicolon = true;
} }
} }
@@ -166,13 +203,51 @@ ref -?[0-9]+|{id}|"["{id}"]"|"$"
handle_action_dollar (self->rule, yytext, *loc); handle_action_dollar (self->rule, yytext, *loc);
if (ref_tail_fields) if (ref_tail_fields)
obstack_sgrow (&obstack_for_string, ref_tail_fields); obstack_sgrow (&obstack_for_string, ref_tail_fields);
need_semicolon = true;
} }
"@"{ref} { "@"{ref} {
ref_tail_fields = NULL; ref_tail_fields = NULL;
handle_action_at (self->rule, yytext, *loc); handle_action_at (self->rule, yytext, *loc);
if (ref_tail_fields) if (ref_tail_fields)
obstack_sgrow (&obstack_for_string, ref_tail_fields); obstack_sgrow (&obstack_for_string, ref_tail_fields);
need_semicolon = true;
} }
";" STRING_GROW; need_semicolon = false;
"{" STRING_GROW; ++braces_level; need_semicolon = false;
"}" {
bool outer_brace = --braces_level == 0;
/* As an undocumented Bison extension, append ';' before the last
brace in braced code, so that the user code can omit trailing
';'. But do not append ';' if emulating Yacc, since Yacc does
not append one. This is deprecated since release 2.4.1. */
if (outer_brace && !yacc_flag && language_prio == default_prio
&& skeleton_prio == default_prio && need_semicolon && ! in_cpp)
{
unsigned int indent = 0;
complain_indent (loc, Wdeprecated, &indent,
_("a ';' might be needed at the end of action code"));
indent += SUB_INDENT;
complain_indent (loc, Wdeprecated | silent | no_caret, &indent,
_("future versions of Bison will not add the ';'"));
obstack_1grow (&obstack_for_string, ';');
}
STRING_GROW;
need_semicolon = false;
}
/* Preprocessing directives should only be recognized at the beginning
of lines, allowing whitespace including comments, but in C/C++,
'#' can only be the start of preprocessor directives or within
'#define' directives anyway, so don't bother with begin of line. */
"#" STRING_GROW; in_cpp = true;
{splice} STRING_GROW;
[\n\r] STRING_GROW; if (in_cpp) in_cpp = need_semicolon = false;
[ \t\f] STRING_GROW;
. STRING_GROW; need_semicolon = true;
} }
<SC_SYMBOL_ACTION> <SC_SYMBOL_ACTION>
@@ -596,8 +671,7 @@ fetch_type_name (char *cp, char const **type_name,
if (*cp == '<') if (*cp == '<')
{ {
*type_name = ++cp; *type_name = ++cp;
/* Series of non-'>' or "->". */ while (*cp != '>')
while (*cp != '>' || cp[-1] == '-')
++cp; ++cp;
/* The '>' symbol will be later replaced by '\0'. Original /* The '>' symbol will be later replaced by '\0'. Original
+23 -33
View File
@@ -112,12 +112,7 @@ static void unexpected_newline (boundary, char const *);
/* A identifier was just read in directives/rules. Special state /* A identifier was just read in directives/rules. Special state
to capture the sequence 'identifier :'. */ to capture the sequence 'identifier :'. */
%x SC_AFTER_IDENTIFIER %x SC_AFTER_IDENTIFIER
/* A complex tag, with nested angles brackets. */
/* POSIX says that a tag must be both an id and a C union member, but
historically almost any character is allowed in a tag. We
disallow NUL, as this simplifies our implementation. We match
angle brackets in nested pairs: several languages use them for
generics/template types. */
%x SC_TAG %x SC_TAG
/* Four types of user code: /* Four types of user code:
@@ -138,6 +133,13 @@ notletter [^.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]{-}[%\{]
id {letter}({letter}|[-0-9])* id {letter}({letter}|[-0-9])*
int [0-9]+ int [0-9]+
/* POSIX says that a tag must be both an id and a C union member, but
historically almost any character is allowed in a tag. We disallow
NUL, as this simplifies our implementation. We disallow angle
bracket to match them in nested pairs: several languages use them
for generics/template types. */
tag [^\0<>]+
/* Zero or more instances of backslash-newline. Following GCC, allow /* Zero or more instances of backslash-newline. Following GCC, allow
white space between the backslash and the newline. */ white space between the backslash and the newline. */
splice (\\[ \f\t\v]*\n)* splice (\\[ \f\t\v]*\n)*
@@ -215,7 +217,6 @@ eqopt ([[:space:]]*=)?
"%defines" return PERCENT_DEFINES; "%defines" return PERCENT_DEFINES;
"%destructor" return PERCENT_DESTRUCTOR; "%destructor" return PERCENT_DESTRUCTOR;
"%dprec" return PERCENT_DPREC; "%dprec" return PERCENT_DPREC;
"%empty" return PERCENT_EMPTY;
"%error-verbose" return PERCENT_ERROR_VERBOSE; "%error-verbose" return PERCENT_ERROR_VERBOSE;
"%expect" return PERCENT_EXPECT; "%expect" return PERCENT_EXPECT;
"%expect-rr" return PERCENT_EXPECT_RR; "%expect-rr" return PERCENT_EXPECT_RR;
@@ -223,10 +224,6 @@ eqopt ([[:space:]]*=)?
"%fixed-output-files" return PERCENT_YACC; "%fixed-output-files" return PERCENT_YACC;
"%initial-action" return PERCENT_INITIAL_ACTION; "%initial-action" return PERCENT_INITIAL_ACTION;
"%glr-parser" return PERCENT_GLR_PARSER; "%glr-parser" return PERCENT_GLR_PARSER;
"%gprec" {
prec_braces = gprec_seen;
return PERCENT_GPREC;
}
"%language" return PERCENT_LANGUAGE; "%language" return PERCENT_LANGUAGE;
"%left" return PERCENT_LEFT; "%left" return PERCENT_LEFT;
"%lex-param" RETURN_PERCENT_PARAM(lex); "%lex-param" RETURN_PERCENT_PARAM(lex);
@@ -243,7 +240,6 @@ eqopt ([[:space:]]*=)?
"%parse-param" RETURN_PERCENT_PARAM(parse); "%parse-param" RETURN_PERCENT_PARAM(parse);
"%prec" return PERCENT_PREC; "%prec" return PERCENT_PREC;
"%precedence" return PERCENT_PRECEDENCE; "%precedence" return PERCENT_PRECEDENCE;
"%precr" return PERCENT_PRECR;
"%printer" return PERCENT_PRINTER; "%printer" return PERCENT_PRINTER;
"%pure-parser" RETURN_PERCENT_FLAG("api.pure"); "%pure-parser" RETURN_PERCENT_FLAG("api.pure");
"%require" return PERCENT_REQUIRE; "%require" return PERCENT_REQUIRE;
@@ -278,17 +274,10 @@ eqopt ([[:space:]]*=)?
"=" return EQUAL; "=" return EQUAL;
"|" return PIPE; "|" return PIPE;
";" return SEMICOLON; ";" return SEMICOLON;
"}" return RBRACE;
">" return GT;
{id} { {id} {
val->uniqstr = uniqstr_new (yytext); val->uniqstr = uniqstr_new (yytext);
id_loc = *loc; id_loc = *loc;
if (prec_braces == gprec_seen)
{
prec_braces = group_name_seen;
return ID;
}
bracketed_id_str = NULL; bracketed_id_str = NULL;
BEGIN SC_AFTER_IDENTIFIER; BEGIN SC_AFTER_IDENTIFIER;
} }
@@ -319,11 +308,6 @@ eqopt ([[:space:]]*=)?
/* Code in between braces. */ /* Code in between braces. */
"{" { "{" {
if (prec_braces == gprec_seen || prec_braces == group_name_seen)
{
prec_braces = braces_seen;
return LBRACE;
}
STRING_GROW; STRING_GROW;
nesting = 0; nesting = 0;
code_start = loc->start; code_start = loc->start;
@@ -340,6 +324,13 @@ eqopt ([[:space:]]*=)?
/* A type. */ /* A type. */
"<*>" return TAG_ANY; "<*>" return TAG_ANY;
"<>" return TAG_NONE; "<>" return TAG_NONE;
"<"{tag}">" {
obstack_grow (&obstack_for_string, yytext + 1, yyleng - 2);
STRING_FINISH;
val->uniqstr = uniqstr_new (last_string);
STRING_FREE;
return TAG;
}
"<" { "<" {
nesting = 0; nesting = 0;
token_start = loc->start; token_start = loc->start;
@@ -529,7 +520,7 @@ eqopt ([[:space:]]*=)?
"\"" { "\"" {
STRING_FINISH; STRING_FINISH;
loc->start = token_start; loc->start = token_start;
val->code = last_string; val->chars = last_string;
BEGIN INITIAL; BEGIN INITIAL;
return STRING; return STRING;
} }
@@ -567,11 +558,10 @@ eqopt ([[:space:]]*=)?
<<EOF>> unexpected_eof (token_start, "'"); <<EOF>> unexpected_eof (token_start, "'");
} }
/*-----------------------------------------------------------.
| Scanning a Bison nested tag. The initial angle bracket is |
/*--------------------------------------------------------------. | already eaten. |
| Scanning a tag. The initial angle bracket is already eaten. | `-----------------------------------------------------------*/
`--------------------------------------------------------------*/
<SC_TAG> <SC_TAG>
{ {
@@ -589,7 +579,7 @@ eqopt ([[:space:]]*=)?
STRING_GROW; STRING_GROW;
} }
([^<>]|->)+ STRING_GROW; [^<>]+ STRING_GROW;
"<"+ STRING_GROW; nesting += yyleng; "<"+ STRING_GROW; nesting += yyleng;
<<EOF>> unexpected_eof (token_start, ">"); <<EOF>> unexpected_eof (token_start, ">");
@@ -768,7 +758,7 @@ eqopt ([[:space:]]*=)?
"%}" { "%}" {
STRING_FINISH; STRING_FINISH;
loc->start = code_start; loc->start = code_start;
val->code = last_string; val->chars = last_string;
BEGIN INITIAL; BEGIN INITIAL;
return PROLOGUE; return PROLOGUE;
} }
@@ -787,7 +777,7 @@ eqopt ([[:space:]]*=)?
<<EOF>> { <<EOF>> {
STRING_FINISH; STRING_FINISH;
loc->start = code_start; loc->start = code_start;
val->code = last_string; val->chars = last_string;
BEGIN INITIAL; BEGIN INITIAL;
return EPILOGUE; return EPILOGUE;
} }
+3 -5
View File
@@ -72,7 +72,7 @@ static void fail_for_invalid_at (char const *at);
"@@" fputc ('@', yyout); "@@" fputc ('@', yyout);
"@{" fputc ('[', yyout); "@{" fputc ('[', yyout);
"@}" fputc (']', yyout); "@}" fputc (']', yyout);
"@'" continue; /* Used by b4_cat in ../data/bison.m4. */ "@`" continue; /* Used by b4_cat in ../data/bison.m4. */
@\n continue; @\n continue;
"@oline@" fprintf (yyout, "%d", out_lineno + 1); "@oline@" fprintf (yyout, "%d", out_lineno + 1);
@@ -83,7 +83,7 @@ static void fail_for_invalid_at (char const *at);
"@output(" at_init (&argc, argv, &at_ptr, &at_output); "@output(" at_init (&argc, argv, &at_ptr, &at_output);
/* This pattern must not match more than the previous @ patterns. */ /* This pattern must not match more than the previous @ patterns. */
@[^@{}\'(\n]* fail_for_invalid_at (yytext); @[^@{}`(\n]* fail_for_invalid_at (yytext);
\n out_lineno++; ECHO; \n out_lineno++; ECHO;
[^@\n]+ ECHO; [^@\n]+ ECHO;
@@ -103,7 +103,7 @@ static void fail_for_invalid_at (char const *at);
"@@" obstack_1grow (&obstack_for_string, '@'); "@@" obstack_1grow (&obstack_for_string, '@');
"@{" obstack_1grow (&obstack_for_string, '['); "@{" obstack_1grow (&obstack_for_string, '[');
"@}" obstack_1grow (&obstack_for_string, ']'); "@}" obstack_1grow (&obstack_for_string, ']');
"@'" continue; /* For starting an argument that begins with whitespace. */ "@`" continue; /* For starting an argument that begins with whitespace. */
@\n continue; @\n continue;
@[,)] { @[,)] {
@@ -183,8 +183,6 @@ flag (const char *arg)
/* compare with values issued from b4_error */ /* compare with values issued from b4_error */
if (STREQ (arg, "complain")) if (STREQ (arg, "complain"))
return complaint; return complaint;
else if (STREQ (arg, "deprecated"))
return Wdeprecated;
else if (STREQ (arg, "fatal")) else if (STREQ (arg, "fatal"))
return fatal; return fatal;
else if (STREQ (arg, "note")) else if (STREQ (arg, "note"))
+1 -1
View File
@@ -135,7 +135,7 @@ typedef struct
/* Is the TRANSITIONS->states[Num] labelled by the error token? */ /* Is the TRANSITIONS->states[Num] labelled by the error token? */
# define TRANSITION_IS_ERROR(Transitions, Num) \ # define TRANSITION_IS_ERROR(Transitions, Num) \
(TRANSITION_SYMBOL (Transitions, Num) == errtoken->content->number) (TRANSITION_SYMBOL (Transitions, Num) == errtoken->number)
/* When resolving a SR conflicts, if the reduction wins, the shift is /* When resolving a SR conflicts, if the reduction wins, the shift is
disabled. */ disabled. */
+10 -17
View File
@@ -36,20 +36,18 @@ symbol_list_sym_new (symbol *sym, location loc)
res->content_type = SYMLIST_SYMBOL; res->content_type = SYMLIST_SYMBOL;
res->content.sym = sym; res->content.sym = sym;
res->location = res->sym_loc = loc; res->location = res->sym_loc = loc;
res->named_ref = NULL;
res->midrule = NULL; res->midrule = NULL;
res->midrule_parent_rule = NULL; res->midrule_parent_rule = NULL;
res->midrule_parent_rhs_index = 0; res->midrule_parent_rhs_index = 0;
/* Members used for LHS only. */
res->ruleprec = NULL;
res->percent_empty_loc = empty_location;
code_props_none_init (&res->action_props); code_props_none_init (&res->action_props);
res->ruleprec = NULL;
res->dprec = 0; res->dprec = 0;
res->dprec_location = empty_location;
res->merger = 0; res->merger = 0;
res->merger_declaration_location = empty_location;
res->named_ref = NULL;
res->next = NULL; res->next = NULL;
@@ -87,17 +85,12 @@ symbol_list_type_new (uniqstr type_name, location loc)
void void
symbol_list_syms_print (const symbol_list *l, FILE *f) symbol_list_syms_print (const symbol_list *l, FILE *f)
{ {
char const *sep = "";
for (/* Nothing. */; l && l->content.sym; l = l->next) for (/* Nothing. */; l && l->content.sym; l = l->next)
{ {
fputs (sep, f);
fputs (l->content_type == SYMLIST_SYMBOL ? "symbol: "
: l->content_type == SYMLIST_TYPE ? "type: "
: "invalid content_type: ",
f);
symbol_print (l->content.sym, f); symbol_print (l->content.sym, f);
fputs (l->action_props.is_value_used ? " used" : " unused", f); fprintf (stderr, l->action_props.is_value_used ? " used" : " unused");
sep = ", "; if (l && l->content.sym)
fprintf (f, ", ");
} }
} }
@@ -205,7 +198,7 @@ symbol_list_n_type_name_get (symbol_list *l, location loc, int n)
return NULL; return NULL;
} }
aver (l->content_type == SYMLIST_SYMBOL); aver (l->content_type == SYMLIST_SYMBOL);
return l->content.sym->content->type_name; return l->content.sym->type_name;
} }
bool bool
@@ -223,8 +216,8 @@ symbol_list_code_props_set (symbol_list *node, code_props_type kind,
{ {
case SYMLIST_SYMBOL: case SYMLIST_SYMBOL:
symbol_code_props_set (node->content.sym, kind, cprops); symbol_code_props_set (node->content.sym, kind, cprops);
if (node->content.sym->content->status == undeclared) if (node->content.sym->status == undeclared)
node->content.sym->content->status = used; node->content.sym->status = used;
break; break;
case SYMLIST_TYPE: case SYMLIST_TYPE:
semantic_type_code_props_set semantic_type_code_props_set
+5 -15
View File
@@ -50,9 +50,6 @@ typedef struct symbol_list
} content; } content;
location location; location location;
/* Named reference. */
named_ref *named_ref;
/* Proper location of the symbol, not all the rule */ /* Proper location of the symbol, not all the rule */
location sym_loc; location sym_loc;
@@ -67,26 +64,19 @@ typedef struct symbol_list
struct symbol_list *midrule_parent_rule; struct symbol_list *midrule_parent_rule;
int midrule_parent_rhs_index; int midrule_parent_rhs_index;
/* ---------------------------------------------- */
/* Apply to the rule (attached to the LHS only). */
/* ---------------------------------------------- */
/* Precedence/associativity. */
symbol *ruleprec;
/* The action is attached to the LHS of a rule, but action properties for /* The action is attached to the LHS of a rule, but action properties for
* each RHS are also stored here. */ * each RHS are also stored here. */
code_props action_props; code_props action_props;
/* The location of the first %empty for this rule, or \a /* Precedence/associativity. */
empty_location. */ symbol *ruleprec;
location percent_empty_loc;
int dprec; int dprec;
location dprec_location;
int merger; int merger;
location merger_declaration_location; location merger_declaration_location;
/* Named reference. */
named_ref *named_ref;
/* The list. */ /* The list. */
struct symbol_list *next; struct symbol_list *next;
} symbol_list; } symbol_list;
+182 -670
View File
File diff suppressed because it is too large Load Diff
+14 -119
View File
@@ -31,8 +31,6 @@
# include "scan-code.h" # include "scan-code.h"
# include "uniqstr.h" # include "uniqstr.h"
typedef struct symbol_list symbol_list;
/*----------. /*----------.
| Symbols. | | Symbols. |
`----------*/ `----------*/
@@ -52,7 +50,6 @@ typedef int symbol_number;
typedef struct symbol symbol; typedef struct symbol symbol;
typedef struct sym_content sym_content;
/* Declaration status of a symbol. /* Declaration status of a symbol.
@@ -64,8 +61,6 @@ typedef struct sym_content sym_content;
When status are checked at the end, "declared" symbols are fine, When status are checked at the end, "declared" symbols are fine,
"used" symbols trigger warnings, otherwise it's an error. */ "used" symbols trigger warnings, otherwise it's an error. */
typedef struct prec_node prec_node;
typedef enum typedef enum
{ {
/** Used in the input file for an unknown reason (error). */ /** Used in the input file for an unknown reason (error). */
@@ -87,6 +82,8 @@ enum code_props_type
enum { CODE_PROPS_SIZE = 2 }; enum { CODE_PROPS_SIZE = 2 };
/* When extending this structure, be sure to complete
symbol_check_alias_consistency. */
struct symbol struct symbol
{ {
/** The key, name of the symbol. */ /** The key, name of the symbol. */
@@ -94,20 +91,6 @@ struct symbol
/** The location of its first occurrence. */ /** The location of its first occurrence. */
location location; location location;
/* Points to the other in the symbol-string pair for an alias. */
symbol *alias;
/** Whether this symbol is the alias of another or not. */
bool is_alias;
/** All the info about the pointed symbol is there. */
sym_content *content;
};
struct sym_content
{
symbol *symbol;
/** Its \c \%type. /** Its \c \%type.
Beware that this is the type_name as was entered by the user, Beware that this is the type_name as was entered by the user,
@@ -129,29 +112,25 @@ struct sym_content
code_props props[CODE_PROPS_SIZE]; code_props props[CODE_PROPS_SIZE];
symbol_number number; symbol_number number;
location prec_location;
/* Not used anymore, to remove. */
int prec; int prec;
assoc assoc;
int user_token_number; int user_token_number;
/* Points to the other in the symbol-string pair for an alias.
Special value USER_NUMBER_HAS_STRING_ALIAS in the symbol half of the
symbol-string pair for an alias. */
symbol *alias;
symbol_class class; symbol_class class;
status status; status status;
/* The next element in the symbol precedence group. */
sym_content *group_next;
/* The graph node containing all the precedence information for this
symbol. */
prec_node *prec_node;
}; };
/** Undefined user number. */ /** Undefined user number. */
# define USER_NUMBER_UNDEFINED -1 # define USER_NUMBER_UNDEFINED -1
/* 'symbol->user_token_number == USER_NUMBER_HAS_STRING_ALIAS' means /* `symbol->user_token_number == USER_NUMBER_HAS_STRING_ALIAS' means
this symbol has a literal string alias. For instance, '%token foo this symbol has a literal string alias. For instance, `%token foo
"foo"' has '"foo"' numbered regularly, and 'foo' numbered as "foo"' has `"foo"' numbered regularly, and `foo' numbered as
USER_NUMBER_HAS_STRING_ALIAS. */ USER_NUMBER_HAS_STRING_ALIAS. */
# define USER_NUMBER_HAS_STRING_ALIAS -9991 # define USER_NUMBER_HAS_STRING_ALIAS -9991
@@ -287,8 +266,7 @@ struct symgraph
void register_precedence (graphid first, graphid snd); void register_precedence (graphid first, graphid snd);
/** Print a warning for each symbol whose precedence and/or associativity /** Print a warning for each symbol whose precedence is useless. */
* is useless. */
void print_precedence_warnings (void); void print_precedence_warnings (void);
@@ -296,92 +274,9 @@ void print_precedence_warnings (void);
| Symbol associativity | | Symbol associativity |
`----------------------*/ `----------------------*/
void register_assoc (graphid i, graphid j); void register_assoc (int i, int j);
/*------------------.
| Groups of symbols |
`------------------*/
#define DEFAULT_GROUP_NAME uniqstr_new ("__default__")
typedef struct symgroup symgroup;
struct symgroup
{
/** The name of the group. */
uniqstr tag;
/** The list of symbols in the group. */
sym_content * symbol_list;
location location;
} ;
/** Get a dummy name for an anonymous group. */
uniqstr new_anonymous_group_name (void);
/** Set the current group in the token precedence declaration to a new group
* with this name */
void set_current_group (const uniqstr name, location *loc);
/** Get or create the group by that name. The location information is used for
* creation when available. */
symgroup *
symgroup_from_uniqstr (const uniqstr key, location *loc);
/** Check if there is a symbol precedence group by that name. */
bool
is_prec_group (const uniqstr key);
/*----------------------------------.
| Graph of precedence relationships |
`----------------------------------*/
typedef struct prec_link prec_link;
struct prec_link
{
prec_node *target;
bool transitive;
prec_link *next;
};
struct prec_node
{
symbol *symbol;
/** Associativity for the symbol. */
assoc assoc;
location prec_location;
prec_link *sons;
prec_link *equals;
};
typedef enum prec_rel_comparator prec_rel_comparator;
enum prec_rel_comparator
{
prec_equal,
prec_superior,
prec_superior_strict,
};
/** Declare a precedence relationship between the symbols of the two lists,
* as defined by the operator. */
void
declare_precedence_relation (symbol_list *l1, symbol_list *l2,
prec_rel_comparator c, location loc);
/** Return the list of symbols contained in the group. */
symbol_list *
expand_symbol_group (symgroup * group, location loc);
/** Check if s1 and s2 have the same precedence level. */
bool is_prec_equal (prec_node * s1, prec_node * s2);
/** Check if from > to . */
bool is_prec_superior (prec_node * from, prec_node * to);
void print_assoc_warnings (void);
/*-----------------. /*-----------------.
| Semantic types. | | Semantic types. |
+1 -1
View File
@@ -99,7 +99,7 @@ typedef size_t uintptr_t;
# endif # endif
# endif # endif
/* The __-protected variants of 'format' and 'printf' attributes /* The __-protected variants of `format' and `printf' attributes
are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
# define __format__ format # define __format__ format
+9 -9
View File
@@ -35,7 +35,7 @@
#include "tables.h" #include "tables.h"
/* Several tables are indexed both by state and nonterminal numbers. /* Several tables are indexed both by state and nonterminal numbers.
We call such an index a 'vector'; i.e., a vector is either a state We call such an index a `vector'; i.e., a vector is either a state
or a nonterminal number. or a nonterminal number.
Of course vector_number_t ought to be wide enough to contain Of course vector_number_t ought to be wide enough to contain
@@ -90,18 +90,18 @@ static base_number *width;
/* For a given state, N = ACTROW[SYMBOL]: /* For a given state, N = ACTROW[SYMBOL]:
If N = 0, stands for 'run the default action'. If N = 0, stands for `run the default action'.
If N = MIN, stands for 'raise a syntax error'. If N = MIN, stands for `raise a syntax error'.
If N > 0, stands for 'shift SYMBOL and go to n'. If N > 0, stands for `shift SYMBOL and go to n'.
If N < 0, stands for 'reduce -N'. */ If N < 0, stands for `reduce -N'. */
typedef int action_number; typedef int action_number;
#define ACTION_NUMBER_MINIMUM INT_MIN #define ACTION_NUMBER_MINIMUM INT_MIN
static action_number *actrow; static action_number *actrow;
/* FROMS and TOS are reordered to be compressed. ORDER[VECTOR] is the /* FROMS and TOS are reordered to be compressed. ORDER[VECTOR] is the
new vector number of VECTOR. We skip 'empty' vectors (i.e., new vector number of VECTOR. We skip `empty' vectors (i.e.,
TALLY[VECTOR] = 0), and call these 'entries'. */ TALLY[VECTOR] = 0), and call these `entries'. */
static vector_number *order; static vector_number *order;
static int nentries; static int nentries;
@@ -290,7 +290,7 @@ action_row (state *s)
/* Do not use any default reduction if there is a shift for /* Do not use any default reduction if there is a shift for
error */ error */
if (sym == errtoken->content->number) if (sym == errtoken->number)
nodefault = true; nodefault = true;
} }
@@ -300,7 +300,7 @@ action_row (state *s)
for (i = 0; i < errp->num; i++) for (i = 0; i < errp->num; i++)
{ {
symbol *sym = errp->symbols[i]; symbol *sym = errp->symbols[i];
actrow[sym->content->number] = ACTION_NUMBER_MINIMUM; actrow[sym->number] = ACTION_NUMBER_MINIMUM;
} }
/* Turn off default reductions where requested by the user. See /* Turn off default reductions where requested by the user. See
+1 -1
View File
@@ -105,7 +105,7 @@ uniqstr_print_processor (void *ustr, void *null ATTRIBUTE_UNUSED)
int int
uniqstr_cmp (uniqstr l, uniqstr r) uniqstr_cmp(uniqstr l, uniqstr r)
{ {
return (l == r ? 0 return (l == r ? 0
: !l ? -1 : !l ? -1
+1 -1
View File
@@ -40,7 +40,7 @@ uniqstr uniqstr_vsprintf (char const *format, ...)
/* Compare two uniqstr a la strcmp: negative for <, nul for =, and /* Compare two uniqstr a la strcmp: negative for <, nul for =, and
positive for >. Undefined order, relies on addresses. */ positive for >. Undefined order, relies on addresses. */
int uniqstr_cmp (uniqstr u1, uniqstr u2); int uniqstr_cmp(uniqstr u1, uniqstr u2);
/* Die if STR is not a uniqstr. */ /* Die if STR is not a uniqstr. */
void uniqstr_assert (char const *str); void uniqstr_assert (char const *str);
+121 -125
View File
@@ -64,119 +64,6 @@ AT_PARSER_CHECK([./input], 0,
AT_CLEANUP AT_CLEANUP
## ----------------------- ##
## Implicitly empty rule. ##
## ----------------------- ##
AT_SETUP([Implicitly empty rule])
AT_DATA_GRAMMAR([[1.y]],
[[%%
exp: a b;
a: /* empty. */ {};
// A mid-rule action does not count as an empty rule.
b: {} {};
]])
AT_BISON_CHECK([-fcaret -Wempty-rule 1.y], [0], [],
[[1.y:11.17-18: warning: empty rule without %empty [-Wempty-rule]
a: /* empty. */ {};
^^
]])
AT_DATA_GRAMMAR([[2.y]],
[[%%
exp: a b c;
a: /* empty. */ {};
b: %empty {};
c: /* empty. */ {};
]])
AT_BISON_CHECK([-fcaret 2.y], [0], [],
[[2.y:11.17-18: warning: empty rule without %empty [-Wempty-rule]
a: /* empty. */ {};
^^
2.y:13.17-18: warning: empty rule without %empty [-Wempty-rule]
c: /* empty. */ {};
^^
]])
AT_BISON_CHECK([-fcaret -Wno-empty-rule 2.y], [0])
AT_CLEANUP
## ------------------------ ##
## Invalid uses of %empty. ##
## ------------------------ ##
AT_SETUP([Invalid uses of %empty])
AT_DATA_GRAMMAR([[one.y]],
[[%%
exp:
%empty {} %empty
;
]])
AT_BISON_CHECK([-fcaret one.y], [1], [],
[[one.y:11.13-18: error: only one %empty allowed per rule
%empty {} %empty
^^^^^^
one.y:11.3-8: previous declaration
%empty {} %empty
^^^^^^
]])
AT_DATA_GRAMMAR([[two.y]],
[[%%
exp:
'a' %empty {}
| %empty 'a' {}
| %empty {} {}
;
]])
AT_BISON_CHECK([-fcaret two.y], [1], [],
[[two.y:11.7-12: error: %empty on non-empty rule
'a' %empty {}
^^^^^^
two.y:12.3-8: error: %empty on non-empty rule
| %empty 'a' {}
^^^^^^
two.y:13.3-8: error: %empty on non-empty rule
| %empty {} {}
^^^^^^
]])
AT_CLEANUP
## ---------------------- ##
## Valid uses of %empty. ##
## ---------------------- ##
AT_SETUP([Valid uses of %empty])
AT_BISON_OPTION_PUSHDEFS
AT_DATA_GRAMMAR([[input.y]],
[[
%debug
%code
{
]AT_YYERROR_DECLARE[
]AT_YYLEX_DECLARE[
}
%%
exp: %empty {}
%%
]AT_YYERROR_DEFINE[
]AT_YYLEX_DEFINE[
]AT_MAIN_DEFINE[
]])
AT_FULL_COMPILE([input])
AT_PARSER_CHECK([./input])
AT_BISON_OPTION_POPDEFS
AT_CLEANUP
## ------------------ ## ## ------------------ ##
## Initial location. ## ## Initial location. ##
@@ -286,8 +173,8 @@ m4_popdef([AT_TEST])
## Location Print. ## ## Location Print. ##
## ---------------- ## ## ---------------- ##
# AT_TEST(SKELETON-NAME, DIRECTIVES, [MORE-DIRECTIVES]) # AT_TEST(SKELETON-NAME, DIRECTIVES, [MORE-DIRECTIVES], [LOCATION = 1.1])
# ----------------------------------------------------- # -----------------------------------------------------------------------
# Check that the initial location is correct. # Check that the initial location is correct.
m4_pushdef([AT_TEST], m4_pushdef([AT_TEST],
[AT_SETUP([Location print: $1 $2]) [AT_SETUP([Location print: $1 $2])
@@ -305,7 +192,7 @@ AT_DATA_GRAMMAR([[input.y]],
]AT_YYLEX_DECLARE[ ]AT_YYLEX_DECLARE[
} }
%% %%
exp: %empty; exp: /* empty */;
%% %%
]AT_YYERROR_DEFINE[ ]AT_YYERROR_DEFINE[
]AT_YYLEX_DEFINE[ ]AT_YYLEX_DEFINE[
@@ -528,7 +415,7 @@ AT_LALR1_CC_IF([typedef yy::location YYLTYPE;])[
%% %%
/* /*
This grammar is made to exercise error recovery. This grammar is made to exercise error recovery.
"Lines" starting with '(' support error recovery, with "Lines" starting with `(' support error recovery, with
')' as synchronizing token. Lines starting with 'x' can never ')' as synchronizing token. Lines starting with 'x' can never
be recovered from if in error. be recovered from if in error.
*/ */
@@ -605,11 +492,11 @@ static
{ {
static unsigned int counter = 0; static unsigned int counter = 0;
unsigned int c = ]AT_VAL[]m4_ifval([$6], [.ival])[ = counter++; int c = ]AT_VAL[]m4_ifval([$6], [.ival])[ = counter++;
/* As in BASIC, line numbers go from 10 to 10. */ /* As in BASIC, line numbers go from 10 to 10. */
]AT_LOC_FIRST_LINE[ = ]AT_LOC_FIRST_COLUMN[ = 10 * c; ]AT_LOC_FIRST_LINE[ = ]AT_LOC_FIRST_COLUMN[ = 10 * c;
]AT_LOC_LAST_LINE[ = ]AT_LOC_LAST_COLUMN[ = ]AT_LOC_FIRST_LINE[ + 9; ]AT_LOC_LAST_LINE[ = ]AT_LOC_LAST_COLUMN[ = ]AT_LOC_FIRST_LINE[ + 9;
assert (c <= strlen (source)); assert (0 <= c && c <= strlen (source));
if (source[c]) if (source[c])
fprintf (stderr, "sending: '%c'", source[c]); fprintf (stderr, "sending: '%c'", source[c]);
else else
@@ -691,7 +578,7 @@ Successful parse.
# Syntax errors caught by the parser # Syntax errors caught by the parser
# ---------------------------------- # ----------------------------------
# Exercise the discarding of stack top and input until 'error' # Exercise the discarding of stack top and input until `error'
# can be reduced. # can be reduced.
# #
# '(', 'x', 'x', 'x', 'x', 'x', ')', # '(', 'x', 'x', 'x', 'x', 'x', ')',
@@ -848,13 +735,13 @@ AT_CLEANUP
AT_CHECK_PRINTER_AND_DESTRUCTOR([]) AT_CHECK_PRINTER_AND_DESTRUCTOR([])
AT_CHECK_PRINTER_AND_DESTRUCTOR([], [ with union]) AT_CHECK_PRINTER_AND_DESTRUCTOR([], [with union])
AT_CHECK_PRINTER_AND_DESTRUCTOR([%defines %skeleton "lalr1.cc"]) AT_CHECK_PRINTER_AND_DESTRUCTOR([%defines %skeleton "lalr1.cc"])
AT_CHECK_PRINTER_AND_DESTRUCTOR([%defines %skeleton "lalr1.cc"], [ with union]) AT_CHECK_PRINTER_AND_DESTRUCTOR([%defines %skeleton "lalr1.cc"], [with union])
AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser]) AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser])
AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser], [ with union]) AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser], [with union])
@@ -1287,7 +1174,7 @@ AT_SETUP([Default %printer and %destructor are not for $accept])
# - The %printer and %destructor code generated for $accept would always be # - The %printer and %destructor code generated for $accept would always be
# dead code because $accept is currently never shifted onto the stack. # dead code because $accept is currently never shifted onto the stack.
# - $$ for $accept would always be of type YYSTYPE because it's not possible # - $$ for $accept would always be of type YYSTYPE because it's not possible
# to declare '%type <field> $accept'. (Also true for $undefined.) # to declare `%type <field> $accept'. (Also true for $undefined.)
# - Thus, the compiler might complain that the user code assumes the wrong # - Thus, the compiler might complain that the user code assumes the wrong
# type for $$ since the code might assume the type associated with a # type for $$ since the code might assume the type associated with a
# specific union field, which is especially reasonable in C++ since that # specific union field, which is especially reasonable in C++ since that
@@ -1607,6 +1494,115 @@ AT_TEST([glr.cc])
m4_popdef([AT_TEST]) m4_popdef([AT_TEST])
## ----------------------------------------------- ##
## Fix user actions without a trailing semicolon. ##
## ----------------------------------------------- ##
AT_SETUP([[Fix user actions without a trailing semicolon]])
# This feature is undocumented, but we accidentally broke it in 2.3a,
# and there was a complaint at:
# <http://lists.gnu.org/archive/html/bug-bison/2008-11/msg00001.html>.
AT_BISON_OPTION_PUSHDEFS
AT_DATA([input.y],
[[%%
start: test2 test1 test0 testc;
test2
: 'a' { semi; /* TEST:N:2 */ }
| 'b' { if (0) {no_semi} /* TEST:N:2 */ }
| 'c' { if (0) {semi;} /* TEST:N:2 */ }
| 'd' { semi; no_semi /* TEST:Y:2 */ }
| 'e' { semi(); no_semi() /* TEST:Y:2 */ }
| 'f' { semi[]; no_semi[] /* TEST:Y:2 */ }
| 'g' { semi++; no_semi++ /* TEST:Y:2 */ }
| 'h' { {no_semi} no_semi /* TEST:Y:2 */ }
| 'i' { {semi;} no_semi /* TEST:Y:2 */ }
;
test1
: 'a' { semi; // TEST:N:1 ;
} | 'b' { if (0) {no_semi} // TEST:N:1 ;
} | 'c' { if (0) {semi;} // TEST:N:1 ;
} | 'd' { semi; no_semi // TEST:Y:1 ;
} | 'e' { semi(); no_semi() // TEST:Y:1 ;
} | 'f' { semi[]; no_semi[] // TEST:Y:1 ;
} | 'g' { semi++; no_semi++ // TEST:Y:1 ;
} | 'h' { {no_semi} no_semi // TEST:Y:1 ;
} | 'i' { {semi;} no_semi // TEST:Y:1 ;
} ;
test0
: 'a' { semi; // TEST:N:1 {}
} | 'b' { if (0) {no_semi} // TEST:N:1 {}
} | 'c' { if (0) {semi;} // TEST:N:1 {}
} | 'd' { semi; no_semi // TEST:Y:1 {}
} | 'e' { semi(); no_semi() // TEST:Y:1 {}
} | 'f' { semi[]; no_semi[] // TEST:Y:1 {}
} | 'g' { semi++; no_semi++ // TEST:Y:1 {}
} | 'h' { {no_semi} no_semi // TEST:Y:1 {}
} | 'i' { {semi;} no_semi // TEST:Y:1 {}
} ;
testc
: 'a' {
#define TEST_MACRO_N \
[]"broken\" $ @ $$ @$ [];\
string;"}
| 'b' {
no_semi
#define TEST_MACRO_N \
[]"broken\" $ @ $$ @$ [];\
string;"}
]])
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o input.c input.y]], [0], [],
[[input.y:8.48: warning: a ';' might be needed at the end of action code [-Wdeprecated]
input.y:8.48: future versions of Bison will not add the ';'
input.y:9.48: warning: a ';' might be needed at the end of action code [-Wdeprecated]
input.y:9.48: future versions of Bison will not add the ';'
input.y:10.48: warning: a ';' might be needed at the end of action code [-Wdeprecated]
input.y:10.48: future versions of Bison will not add the ';'
input.y:11.48: warning: a ';' might be needed at the end of action code [-Wdeprecated]
input.y:11.48: future versions of Bison will not add the ';'
input.y:12.48: warning: a ';' might be needed at the end of action code [-Wdeprecated]
input.y:12.48: future versions of Bison will not add the ';'
input.y:13.48: warning: a ';' might be needed at the end of action code [-Wdeprecated]
input.y:13.48: future versions of Bison will not add the ';'
input.y:20.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
input.y:20.1: future versions of Bison will not add the ';'
input.y:21.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
input.y:21.1: future versions of Bison will not add the ';'
input.y:22.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
input.y:22.1: future versions of Bison will not add the ';'
input.y:23.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
input.y:23.1: future versions of Bison will not add the ';'
input.y:24.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
input.y:24.1: future versions of Bison will not add the ';'
input.y:25.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
input.y:25.1: future versions of Bison will not add the ';'
input.y:31.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
input.y:31.1: future versions of Bison will not add the ';'
input.y:32.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
input.y:32.1: future versions of Bison will not add the ';'
input.y:33.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
input.y:33.1: future versions of Bison will not add the ';'
input.y:34.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
input.y:34.1: future versions of Bison will not add the ';'
input.y:35.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
input.y:35.1: future versions of Bison will not add the ';'
input.y:36.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
input.y:36.1: future versions of Bison will not add the ';'
]])
AT_MATCHES_CHECK([input.c], [[/\* TEST:N:2 \*/ \}$]], [[3]])
AT_MATCHES_CHECK([input.c], [[/\* TEST:Y:2 \*/ ;\}$]], [[6]])
AT_MATCHES_CHECK([input.c], [[// TEST:N:1 [;{}]*\n\}$]], [[6]])
AT_MATCHES_CHECK([input.c], [[// TEST:Y:1 [;{}]*\n;\}$]], [[12]])
AT_MATCHES_CHECK([input.c], [[#define TEST_MACRO_N \\\n\[\]"broken\\" \$ \@ \$\$ \@\$ \[\];\\\nstring;"\}]], [[2]])
AT_CLEANUP
## -------------------------------------------------- ## ## -------------------------------------------------- ##
## Destroying lookahead assigned by semantic action. ## ## Destroying lookahead assigned by semantic action. ##
## -------------------------------------------------- ## ## -------------------------------------------------- ##
@@ -1641,7 +1637,7 @@ AT_DATA_GRAMMAR([input.y],
// that has set yychar might not always return normally. Instead, // that has set yychar might not always return normally. Instead,
// skeletons must translate before every use of yytoken. // skeletons must translate before every use of yytoken.
start: 'a' accept { USE($1); } ; start: 'a' accept { USE($1); } ;
accept: %empty { accept: /*empty*/ {
assert (yychar == YYEMPTY); assert (yychar == YYEMPTY);
yychar = 'b'; yychar = 'b';
YYACCEPT; YYACCEPT;
+13 -32
View File
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# We need 'config.h'. # We need `config.h'.
CPPFLAGS="-I$abs_top_builddir/lib @CPPFLAGS@" CPPFLAGS="-I$abs_top_builddir/lib @CPPFLAGS@"
# Don't just check if $POSIXLY_CORRECT is set, as Bash, when launched # Don't just check if $POSIXLY_CORRECT is set, as Bash, when launched
@@ -47,40 +47,12 @@ NO_WERROR_CXXFLAGS='@CXXFLAGS@ @WARN_CXXFLAGS@ @WARN_CXXFLAGS_TEST@'
CFLAGS="$NO_WERROR_CFLAGS @WERROR_CFLAGS@" CFLAGS="$NO_WERROR_CFLAGS @WERROR_CFLAGS@"
CXXFLAGS="$NO_WERROR_CXXFLAGS @WERROR_CXXFLAGS@" CXXFLAGS="$NO_WERROR_CXXFLAGS @WERROR_CXXFLAGS@"
# C++ variants break strict aliasing analysis.
NO_STRICT_ALIAS_CXXFLAGS='@NO_STRICT_ALIAS_CXXFLAGS@'
# If 'exit 77'; skip all C++ tests; otherwise ':'. # If 'exit 77'; skip all C++ tests; otherwise ':'.
BISON_CXX_WORKS='@BISON_CXX_WORKS@' BISON_CXX_WORKS='@BISON_CXX_WORKS@'
# Be sure that the C++ compiler is not broken because of gnulib. This
# cannot be checked in configure (gnulib is not parameterized yet),
# and checking this in every C++ test in AC_COMPILE_CXX is too costly.
#
# http://lists.gnu.org/archive/html/bug-bison/2013-06/msg00001.html
#
# FIXME: Check (say 2014) whether this is still needed.
if $BISON_CXX_WORKS; then
# See AT_DATA_SOURCE_PROLOGUE.
cat >conftest.cc <<EOF
#include <config.h>
/* We don't need perfect functions for these tests. */
#undef malloc
#undef memcmp
#undef realloc
#include <iostream>
int main ()
{
std::cout << "Works" << std::endl;
}
EOF
ls
$CXX $CXXFLAGS $CPPFLAGS $LDFLAGS $LIBS -o conftest conftest.cc
case $? in
0);;
*) BISON_CXX_WORKS="as_fn_error 77 cannot-compile-simple-program";;
esac
rm -f conftest*
fi
# Whether the compiler supports POSIXLY_CORRECT defined. # Whether the compiler supports POSIXLY_CORRECT defined.
: ${C_COMPILER_POSIXLY_CORRECT='@C_COMPILER_POSIXLY_CORRECT@'} : ${C_COMPILER_POSIXLY_CORRECT='@C_COMPILER_POSIXLY_CORRECT@'}
: ${CXX_COMPILER_POSIXLY_CORRECT='@CXX_COMPILER_POSIXLY_CORRECT@'} : ${CXX_COMPILER_POSIXLY_CORRECT='@CXX_COMPILER_POSIXLY_CORRECT@'}
@@ -103,6 +75,15 @@ else
CC_IS_CXX=0 CC_IS_CXX=0
fi fi
# In a similar way, handle --release
if "$at_arg_release"; then
BISON_USE_PUSH_FOR_PULL=1
BISON_TEST_XML=1
else
BISON_USE_PUSH_FOR_PULL=0
BISON_TEST_XML=0
fi
## ------- ## ## ------- ##
## Other. ## ## Other. ##
+42 -110
View File
@@ -18,68 +18,6 @@
AT_BANNER([[C++ Features.]]) AT_BANNER([[C++ Features.]])
## --------------- ##
## C++ Locations. ##
## --------------- ##
AT_SETUP([C++ Locations])
AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "lalr1.cc"])
AT_DATA_GRAMMAR([[input.y]],
[[%code {#include <sstream>}
%locations
%debug
%skeleton "lalr1.cc"
%code
{
]AT_YYERROR_DECLARE[
]AT_YYLEX_DECLARE[
}
%%
exp: %empty;
%%
]AT_YYERROR_DEFINE[
]AT_YYLEX_DEFINE[
template <typename T>
bool
check (const T& in, const std::string& s)
{
std::stringstream os;
os << in;
if (os.str () != s)
{
std::cerr << "fail: " << os.str () << ", expected: " << s << std::endl;
return false;
}
return true;
}
int
main (void)
{
int fail = 0;
]AT_YYLTYPE[ loc; fail += check (loc, "1.1");
loc += 10; fail += check (loc, "1.1-10");
loc += -5; fail += check (loc, "1.1-5");
loc -= 5; fail += check (loc, "1.1");
// Check that we don't go below.
// http://lists.gnu.org/archive/html/bug-bison/2013-02/msg00000.html
loc -= 10; fail += check (loc, "1.1");
loc.columns (10); loc.lines (10); fail += check (loc, "1.1-11.0");
loc.lines (-2); fail += check (loc, "1.1-9.0");
loc.lines (-10); fail += check (loc, "1.1");
return !fail;
}
]])
AT_FULL_COMPILE([input])
AT_PARSER_CHECK([./input], 0)
AT_BISON_OPTION_POPDEFS
AT_CLEANUP
## --------------------------- ## ## --------------------------- ##
## C++ Variant-based Symbols. ## ## C++ Variant-based Symbols. ##
## --------------------------- ## ## --------------------------- ##
@@ -90,7 +28,7 @@ AT_KEYWORDS([variant])
AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc" %debug $1]) AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc" %debug $1])
# Store strings and integers in a list of strings. # Store strings and integers in a list of strings.
AT_DATA_GRAMMAR([list.y], AT_DATA_GRAMMAR([list.yy],
[[%skeleton "lalr1.cc" [[%skeleton "lalr1.cc"
%define api.value.type variant %define api.value.type variant
%define parse.assert %define parse.assert
@@ -154,7 +92,8 @@ int main()
} }
]]) ]])
AT_FULL_COMPILE([list]) AT_BISON_CHECK([-o list.cc list.yy])
AT_COMPILE_CXX([list], [$NO_STRICT_ALIAS_CXXFLAGS list.cc])
AT_PARSER_CHECK([./list], 0, [], AT_PARSER_CHECK([./list], 0, [],
[12 [12
123 123
@@ -176,7 +115,7 @@ m4_pushdef([AT_TEST],
AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc" %debug $1]) AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc" %debug $1])
# Store strings and integers in a list of strings. # Store strings and integers in a list of strings.
AT_DATA_GRAMMAR([list.y], AT_DATA_GRAMMAR([list.yy],
[[%debug [[%debug
%skeleton "lalr1.cc" %skeleton "lalr1.cc"
%define api.value.type variant %define api.value.type variant
@@ -311,7 +250,8 @@ namespace yy
]AT_MAIN_DEFINE[ ]AT_MAIN_DEFINE[
]]) ]])
AT_FULL_COMPILE([list]) AT_BISON_CHECK([-o list.cc list.yy])
AT_COMPILE_CXX([list], [$NO_STRICT_ALIAS_CXXFLAGS list.cc])
AT_PARSER_CHECK([./list], 0, AT_PARSER_CHECK([./list], 0,
[(0, 1, 2, 4) [(0, 1, 2, 4)
]) ])
@@ -325,8 +265,8 @@ AT_TEST([%define parse.assert])
AT_TEST([%locations %define parse.assert]) AT_TEST([%locations %define parse.assert])
AT_TEST([[%define parse.assert %code {\n#define TWO_STAGE_BUILD\n}]]) AT_TEST([[%define parse.assert %code {\n#define TWO_STAGE_BUILD\n}]])
AT_TEST([[%define parse.assert %define api.token.constructor]]) AT_TEST([[%define parse.assert %define api.token.constructor]])
AT_TEST([[%define parse.assert %define api.token.constructor %define api.token.prefix {TOK_}]]) AT_TEST([[%define parse.assert %define api.token.constructor %define api.token.prefix "TOK_"]])
AT_TEST([[%locations %define parse.assert %define api.token.constructor %define api.token.prefix {TOK_}]]) AT_TEST([[%locations %define parse.assert %define api.token.constructor %define api.token.prefix "TOK_"]])
m4_popdef([AT_TEST]) m4_popdef([AT_TEST])
@@ -423,10 +363,10 @@ AT_CHECK_DOXYGEN([Private])
# is specified, then Bison should accept the input, but compilation will fail, # is specified, then Bison should accept the input, but compilation will fail,
# so don't check compilation. # so don't check compilation.
m4_pushdef([AT_TEST], m4_pushdef([AT_TEST],
[AT_BISON_OPTION_PUSHDEFS([%language "C++" %define api.namespace {$1}]) [AT_BISON_OPTION_PUSHDEFS([%language "C++" %define api.namespace "$1"])
AT_DATA_GRAMMAR([[input.y]], AT_DATA_GRAMMAR([[input.y]],
[[%language "C++" [[%language "C++"
%define api.namespace {]$1[} %define api.namespace "]$1["
%union { int i; } %union { int i; }
%define global_tokens_and_yystype %define global_tokens_and_yystype
%locations %locations
@@ -482,8 +422,8 @@ AT_CLEANUP
AT_SETUP([[Syntactically invalid namespace references]]) AT_SETUP([[Syntactically invalid namespace references]])
AT_TEST([[:foo:bar]], [[-]]) AT_TEST([[:foo:bar]], [[-]])
AT_TEST([[foo: :bar]], [[-]]) AT_TEST([[foo: :bar]], [[-]])
# This one is interesting because '[3]' is encoded as '@<:@3@:>@', which # This one is interesting because `[3]' is encoded as `@<:@3@:>@', which
# contains single occurrences of ':'. # contains single occurrences of `:'.
AT_TEST([[foo[3]::bar::baz]], [[-]]) AT_TEST([[foo[3]::bar::baz]], [[-]])
AT_TEST([[foo::bar,baz]], [[-]]) AT_TEST([[foo::bar,baz]], [[-]])
AT_TEST([[foo::bar::(baz /* Pacify Emacs ) */]], [[-]]) AT_TEST([[foo::bar::(baz /* Pacify Emacs ) */]], [[-]])
@@ -675,42 +615,14 @@ $1
/// A class that counts its number of instances. /// A class that counts its number of instances.
struct Object struct Object
{ {
char val;
Object (char v)
: val (v)
{
Object::instances.push_back(this);
log (this, "Object::Object");
}
Object ()
: val ('?')
{
Object::instances.push_back(this);
log (this, "Object::Object");
}
Object& operator= (char v)
{
val = v;
return *this;
}
~Object ()
{
Object::instances.remove (this);
log (this, "Object::~Object");
}
// Static part.
typedef std::list<const Object*> objects; typedef std::list<const Object*> objects;
static objects instances; static objects instances;
char val;
static bool static bool
empty () empty ()
{ {
return instances.empty (); return instances.empty();
} }
static void static void
@@ -733,6 +645,26 @@ $1
std::cerr << " }" << std::endl; std::cerr << " }" << std::endl;
} }
} }
Object (char v)
: val (v)
{
instances.push_back(this);
log (this, "Object::Object");
}
Object ()
: val ('?')
{
instances.push_back(this);
log (this, "Object::Object");
}
~Object ()
{
instances.remove(this);
log (this, "Object::~Object");
}
}; };
} }
@@ -790,16 +722,16 @@ list:
; ;
item: item:
'a' { $$][ = $][1; } 'a' { $$][ = $][1; }
| 'e' { YYUSE ($][$); YYUSE($][1); error ("syntax error"); } | 'e' { YYUSE ($][$); YYUSE($][1); error ("syntax error"); }
// Not just 'E', otherwise we reduce when 'E' is the lookahead, and // Not just 'E', otherwise we reduce when 'E' is the lookahead, and
// then the stack is emptied, defeating the point of the test. // then the stack is emptied, defeating the point of the test.
| 'E' 'a' { YYUSE($][1); $][$ = $][2; } | 'E' 'a' { YYUSE($][1); $][$ = $][2; }
| 'R' { ]AT_VARIANT_IF([], [$][$ = YY_NULL; delete $][1]; )[YYERROR; } | 'R' { $][$ = YY_NULL; ]AT_VARIANT_IF([], [delete $][1]; )[YYERROR; }
| 'p' { $][$ = $][1; } | 'p' { $][$ = $][1; }
| 's' { $][$ = $][1; throw std::runtime_error ("reduction"); } | 's' { $][$ = $][1; throw std::runtime_error ("reduction"); }
| 'T' { ]AT_VARIANT_IF([], [$][$ = YY_NULL; delete $][1]; )[YYABORT; } | 'T' { $][$ = YY_NULL; ]AT_VARIANT_IF([], [delete $][1]; )[YYABORT; }
| error { ]AT_VARIANT_IF([], [$][$ = YY_NULL; ])[yyerrok; } | error { $][$ = YY_NULL; yyerrok; }
; ;
%% %%
@@ -872,7 +804,7 @@ main (int argc, const char *argv[])
} }
]]) ]])
AT_BISON_CHECK([[-o input.cc --report=all input.yy]]) AT_BISON_CHECK([[-o input.cc --report=all input.yy]])
AT_COMPILE_CXX([[input]]) AT_COMPILE_CXX([input], [[$NO_STRICT_ALIAS_CXXFLAGS input.cc]])
AT_PARSER_CHECK([[./input aaaas]], [[2]], [[]], AT_PARSER_CHECK([[./input aaaas]], [[2]], [[]],
[[exception caught: reduction [[exception caught: reduction
+48 -48
View File
@@ -27,11 +27,11 @@
# _AT_DATA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES]) # _AT_DATA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])
# ----------------------------------------------- # -----------------------------------------------
# Produce 'calc.y' and, if %defines was specified, 'calc-lex.c' or # Produce `calc.y' and, if %defines was specified, `calc-lex.c' or
# 'calc-lex.cc'. # `calc-lex.cc'.
# #
# Don't call this macro directly, because it contains some occurrences # Don't call this macro directly, because it contains some occurrences
# of '$1' etc. which will be interpreted by m4. So you should call it # of `$1' etc. which will be interpreted by m4. So you should call it
# with $1, $2, and $3 as arguments, which is what AT_DATA_CALC_Y does. # with $1, $2, and $3 as arguments, which is what AT_DATA_CALC_Y does.
# #
# When %defines is not passed, generate a single self-contained file. # When %defines is not passed, generate a single self-contained file.
@@ -72,12 +72,10 @@ main (int argc, const char **argv)
int count = 0; int count = 0;
int status; int status;
/* This used to be alarm (10), but that isn't enough time for a July /* This used to be alarm (10), but that isn't enough time for
1995 vintage DEC Alphastation 200 4/100 system, according to a July 1995 vintage DEC Alphastation 200 4/100 system,
Nelson H. F. Beebe. 100 seconds was enough for regular users, according to Nelson H. F. Beebe. 100 seconds is enough. */
but the Hydra build farm, which is heavily loaded needs more. */ alarm (100);
alarm (200);
if (argc == 2) if (argc == 2)
input = fopen (argv[1], "r"); input = fopen (argv[1], "r");
@@ -90,7 +88,8 @@ main (int argc, const char **argv)
return 3; return 3;
} }
]AT_SKEL_CC_IF([], [AT_DEBUG_IF([ ]AT_NAME_PREFIX[debug = 1;])])[ ]AT_SKEL_CC_IF([], [m4_bmatch([$4], [%debug],
[ ]AT_NAME_PREFIX[debug = 1;])])[
status = ]AT_NAME_PREFIX[parse (]AT_PARAM_IF([[&result, &count]])[); status = ]AT_NAME_PREFIX[parse (]AT_PARAM_IF([[&result, &count]])[);
if (fclose (input)) if (fclose (input))
perror ("fclose"); perror ("fclose");
@@ -134,7 +133,7 @@ unget_char (]AT_YYLEX_PRE_FORMALS[ int c)
{ {
]AT_USE_LEX_ARGS[; ]AT_USE_LEX_ARGS[;
]AT_LOCATION_IF([ ]AT_LOCATION_IF([
/* Wrong when C == '\n'. */ /* Wrong when C == `\n'. */
AT_LOC = last_yylloc; AT_LOC = last_yylloc;
])[ ])[
ungetc (c, input); ungetc (c, input);
@@ -366,8 +365,8 @@ m4_popdef([AT_CALC_LEX])
# AT_DATA_CALC_Y([BISON-OPTIONS]) # AT_DATA_CALC_Y([BISON-OPTIONS])
# ------------------------------- # -------------------------------
# Produce 'calc.y' and, if %defines was specified, 'calc-lex.c' or # Produce `calc.y' and, if %defines was specified, `calc-lex.c' or
# 'calc-lex.cc'. # `calc-lex.cc'.
m4_define([AT_DATA_CALC_Y], m4_define([AT_DATA_CALC_Y],
[_AT_DATA_CALC_Y($[1], $[2], $[3], [$1]) [_AT_DATA_CALC_Y($[1], $[2], $[3], [$1])
]) ])
@@ -376,9 +375,9 @@ m4_define([AT_DATA_CALC_Y],
# _AT_CHECK_CALC(BISON-OPTIONS, INPUT, [NUM-STDERR-LINES]) # _AT_CHECK_CALC(BISON-OPTIONS, INPUT, [NUM-STDERR-LINES])
# -------------------------------------------------------- # --------------------------------------------------------
# Run 'calc' on INPUT and expect no STDOUT nor STDERR. # Run `calc' on INPUT and expect no STDOUT nor STDERR.
# #
# If BISON-OPTIONS contains '%debug' but not '%glr-parser', then # If BISON-OPTIONS contains `%debug' but not `%glr-parser', then
# #
# NUM-STDERR-LINES is the number of expected lines on stderr. # NUM-STDERR-LINES is the number of expected lines on stderr.
# Currently this is ignored, though, since the output format is fluctuating. # Currently this is ignored, though, since the output format is fluctuating.
@@ -397,7 +396,7 @@ AT_PARSER_CHECK([./calc input], 0, [], [stderr])
# [NUM-STDERR-LINES], # [NUM-STDERR-LINES],
# [VERBOSE-AND-LOCATED-ERROR-MESSAGE]) # [VERBOSE-AND-LOCATED-ERROR-MESSAGE])
# --------------------------------------------------------- # ---------------------------------------------------------
# Run 'calc' on INPUT, and expect a 'syntax error' message. # Run `calc' on INPUT, and expect a `syntax error' message.
# #
# If INPUT starts with a slash, it is used as absolute input file name, # If INPUT starts with a slash, it is used as absolute input file name,
# otherwise as contents. # otherwise as contents.
@@ -405,14 +404,14 @@ AT_PARSER_CHECK([./calc input], 0, [], [stderr])
# NUM-STDERR-LINES is the number of expected lines on stderr. # NUM-STDERR-LINES is the number of expected lines on stderr.
# Currently this is ignored, though, since the output format is fluctuating. # Currently this is ignored, though, since the output format is fluctuating.
# #
# If BISON-OPTIONS contains '%location', then make sure the ERROR-LOCATION # If BISON-OPTIONS contains `%location', then make sure the ERROR-LOCATION
# is correctly output on stderr. # is correctly output on stderr.
# #
# If BISON-OPTIONS contains '%define parse.error verbose', then make sure the # If BISON-OPTIONS contains `%define parse.error verbose', then make sure the
# IF-YYERROR-VERBOSE message is properly output after 'syntax error, ' # IF-YYERROR-VERBOSE message is properly output after `syntax error, '
# on STDERR. # on STDERR.
# #
# If BISON-OPTIONS contains '%debug' but not '%glr', then NUM-STDERR-LINES # If BISON-OPTIONS contains `%debug' but not `%glr', then NUM-STDERR-LINES
# is the number of expected lines on stderr. # is the number of expected lines on stderr.
m4_define([_AT_CHECK_CALC_ERROR], m4_define([_AT_CHECK_CALC_ERROR],
[m4_bmatch([$3], [^/], [m4_bmatch([$3], [^/],
@@ -449,7 +448,7 @@ AT_DATA([[expout]],
AT_YYERROR_SEES_LOC_IF([], AT_YYERROR_SEES_LOC_IF([],
[[sed 's/^[-0-9.]*: //' expout >at-expout [[sed 's/^[-0-9.]*: //' expout >at-expout
mv at-expout expout]]) mv at-expout expout]])
# 4. If error-verbose is not used, strip the', unexpected....' part. # 4. If error-verbose is not used, strip the`, unexpected....' part.
m4_bmatch([$1], [%define parse.error verbose], [], m4_bmatch([$1], [%define parse.error verbose], [],
[[sed 's/syntax error, .*$/syntax error/' expout >at-expout [[sed 's/syntax error, .*$/syntax error/' expout >at-expout
mv at-expout expout]]) mv at-expout expout]])
@@ -479,7 +478,7 @@ m4_define([AT_CHECK_SPACES],
# AT_CHECK_CALC([BISON-OPTIONS]) # AT_CHECK_CALC([BISON-OPTIONS])
# ------------------------------ # ------------------------------
# Start a testing chunk which compiles 'calc' grammar with # Start a testing chunk which compiles `calc' grammar with
# BISON-OPTIONS, and performs several tests over the parser. # BISON-OPTIONS, and performs several tests over the parser.
m4_define([AT_CHECK_CALC], m4_define([AT_CHECK_CALC],
[m4_ifval([$2], [m4_fatal([$0: expected a single argument])]) [m4_ifval([$2], [m4_fatal([$0: expected a single argument])])
@@ -539,7 +538,7 @@ _AT_CHECK_CALC_ERROR([$1], [1], [/dev/null], [4],
# - (* * *): nothing to pop, a lot to discard # - (* * *): nothing to pop, a lot to discard
# - (1 + 2 * *): some to pop and discard # - (1 + 2 * *): some to pop and discard
# #
# - test the action associated to 'error' # - test the action associated to `error'
# #
# - check the lookahead that triggers an error is not discarded # - check the lookahead that triggers an error is not discarded
# when we enter error recovery. Below, the lookahead causing the # when we enter error recovery. Below, the lookahead causing the
@@ -588,7 +587,7 @@ AT_BANNER([[Simple LALR(1) Calculator.]])
# AT_CHECK_CALC_LALR([BISON-OPTIONS]) # AT_CHECK_CALC_LALR([BISON-OPTIONS])
# ----------------------------------- # -----------------------------------
# Start a testing chunk which compiles 'calc' grammar with # Start a testing chunk which compiles `calc' grammar with
# BISON-OPTIONS, and performs several tests over the parser. # BISON-OPTIONS, and performs several tests over the parser.
m4_define([AT_CHECK_CALC_LALR], m4_define([AT_CHECK_CALC_LALR],
[AT_CHECK_CALC($@)]) [AT_CHECK_CALC($@)])
@@ -607,17 +606,17 @@ AT_CHECK_CALC_LALR([%define api.pure full %locations])
AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure full %locations]) AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure full %locations])
AT_CHECK_CALC_LALR([%define parse.error verbose %locations]) AT_CHECK_CALC_LALR([%define parse.error verbose %locations])
AT_CHECK_CALC_LALR([%define parse.error verbose %locations %defines %define api.prefix {calc} %verbose %yacc]) AT_CHECK_CALC_LALR([%define parse.error verbose %locations %defines %define api.prefix "calc" %verbose %yacc])
AT_CHECK_CALC_LALR([%define parse.error verbose %locations %defines %name-prefix "calc" %define api.token.prefix {TOK_} %verbose %yacc]) AT_CHECK_CALC_LALR([%define parse.error verbose %locations %defines %name-prefix "calc" %define api.token.prefix "TOK_" %verbose %yacc])
AT_CHECK_CALC_LALR([%debug]) AT_CHECK_CALC_LALR([%debug])
AT_CHECK_CALC_LALR([%define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc]) AT_CHECK_CALC_LALR([%define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
AT_CHECK_CALC_LALR([%define parse.error verbose %debug %locations %defines %define api.prefix {calc} %verbose %yacc]) AT_CHECK_CALC_LALR([%define parse.error verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc])
AT_CHECK_CALC_LALR([%define api.pure full %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc]) AT_CHECK_CALC_LALR([%define api.pure full %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure full %define parse.error verbose %debug %locations %defines %define api.prefix {calc} %verbose %yacc]) AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure full %define parse.error verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc])
AT_CHECK_CALC_LALR([%define api.pure %define parse.error verbose %debug %locations %defines %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}]) AT_CHECK_CALC_LALR([%define api.pure %define parse.error verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
# ----------------------- # # ----------------------- #
@@ -628,7 +627,7 @@ AT_BANNER([[Simple GLR Calculator.]])
# AT_CHECK_CALC_GLR([BISON-OPTIONS]) # AT_CHECK_CALC_GLR([BISON-OPTIONS])
# ---------------------------------- # ----------------------------------
# Start a testing chunk which compiles 'calc' grammar with # Start a testing chunk which compiles `calc' grammar with
# BISON-OPTIONS and %glr-parser, and performs several tests over the parser. # BISON-OPTIONS and %glr-parser, and performs several tests over the parser.
m4_define([AT_CHECK_CALC_GLR], m4_define([AT_CHECK_CALC_GLR],
[AT_CHECK_CALC([%glr-parser] $@)]) [AT_CHECK_CALC([%glr-parser] $@)])
@@ -639,7 +638,7 @@ AT_CHECK_CALC_GLR()
AT_CHECK_CALC_GLR([%defines]) AT_CHECK_CALC_GLR([%defines])
AT_CHECK_CALC_GLR([%locations]) AT_CHECK_CALC_GLR([%locations])
AT_CHECK_CALC_GLR([%name-prefix "calc"]) AT_CHECK_CALC_GLR([%name-prefix "calc"])
AT_CHECK_CALC_GLR([%define api.prefix {calc}]) AT_CHECK_CALC_GLR([%define api.prefix "calc"])
AT_CHECK_CALC_GLR([%verbose]) AT_CHECK_CALC_GLR([%verbose])
AT_CHECK_CALC_GLR([%yacc]) AT_CHECK_CALC_GLR([%yacc])
AT_CHECK_CALC_GLR([%define parse.error verbose]) AT_CHECK_CALC_GLR([%define parse.error verbose])
@@ -651,12 +650,12 @@ AT_CHECK_CALC_GLR([%define parse.error verbose %locations %defines %name-prefix
AT_CHECK_CALC_GLR([%debug]) AT_CHECK_CALC_GLR([%debug])
AT_CHECK_CALC_GLR([%define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc]) AT_CHECK_CALC_GLR([%define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
AT_CHECK_CALC_GLR([%define parse.error verbose %debug %locations %defines %define api.prefix {calc} %define api.token.prefix {TOK_} %verbose %yacc]) AT_CHECK_CALC_GLR([%define parse.error verbose %debug %locations %defines %define api.prefix "calc" %define api.token.prefix "TOK_" %verbose %yacc])
AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc]) AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}]) AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %defines %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}]) AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
# ----------------------------- # # ----------------------------- #
@@ -670,26 +669,26 @@ AT_CHECK_CALC([%skeleton "lalr1.cc" %defines])
# AT_CHECK_CALC_LALR1_CC([BISON-OPTIONS]) # AT_CHECK_CALC_LALR1_CC([BISON-OPTIONS])
# --------------------------------------- # ---------------------------------------
# Start a testing chunk which compiles 'calc' grammar with # Start a testing chunk which compiles `calc' grammar with
# the C++ skeleton, and performs several tests over the parser. # the C++ skeleton, and performs several tests over the parser.
m4_define([AT_CHECK_CALC_LALR1_CC], m4_define([AT_CHECK_CALC_LALR1_CC],
[AT_CHECK_CALC([%language "C++"] $@)]) [AT_CHECK_CALC([%language "C++"] $@)])
AT_CHECK_CALC_LALR1_CC([]) AT_CHECK_CALC_LALR1_CC([])
AT_CHECK_CALC_LALR1_CC([%locations]) AT_CHECK_CALC_LALR1_CC([%locations])
AT_CHECK_CALC_LALR1_CC([%locations %define api.location.type {Span}]) AT_CHECK_CALC_LALR1_CC([%locations %define api.location.type Span])
AT_CHECK_CALC_LALR1_CC([%defines %locations %define parse.error verbose %name-prefix "calc" %verbose %yacc]) AT_CHECK_CALC_LALR1_CC([%defines %locations %define parse.error verbose %name-prefix "calc" %verbose %yacc])
AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %define api.prefix {calc} %verbose %yacc]) AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %define api.prefix "calc" %verbose %yacc])
AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc]) AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc])
AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %debug %define api.prefix {calc} %verbose %yacc]) AT_CHECK_CALC_LALR1_CC([%locations %pure-parser %define parse.error verbose %debug %define api.prefix "calc" %verbose %yacc])
AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %debug %define api.prefix {calc} %define api.token.prefix {TOK_} %verbose %yacc]) AT_CHECK_CALC_LALR1_CC([%locations %pure-parser %define parse.error verbose %debug %define api.prefix "calc" %define api.token.prefix "TOK_" %verbose %yacc])
AT_CHECK_CALC_LALR1_CC([%defines %locations %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}]) AT_CHECK_CALC_LALR1_CC([%defines %locations %pure-parser %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
AT_CHECK_CALC_LALR1_CC([%define parse.error verbose %debug %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}]) AT_CHECK_CALC_LALR1_CC([%pure-parser %define parse.error verbose %debug %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
AT_CHECK_CALC_LALR1_CC([%defines %locations %define parse.error verbose %debug %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}]) AT_CHECK_CALC_LALR1_CC([%defines %locations %pure-parser %define parse.error verbose %debug %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
@@ -704,21 +703,22 @@ AT_CHECK_CALC([%skeleton "glr.cc"])
# AT_CHECK_CALC_GLR_CC([BISON-OPTIONS]) # AT_CHECK_CALC_GLR_CC([BISON-OPTIONS])
# ------------------------------------- # -------------------------------------
# Start a testing chunk which compiles 'calc' grammar with # Start a testing chunk which compiles `calc' grammar with
# the GLR C++ skeleton, and performs several tests over the parser. # the GLR C++ skeleton, and performs several tests over the parser.
m4_define([AT_CHECK_CALC_GLR_CC], m4_define([AT_CHECK_CALC_GLR_CC],
[AT_CHECK_CALC([%language "C++" %glr-parser] $@)]) [AT_CHECK_CALC([%language "C++" %glr-parser] $@)])
AT_CHECK_CALC_GLR_CC([]) AT_CHECK_CALC_GLR_CC([])
AT_CHECK_CALC_GLR_CC([%locations]) AT_CHECK_CALC_GLR_CC([%locations])
AT_CHECK_CALC_GLR_CC([%locations %define api.location.type {Span}]) AT_CHECK_CALC_GLR_CC([%locations %define api.location.type Span])
AT_CHECK_CALC_GLR_CC([%defines %define parse.error verbose %name-prefix "calc" %verbose %yacc]) AT_CHECK_CALC_GLR_CC([%defines %define parse.error verbose %name-prefix "calc" %verbose %yacc])
AT_CHECK_CALC_GLR_CC([%define parse.error verbose %define api.prefix {calc} %verbose %yacc]) AT_CHECK_CALC_GLR_CC([%define parse.error verbose %define api.prefix "calc" %verbose %yacc])
AT_CHECK_CALC_GLR_CC([%debug]) AT_CHECK_CALC_GLR_CC([%debug])
AT_CHECK_CALC_GLR_CC([%define parse.error verbose %debug %name-prefix "calc" %verbose %yacc]) AT_CHECK_CALC_GLR_CC([%define parse.error verbose %debug %name-prefix "calc" %verbose %yacc])
AT_CHECK_CALC_GLR_CC([%define parse.error verbose %debug %name-prefix "calc" %define api.token.prefix {TOK_} %verbose %yacc])
AT_CHECK_CALC_GLR_CC([%locations %defines %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}]) AT_CHECK_CALC_GLR_CC([%pure-parser %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc])
AT_CHECK_CALC_GLR_CC([%locations %defines %define parse.error verbose %debug %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}]) AT_CHECK_CALC_GLR_CC([%pure-parser %define parse.error verbose %debug %name-prefix "calc" %define api.token.prefix "TOK_" %verbose %yacc])
AT_CHECK_CALC_GLR_CC([%locations %defines %pure-parser %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
AT_CHECK_CALC_GLR_CC([%locations %defines %pure-parser %define parse.error verbose %debug %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
+86 -300
View File
@@ -17,155 +17,42 @@
AT_BANNER([[Conflicts.]]) AT_BANNER([[Conflicts.]])
## ----------------- ##
## Precedence groups ##
## ----------------- ##
# Sample use case of precedence groups and relations, working.
AT_SETUP([Precedence groups])
AT_DATA_GRAMMAR([[input.y]],
[[%token CARET "^"
%token NUM BOOL '^' OR AND
%left '+' '-'
%gprec {
%right CARET
}
%gprec boolean {
%left OR
%left AND
}
%left '*' '/'
%precr boolean >> "^"
%precr CARET > '*' '/' '-' '+'
%%
stmt:
exp
| bool_exp
exp:
NUM
| exp '+' exp
| exp '-' exp
| exp '*' exp
| exp '/' exp
| exp "^" exp
bool_exp:
BOOL
| bool_exp AND bool_exp
| bool_exp OR bool_exp
| bool_exp CARET bool_exp
]])
AT_BISON_CHECK([[--report=all -o input.c input.y]], 0, [])
AT_CLEANUP
## -------------------------------- ##
## Conflicting precedence relations ##
## -------------------------------- ##
AT_SETUP([Conflicting precedence relations])
AT_DATA_GRAMMAR([[input.y]],
[[%token TOKEN
%precedence A
%precedence B
%precedence C
%precedence D E
%gprec group {
%precedence F
%precedence G
}
%precr B = C
%precr A > B
%precr C > B
%precr F > G
%precr F > A
%%
exp:
TOKEN
| exp A exp
| exp B exp
| exp C exp
| exp D exp
| exp E exp
| exp F exp
| exp G exp
]])
AT_BISON_CHECK([[-Wall -o input.c input.y]], 0, [],
[[input.y:20.10: warning: contradicting declaration: B = C is in conflict with the previous declaration: B > C [-Wprecedence]
input.y:21.10: warning: contradicting declaration: A > B is in conflict with the previous declaration: A < B [-Wprecedence]
input.y:22.10: warning: contradicting declaration: C > B is in conflict with the previous declaration: C = B [-Wprecedence]
input.y:23.10: warning: contradicting declaration: F > G is in conflict with the previous declaration: F < G [-Wprecedence]
input.y: warning: 27 shift/reduce conflicts [-Wconflicts-sr]
]])
AT_CLEANUP
## ------------------------------ ## ## ------------------------------ ##
## Duplicate precedence relations ## ## Useless associativity warning. ##
## ------------------------------ ## ## ------------------------------ ##
AT_SETUP([Duplicate precedence relations]) AT_SETUP([Useless associativity warning])
AT_DATA_GRAMMAR([[input.y]], AT_DATA([[input.y]],
[[%token TOKEN [[%token T
%precedence A %left A B
%precedence B %right C
%precedence C %nonassoc D
%precedence D E %precedence E
%gprec group {
%precedence F
%precedence G
}
%precr D = E
%precr B > A
%precr C > B
%precr G > F
%precr F > A
%precr C > group
%precr C > F
%% %%
exp: e: T A T
TOKEN | T B T
| exp A exp | T C T
| exp B exp | T D T
| exp C exp | T E T
| exp D exp ;
| exp E exp
| exp F exp
| exp G exp
]]) ]])
AT_BISON_CHECK([[-Wall -o input.c input.y]], 0, [], AT_BISON_CHECK([input.y], 0, [],
[[input.y:20.10: warning: duplicate declaration of the precedence relationship D = E [-Wprecedence] [[input.y:5.13: warning: useless precedence for E [-Wother]
input.y:20.10: warning: duplicate declaration of the precedence relationship E = D [-Wprecedence] input.y:2.7: warning: useless associativity for A [-Wother]
input.y:21.10: warning: duplicate declaration of the precedence relationship B > A [-Wprecedence] input.y:2.9: warning: useless associativity for B [-Wother]
input.y:22.10: warning: duplicate declaration of the precedence relationship C > B [-Wprecedence] input.y:3.8: warning: useless associativity for C [-Wother]
input.y:23.10: warning: duplicate declaration of the precedence relationship G > F [-Wprecedence] input.y:4.11: warning: useless associativity for D [-Wother]
input.y:26.10: warning: duplicate declaration of the precedence relationship C > F [-Wprecedence]
input.y: warning: 23 shift/reduce conflicts [-Wconflicts-sr]
]]) ]])
AT_CLEANUP AT_CLEANUP
## ------------------------ ##
## ------------------------- ## ## Token declaration order. ##
## Token declaration order. ## ## ------------------------ ##
## ------------------------- ##
# This test checks that token are declared left to right when in a precedence # This test checks that token are declared left to right when in a precedence
# statement. # statement.
@@ -223,7 +110,27 @@ int main (void)
} }
]]) ]])
AT_BISON_CHECK([-o input.c input.y]) AT_BISON_CHECK([-o input.c input.y], [], [],
[[input.y:24.13: warning: useless precedence for R [-Wother]
input.y:24.15: warning: useless precedence for S [-Wother]
input.y:24.17: warning: useless precedence for T [-Wother]
input.y:24.19: warning: useless precedence for U [-Wother]
input.y:25.13: warning: useless precedence for V [-Wother]
input.y:25.15: warning: useless precedence for W [-Wother]
input.y:18.8: warning: useless associativity for E [-Wother]
input.y:18.10: warning: useless associativity for F [-Wother]
input.y:18.12: warning: useless associativity for G [-Wother]
input.y:19.8: warning: useless associativity for H [-Wother]
input.y:19.10: warning: useless associativity for I [-Wother]
input.y:20.8: warning: useless associativity for J [-Wother]
input.y:21.8: warning: useless associativity for K [-Wother]
input.y:22.8: warning: useless associativity for L [-Wother]
input.y:22.10: warning: useless associativity for M [-Wother]
input.y:22.12: warning: useless associativity for N [-Wother]
input.y:23.11: warning: useless associativity for O [-Wother]
input.y:23.13: warning: useless associativity for P [-Wother]
input.y:23.15: warning: useless associativity for Q [-Wother]
]])
AT_COMPILE([input]) AT_COMPILE([input])
AT_PARSER_CHECK([./input]) AT_PARSER_CHECK([./input])
@@ -233,127 +140,6 @@ AT_BISON_OPTION_POPDEFS
AT_CLEANUP AT_CLEANUP
## --------------------------------------------------- ##
## Token declaration order: literals vs. identifiers. ##
## --------------------------------------------------- ##
# This test checks that when several tokens are declared by the same keyword,
# some of them defined as a character ('a'), others as simple textual reference
# (A), they are declared correctly left to right.
# Previously, the following test would declare the states in the order 'o' 'p'
# M N, instead of M N 'o' 'p'.
AT_SETUP([Token declaration order: literals vs. identifiers])
AT_DATA_GRAMMAR([[input.y]],
[[%token 'a' 'b' C D
%token E F 'g' 'h'
%right 'i' 'j' K L
%right M N 'o' 'p'
%%
exp: 'a'
| 'b'
| C
| D
| E
| F
| 'g'
| 'h'
| 'i'
| 'j'
| K
| L
| M
| N
| 'o'
| 'p'
;
%%
]])
AT_BISON_CHECK([[--report=all -o input.c input.y]], 0, [], [ignore])
AT_CHECK([[cat input.output | sed -n '/^State 0$/,/^State 1$/p']], 0,
[[State 0
0 $accept: . exp $end
1 exp: . 'a'
2 | . 'b'
3 | . C
4 | . D
5 | . E
6 | . F
7 | . 'g'
8 | . 'h'
9 | . 'i'
10 | . 'j'
11 | . K
12 | . L
13 | . M
14 | . N
15 | . 'o'
16 | . 'p'
'a' shift, and go to state 1
'b' shift, and go to state 2
C shift, and go to state 3
D shift, and go to state 4
E shift, and go to state 5
F shift, and go to state 6
'g' shift, and go to state 7
'h' shift, and go to state 8
'i' shift, and go to state 9
'j' shift, and go to state 10
K shift, and go to state 11
L shift, and go to state 12
M shift, and go to state 13
N shift, and go to state 14
'o' shift, and go to state 15
'p' shift, and go to state 16
exp go to state 17
State 1
]])
AT_CLEANUP
## ------------------------------- ##
## Useless associativity warning. ##
## ------------------------------- ##
AT_SETUP([Useless associativity warning])
AT_DATA([[input.y]],
[[%token EQ "=" PL "+" ST "*" LP "("
%nonassoc "="
%left "+"
%left "*"
%precedence "("
%%
stmt:
exp
| "var" "=" exp
;
exp:
exp "+" exp
| exp "*" "num"
| "(" exp ")"
| "num"
;
]])
AT_BISON_CHECK([-Wprecedence input.y], 0, [],
[[input.y:2.1-9: warning: useless precedence and associativity for "=" [-Wprecedence]
input.y:4.1-5: warning: useless associativity for "*", use %precedence [-Wprecedence]
input.y:5.1-11: warning: useless precedence for "(" [-Wprecedence]
]])
AT_CLEANUP
## ---------------------------- ## ## ---------------------------- ##
## Useless precedence warning. ## ## Useless precedence warning. ##
## ---------------------------- ## ## ---------------------------- ##
@@ -361,7 +147,7 @@ AT_CLEANUP
AT_SETUP([Useless precedence warning]) AT_SETUP([Useless precedence warning])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%token A B U V W X Y Z [[%token A B
%precedence Z %precedence Z
%left X %left X
%precedence Y %precedence Y
@@ -388,19 +174,19 @@ f: B
; ;
]]) ]])
AT_BISON_CHECK([-Wprecedence -fcaret -o input.c input.y], 0, [], AT_BISON_CHECK([-fcaret -o input.c input.y], 0, [],
[[input.y:7.1-9: warning: useless precedence and associativity for U [-Wprecedence] [[input.y:2.13: warning: useless precedence for Z [-Wother]
%nonassoc U
^^^^^^^^^
input.y:6.1-6: warning: useless precedence and associativity for V [-Wprecedence]
%right V
^^^^^^
input.y:5.1-5: warning: useless precedence and associativity for W [-Wprecedence]
%left W
^^^^^
input.y:2.1-11: warning: useless precedence for Z [-Wprecedence]
%precedence Z %precedence Z
^^^^^^^^^^^ ^
input.y:5.7: warning: useless associativity for W [-Wother]
%left W
^
input.y:6.8: warning: useless associativity for V [-Wother]
%right V
^
input.y:7.11: warning: useless associativity for U [-Wother]
%nonassoc U
^
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -425,7 +211,7 @@ e: 'e' | /* Nothing. */;
]]) ]])
AT_BISON_CHECK([-o input.c input.y], 0, [], AT_BISON_CHECK([-o input.c input.y], 0, [],
[[input.y:4.9: warning: rule useless in parser due to conflicts [-Wother] [[input.y:4.9: warning: rule useless in parser due to conflicts: e: /* empty */ [-Wother]
]]) ]])
AT_BISON_CHECK([-fcaret -o input.c input.y], 0, [], AT_BISON_CHECK([-fcaret -o input.c input.y], 0, [],
@@ -1153,7 +939,7 @@ cond:
AT_BISON_CHECK([-o input.c input.y], 0, [], AT_BISON_CHECK([-o input.c input.y], 0, [],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
input.y:12.3-18: warning: rule useless in parser due to conflicts [-Wother] input.y:12.3-18: warning: rule useless in parser due to conflicts: cond: cond "then" cond [-Wother]
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -1169,13 +955,13 @@ AT_CLEANUP
# $end reduce using rule 3 (num) # $end reduce using rule 3 (num)
# $end [reduce using rule 4 (id)] # $end [reduce using rule 4 (id)]
# #
# But when 'reduce 3' is the default action, we'd produce: # But when `reduce 3' is the default action, we'd produce:
# #
# $end [reduce using rule 4 (id)] # $end [reduce using rule 4 (id)]
# $default reduce using rule 3 (num) # $default reduce using rule 3 (num)
# #
# In this precise case (a reduction is masked by the default # In this precise case (a reduction is masked by the default
# reduction), we make the 'reduce 3' explicit: # reduction), we make the `reduce 3' explicit:
# #
# $end reduce using rule 3 (num) # $end reduce using rule 3 (num)
# $end [reduce using rule 4 (id)] # $end [reduce using rule 4 (id)]
@@ -1197,7 +983,7 @@ id : '0';
AT_BISON_CHECK([-o input.c --report=all input.y], 0, [], AT_BISON_CHECK([-o input.c --report=all input.y], 0, [],
[[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] [[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
input.y:4.6-8: warning: rule useless in parser due to conflicts [-Wother] input.y:4.6-8: warning: rule useless in parser due to conflicts: id: '0' [-Wother]
]]) ]])
# Check the contents of the report. # Check the contents of the report.
@@ -1410,10 +1196,10 @@ e: e '+' e
; ;
]]) ]])
AT_BISON_CHECK([-Wall -o input.c input.y], 0, [], AT_BISON_CHECK([-o input.c input.y], 0, [],
[[input.y: warning: 4 shift/reduce conflicts [-Wconflicts-sr] [[input.y: warning: 4 shift/reduce conflicts [-Wconflicts-sr]
input.y:1.1-5: warning: useless precedence and associativity for '+' [-Wprecedence] input.y:1.7-9: warning: useless associativity for '+' [-Wother]
input.y:2.1-5: warning: useless precedence and associativity for '*' [-Wprecedence] input.y:2.7-9: warning: useless associativity for '*' [-Wother]
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -1517,13 +1303,13 @@ reported_conflicts:
AT_BISON_CHECK([[--report=all input.y]], 0, [], AT_BISON_CHECK([[--report=all input.y]], 0, [],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
input.y:12.5-20: warning: rule useless in parser due to conflicts [-Wother] input.y:12.5-20: warning: rule useless in parser due to conflicts: resolved_conflict: 'a' unreachable1 [-Wother]
input.y:20.5-20: warning: rule useless in parser due to conflicts [-Wother] input.y:20.5-20: warning: rule useless in parser due to conflicts: unreachable1: 'a' unreachable2 [-Wother]
input.y:21.4: warning: rule useless in parser due to conflicts [-Wother] input.y:21.4: warning: rule useless in parser due to conflicts: unreachable1: /* empty */ [-Wother]
input.y:25.13: warning: rule useless in parser due to conflicts [-Wother] input.y:25.13: warning: rule useless in parser due to conflicts: unreachable2: /* empty */ [-Wother]
input.y:25.16: warning: rule useless in parser due to conflicts [-Wother] input.y:25.16: warning: rule useless in parser due to conflicts: unreachable2: /* empty */ [-Wother]
input.y:31.5-7: warning: rule useless in parser due to conflicts [-Wother] input.y:31.5-7: warning: rule useless in parser due to conflicts: reported_conflicts: 'a' [-Wother]
input.y:32.4: warning: rule useless in parser due to conflicts [-Wother] input.y:32.4: warning: rule useless in parser due to conflicts: reported_conflicts: /* empty */ [-Wother]
]]) ]])
AT_CHECK([[cat input.output]], 0, AT_CHECK([[cat input.output]], 0,
@@ -1532,13 +1318,13 @@ AT_CHECK([[cat input.output]], 0,
2 resolved_conflict: 'a' unreachable1 2 resolved_conflict: 'a' unreachable1
4 unreachable1: 'a' unreachable2 4 unreachable1: 'a' unreachable2
5 | %empty 5 | /* empty */
6 unreachable2: %empty 6 unreachable2: /* empty */
7 | %empty 7 | /* empty */
9 reported_conflicts: 'a' 9 reported_conflicts: 'a'
10 | %empty 10 | /* empty */
State 4 conflicts: 1 shift/reduce State 4 conflicts: 1 shift/reduce
@@ -1552,17 +1338,17 @@ Grammar
1 start: resolved_conflict 'a' reported_conflicts 'a' 1 start: resolved_conflict 'a' reported_conflicts 'a'
2 resolved_conflict: 'a' unreachable1 2 resolved_conflict: 'a' unreachable1
3 | %empty 3 | /* empty */
4 unreachable1: 'a' unreachable2 4 unreachable1: 'a' unreachable2
5 | %empty 5 | /* empty */
6 unreachable2: %empty 6 unreachable2: /* empty */
7 | %empty 7 | /* empty */
8 reported_conflicts: 'a' 8 reported_conflicts: 'a'
9 | 'a' 9 | 'a'
10 | %empty 10 | /* empty */
Terminals, with rules where they appear Terminals, with rules where they appear
@@ -1670,10 +1456,10 @@ AT_CHECK([[cat input.y >> input-keep.y]])
AT_BISON_CHECK([[input-keep.y]], 0, [], AT_BISON_CHECK([[input-keep.y]], 0, [],
[[input-keep.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr] [[input-keep.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
input-keep.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr] input-keep.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
input-keep.y:22.4: warning: rule useless in parser due to conflicts [-Wother] input-keep.y:22.4: warning: rule useless in parser due to conflicts: unreachable1: /* empty */ [-Wother]
input-keep.y:26.16: warning: rule useless in parser due to conflicts [-Wother] input-keep.y:26.16: warning: rule useless in parser due to conflicts: unreachable2: /* empty */ [-Wother]
input-keep.y:32.5-7: warning: rule useless in parser due to conflicts [-Wother] input-keep.y:32.5-7: warning: rule useless in parser due to conflicts: reported_conflicts: 'a' [-Wother]
input-keep.y:33.4: warning: rule useless in parser due to conflicts [-Wother] input-keep.y:33.4: warning: rule useless in parser due to conflicts: reported_conflicts: /* empty */ [-Wother]
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -1853,7 +1639,7 @@ exp: 'a' | 'a';
AT_BISON_CHECK([[2.y]], [[0]], [], AT_BISON_CHECK([[2.y]], [[0]], [],
[[2.y: warning: %expect-rr applies only to GLR parsers [-Wother] [[2.y: warning: %expect-rr applies only to GLR parsers [-Wother]
2.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] 2.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
2.y:3.12-14: warning: rule useless in parser due to conflicts [-Wother] 2.y:3.12-14: warning: rule useless in parser due to conflicts: exp: 'a' [-Wother]
]]) ]])
AT_CLEANUP AT_CLEANUP
+147 -160
View File
@@ -403,60 +403,68 @@ dnl parses it as:
dnl dnl
dnl getline $!(4*0); dnl getline $!(4*0);
dnl dnl
dnl That is, they shift '*' immediately and make it part of the getline dnl That is, they shift `*' immediately and make it part of the getline
dnl argument. dnl argument.
dnl dnl
dnl The grammar below using LALR(1) parses it as a syntax error. So does dnl The grammar below using LALR(1) parses it as a syntax error. So does
dnl GNU AWK 3.0.6, 3.1.0, and 3.1.1. They reduce the full getline expression dnl GNU AWK 3.0.6, 3.1.0, and 3.1.1. They reduce the full getline expression
dnl before shifting '*' even though '*' is not a valid lookahead. dnl before shifting `*' even though `*' is not a valid lookahead.
dnl dnl
dnl GNU AWK 3.1.2, 3.1.3, 3.1.4, and 3.1.5 parse it as: dnl GNU AWK 3.1.2, 3.1.3, 3.1.4, and 3.1.5 parse it as:
dnl dnl
dnl (getline $!4)*0; dnl (getline $!4)*0;
dnl dnl
dnl That is, like the other versions of GNU AWK, they reduce the full getline dnl That is, like the other versions of GNU AWK, they reduce the full getline
dnl expression before shifting '*'. However, because of a different LHS on the dnl expression before shifting `*'. However, because of a different LHS on the
dnl getline rule, '*' actually is a valid lookahead. Solaris /usr/xpg4/bin/awk dnl getline rule, `*' actually is a valid lookahead. Solaris /usr/xpg4/bin/awk
dnl and the Open Group awk specification seem to agree: dnl and the Open Group awk specification seem to agree:
dnl dnl
dnl http://www.opengroup.org/pubs/online/7908799/xcu/awk.html dnl http://www.opengroup.org/pubs/online/7908799/xcu/awk.html
dnl dnl
dnl /bin/nawk and /bin/awk on Solaris 10 report it as a syntax error, but they dnl /bin/nawk and /bin/awk on Solaris 10 report it as a syntax error, but they
dnl don't like even 'print $!4;'. dnl don't like even `print $!4;'.
[[LEX_GETLINE, '$', '!', YNUMBER, '*', YNUMBER, ';']], [[LEX_GETLINE, '$', '!', YNUMBER, '*', YNUMBER, ';']],
dnl BISON-STDERR dnl BISON-STDERR
[[input.y:66.10: warning: empty rule without %empty [-Wempty-rule] [AT_COND_CASE([[canonical LR]],
input.y:169.8: warning: empty rule without %empty [-Wempty-rule] [[input.y: warning: 265 shift/reduce conflicts [-Wconflicts-sr]
input.y:174.12: warning: empty rule without %empty [-Wempty-rule] input.y:19.8-16: warning: useless associativity for FUNC_CALL [-Wother]
input.y:179.13: warning: empty rule without %empty [-Wempty-rule] input.y:21.8-14: warning: useless associativity for YNUMBER [-Wother]
input.y:187.15: warning: empty rule without %empty [-Wempty-rule] input.y:21.16-22: warning: useless associativity for YSTRING [-Wother]
input.y:201.8: warning: empty rule without %empty [-Wempty-rule] input.y:22.14-22: warning: useless associativity for APPEND_OP [-Wother]
input.y:206.21: warning: empty rule without %empty [-Wempty-rule] input.y:23.8-15: warning: useless associativity for ASSIGNOP [-Wother]
input.y:220.20: warning: empty rule without %empty [-Wempty-rule] input.y:23.33-41: warning: useless associativity for CONCAT_OP [-Wother]
input.y:299.13: warning: empty rule without %empty [-Wempty-rule] input.y:27.8-18: warning: useless associativity for LEX_GETLINE [-Wother]
input.y:322.9: warning: empty rule without %empty [-Wempty-rule] input.y:28.8-13: warning: useless associativity for LEX_IN [-Wother]
]AT_COND_CASE([[canonical LR]], input.y:29.23-31: warning: useless associativity for INCREMENT [-Wother]
[[input.y: warning: 265 shift/reduce conflicts [-Wconflicts-sr]]], input.y:29.33-41: warning: useless associativity for DECREMENT [-Wother]
[[input.y: warning: 65 shift/reduce conflicts [-Wconflicts-sr]]])[ input.y:30.8-18: warning: useless associativity for LEX_BUILTIN [-Wother]
input.y:39.1-5: warning: useless associativity for FUNC_CALL, use %precedence [-Wprecedence] input.y:30.20-29: warning: useless associativity for LEX_LENGTH [-Wother]
input.y:44.1-5: warning: useless associativity for YNUMBER, use %precedence [-Wprecedence] input.y:40.11-13: warning: useless associativity for ',' [-Wother]
input.y:44.1-5: warning: useless associativity for YSTRING, use %precedence [-Wprecedence] input.y:47.8-10: warning: useless associativity for '!' [-Wother]
input.y:42.1-9: warning: useless precedence and associativity for APPEND_OP [-Wprecedence] input.y:47.12-16: warning: useless associativity for UNARY [-Wother]
input.y:33.1-6: warning: useless associativity for ASSIGNOP, use %precedence [-Wprecedence] input.y:50.7-9: warning: useless associativity for '$' [-Wother]
input.y:43.1-5: warning: useless associativity for CONCAT_OP, use %precedence [-Wprecedence] input.y:51.7-9: warning: useless associativity for '(' [-Wother]
input.y:37.1-5: warning: useless precedence and associativity for LEX_GETLINE [-Wprecedence] input.y:51.11-13: warning: useless associativity for ')' [-Wother]]],
input.y:38.1-9: warning: useless associativity for LEX_IN, use %precedence [-Wprecedence] [[input.y: warning: 65 shift/reduce conflicts [-Wconflicts-sr]
input.y:49.1-5: warning: useless associativity for INCREMENT, use %precedence [-Wprecedence] input.y:19.8-16: warning: useless associativity for FUNC_CALL [-Wother]
input.y:49.1-5: warning: useless associativity for DECREMENT, use %precedence [-Wprecedence] input.y:21.8-14: warning: useless associativity for YNUMBER [-Wother]
input.y:39.1-5: warning: useless associativity for LEX_BUILTIN, use %precedence [-Wprecedence] input.y:21.16-22: warning: useless associativity for YSTRING [-Wother]
input.y:39.1-5: warning: useless associativity for LEX_LENGTH, use %precedence [-Wprecedence] input.y:22.14-22: warning: useless associativity for APPEND_OP [-Wother]
input.y:40.1-9: warning: useless precedence and associativity for ',' [-Wprecedence] input.y:23.8-15: warning: useless associativity for ASSIGNOP [-Wother]
input.y:47.1-6: warning: useless associativity for '!', use %precedence [-Wprecedence] input.y:23.33-41: warning: useless associativity for CONCAT_OP [-Wother]
input.y:47.1-6: warning: useless associativity for UNARY, use %precedence [-Wprecedence] input.y:27.8-18: warning: useless associativity for LEX_GETLINE [-Wother]
input.y:50.1-5: warning: useless associativity for '$', use %precedence [-Wprecedence] input.y:28.8-13: warning: useless associativity for LEX_IN [-Wother]
input.y:51.1-5: warning: useless associativity for '(', use %precedence [-Wprecedence] input.y:29.23-31: warning: useless associativity for INCREMENT [-Wother]
input.y:51.1-5: warning: useless precedence and associativity for ')' [-Wprecedence] input.y:29.33-41: warning: useless associativity for DECREMENT [-Wother]
input.y:30.8-18: warning: useless associativity for LEX_BUILTIN [-Wother]
input.y:30.20-29: warning: useless associativity for LEX_LENGTH [-Wother]
input.y:40.11-13: warning: useless associativity for ',' [-Wother]
input.y:47.8-10: warning: useless associativity for '!' [-Wother]
input.y:47.12-16: warning: useless associativity for UNARY [-Wother]
input.y:50.7-9: warning: useless associativity for '$' [-Wother]
input.y:51.7-9: warning: useless associativity for '(' [-Wother]
input.y:51.11-13: warning: useless associativity for ')' [-Wother]]])[
]], ]],
dnl LAST-STATE dnl LAST-STATE
@@ -484,7 +492,7 @@ dnl - 61 -> 328: reduce -> shift on '*', '/', and '%'
NAME [reduce using rule 152 (opt_variable)] NAME [reduce using rule 152 (opt_variable)]
'$' [reduce using rule 152 (opt_variable)] '$' [reduce using rule 152 (opt_variable)]
@@ -5385,7 +5385,7 @@ @@ -5379,7 +5379,7 @@
156 | . '$' non_post_simp_exp 156 | . '$' non_post_simp_exp
NAME shift, and go to state 9 NAME shift, and go to state 9
@@ -493,7 +501,7 @@ dnl - 61 -> 328: reduce -> shift on '*', '/', and '%'
NAME [reduce using rule 152 (opt_variable)] NAME [reduce using rule 152 (opt_variable)]
'$' [reduce using rule 152 (opt_variable)] '$' [reduce using rule 152 (opt_variable)]
@@ -5405,7 +5405,7 @@ @@ -5399,7 +5399,7 @@
156 | . '$' non_post_simp_exp 156 | . '$' non_post_simp_exp
NAME shift, and go to state 9 NAME shift, and go to state 9
@@ -502,7 +510,7 @@ dnl - 61 -> 328: reduce -> shift on '*', '/', and '%'
NAME [reduce using rule 152 (opt_variable)] NAME [reduce using rule 152 (opt_variable)]
'$' [reduce using rule 152 (opt_variable)] '$' [reduce using rule 152 (opt_variable)]
@@ -6220,7 +6220,7 @@ @@ -6214,7 +6214,7 @@
156 | . '$' non_post_simp_exp 156 | . '$' non_post_simp_exp
NAME shift, and go to state 9 NAME shift, and go to state 9
@@ -511,7 +519,7 @@ dnl - 61 -> 328: reduce -> shift on '*', '/', and '%'
NAME [reduce using rule 152 (opt_variable)] NAME [reduce using rule 152 (opt_variable)]
'$' [reduce using rule 152 (opt_variable)] '$' [reduce using rule 152 (opt_variable)]
@@ -11117,3 +11117,274 @@ @@ -11099,3 +11099,274 @@
45 statement: LEX_FOR '(' opt_exp semi opt_nls exp semi opt_nls opt_exp r_paren opt_nls statement . 45 statement: LEX_FOR '(' opt_exp semi opt_nls exp semi opt_nls opt_exp r_paren opt_nls statement .
$default reduce using rule 45 (statement) $default reduce using rule 45 (statement)
@@ -1395,39 +1403,23 @@ dnl INPUT
[[]], [[]],
dnl BISON-STDERR dnl BISON-STDERR
[[input.y:128.12: warning: empty rule without %empty [-Wempty-rule] [AT_COND_CASE([[canonical LR]],
input.y:137.10: warning: empty rule without %empty [-Wempty-rule]
input.y:142.8: warning: empty rule without %empty [-Wempty-rule]
input.y:161.15: warning: empty rule without %empty [-Wempty-rule]
input.y:179.17: warning: empty rule without %empty [-Wempty-rule]
input.y:205.16: warning: empty rule without %empty [-Wempty-rule]
input.y:213.9: warning: empty rule without %empty [-Wempty-rule]
input.y:225.6: warning: empty rule without %empty [-Wempty-rule]
input.y:292.18: warning: empty rule without %empty [-Wempty-rule]
input.y:294.19: warning: empty rule without %empty [-Wempty-rule]
input.y:367.16: warning: empty rule without %empty [-Wempty-rule]
input.y:373.11: warning: empty rule without %empty [-Wempty-rule]
input.y:387.15: warning: empty rule without %empty [-Wempty-rule]
input.y:401.18: warning: empty rule without %empty [-Wempty-rule]
input.y:413.15: warning: empty rule without %empty [-Wempty-rule]
input.y:443.15: warning: empty rule without %empty [-Wempty-rule]
input.y:471.15: warning: empty rule without %empty [-Wempty-rule]
input.y:474.15: warning: empty rule without %empty [-Wempty-rule]
input.y:489.15: warning: empty rule without %empty [-Wempty-rule]
input.y:506.14: warning: empty rule without %empty [-Wempty-rule]
input.y:587.9: warning: empty rule without %empty [-Wempty-rule]
input.y:591.14: warning: empty rule without %empty [-Wempty-rule]
]AT_COND_CASE([[canonical LR]],
[[input.y: warning: 1876 shift/reduce conflicts [-Wconflicts-sr] [[input.y: warning: 1876 shift/reduce conflicts [-Wconflicts-sr]
input.y: warning: 144 reduce/reduce conflicts [-Wconflicts-rr]]], input.y: warning: 144 reduce/reduce conflicts [-Wconflicts-rr]
input.y:32.9-12: warning: useless associativity for HQUA [-Wother]
input.y:53.8-14: warning: useless associativity for HASSIGN [-Wother]
input.y:54.9-15: warning: useless associativity for HORELSE [-Wother]
input.y:55.9-16: warning: useless associativity for HANDTHEN [-Wother]
input.y:61.9-12: warning: useless associativity for HNOT [-Wother]
input.y:68.7-11: warning: useless associativity for UNEAR [-Wother]]],
[[input.y: warning: 78 shift/reduce conflicts [-Wconflicts-sr] [[input.y: warning: 78 shift/reduce conflicts [-Wconflicts-sr]
input.y: warning: 10 reduce/reduce conflicts [-Wconflicts-rr]]])[ input.y: warning: 10 reduce/reduce conflicts [-Wconflicts-rr]
input.y:72.1-5: warning: useless associativity for HQUA, use %precedence [-Wprecedence] input.y:32.9-12: warning: useless associativity for HQUA [-Wother]
input.y:53.1-6: warning: useless associativity for HASSIGN, use %precedence [-Wprecedence] input.y:53.8-14: warning: useless associativity for HASSIGN [-Wother]
input.y:54.1-5: warning: useless associativity for HORELSE, use %precedence [-Wprecedence] input.y:54.9-15: warning: useless associativity for HORELSE [-Wother]
input.y:55.1-5: warning: useless associativity for HANDTHEN, use %precedence [-Wprecedence] input.y:55.9-16: warning: useless associativity for HANDTHEN [-Wother]
input.y:61.1-5: warning: useless associativity for HNOT, use %precedence [-Wprecedence] input.y:61.9-12: warning: useless associativity for HNOT [-Wother]
input.y:68.1-5: warning: useless associativity for UNEAR, use %precedence [-Wprecedence] input.y:68.7-11: warning: useless associativity for UNEAR [-Wother]]])[
]], ]],
dnl LAST-STATE dnl LAST-STATE
@@ -1593,7 +1585,7 @@ box "foo" above ljust == box ("foo" above ljust)
%left LEFT RIGHT %left LEFT RIGHT
/* Give attributes that take an optional expression a higher /* Give attributes that take an optional expression a higher
precedence than left and right, so that eg 'line chop left' precedence than left and right, so that eg `line chop left'
parses properly. */ parses properly. */
%left CHOP SOLID DASHED DOTTED UP DOWN FILL COLORED OUTLINED %left CHOP SOLID DASHED DOTTED UP DOWN FILL COLORED OUTLINED
%left LABEL %left LABEL
@@ -1606,7 +1598,7 @@ parses properly. */
/* these need to be lower than '-' */ /* these need to be lower than '-' */
%left HEIGHT RADIUS WIDTH DIAMETER FROM TO AT THICKNESS %left HEIGHT RADIUS WIDTH DIAMETER FROM TO AT THICKNESS
/* these must have higher precedence than CHOP so that 'label %prec CHOP' /* these must have higher precedence than CHOP so that `label %prec CHOP'
works */ works */
%left DOT_N DOT_E DOT_W DOT_S DOT_NE DOT_SE DOT_NW DOT_SW DOT_C %left DOT_N DOT_E DOT_W DOT_S DOT_NE DOT_SE DOT_NW DOT_SW DOT_C
%left DOT_START DOT_END TOP BOTTOM LEFT_CORNER RIGHT_CORNER %left DOT_START DOT_END TOP BOTTOM LEFT_CORNER RIGHT_CORNER
@@ -2009,93 +2001,88 @@ dnl without being followed by "of".)
[[VARIABLE, '=', LABEL, LEFT, DOT_X]], [[VARIABLE, '=', LABEL, LEFT, DOT_X]],
dnl BISON-STDERR dnl BISON-STDERR
[[input.y:202.19: warning: empty rule without %empty [-Wempty-rule] [[input.y:471.11-48: warning: rule useless in parser due to conflicts: path: ORDINAL LAST object_type relative_path [-Wother]
input.y:270.6: warning: empty rule without %empty [-Wempty-rule] input.y:19.8-12: warning: useless associativity for LABEL [-Wother]
input.y:292.12: warning: empty rule without %empty [-Wempty-rule] input.y:20.8-15: warning: useless associativity for VARIABLE [-Wother]
input.y:309.17: warning: empty rule without %empty [-Wempty-rule] input.y:21.8-13: warning: useless associativity for NUMBER [-Wother]
input.y:382.13: warning: empty rule without %empty [-Wempty-rule] input.y:22.8-11: warning: useless associativity for TEXT [-Wother]
input.y:471.11-48: warning: rule useless in parser due to conflicts [-Wother] input.y:25.8-14: warning: useless associativity for ORDINAL [-Wother]
input.y:154.1-5: warning: useless associativity for LABEL, use %precedence [-Wprecedence] input.y:30.8-11: warning: useless associativity for LAST [-Wother]
input.y:156.1-5: warning: useless associativity for VARIABLE, use %precedence [-Wprecedence] input.y:31.8-9: warning: useless associativity for UP [-Wother]
input.y:156.1-5: warning: useless associativity for NUMBER, use %precedence [-Wprecedence] input.y:32.8-11: warning: useless associativity for DOWN [-Wother]
input.y:141.1-5: warning: useless associativity for TEXT, use %precedence [-Wprecedence] input.y:35.8-10: warning: useless associativity for BOX [-Wother]
input.y:157.1-5: warning: useless associativity for ORDINAL, use %precedence [-Wprecedence] input.y:36.8-13: warning: useless associativity for CIRCLE [-Wother]
input.y:156.1-5: warning: useless associativity for LAST, use %precedence [-Wprecedence] input.y:37.8-14: warning: useless associativity for ELLIPSE [-Wother]
input.y:153.1-5: warning: useless associativity for UP, use %precedence [-Wprecedence] input.y:38.8-10: warning: useless associativity for ARC [-Wother]
input.y:153.1-5: warning: useless associativity for DOWN, use %precedence [-Wprecedence] input.y:39.8-11: warning: useless associativity for LINE [-Wother]
input.y:159.1-5: warning: useless associativity for BOX, use %precedence [-Wprecedence] input.y:40.8-12: warning: useless associativity for ARROW [-Wother]
input.y:159.1-5: warning: useless associativity for CIRCLE, use %precedence [-Wprecedence] input.y:42.8-13: warning: useless associativity for SPLINE [-Wother]
input.y:159.1-5: warning: useless associativity for ELLIPSE, use %precedence [-Wprecedence] input.y:43.8-13: warning: useless associativity for HEIGHT [-Wother]
input.y:159.1-5: warning: useless associativity for ARC, use %precedence [-Wprecedence] input.y:44.8-13: warning: useless associativity for RADIUS [-Wother]
input.y:159.1-5: warning: useless associativity for LINE, use %precedence [-Wprecedence] input.y:45.8-12: warning: useless associativity for WIDTH [-Wother]
input.y:159.1-5: warning: useless associativity for ARROW, use %precedence [-Wprecedence] input.y:46.8-15: warning: useless associativity for DIAMETER [-Wother]
input.y:159.1-5: warning: useless associativity for SPLINE, use %precedence [-Wprecedence] input.y:47.8-11: warning: useless associativity for FROM [-Wother]
input.y:162.1-5: warning: useless associativity for HEIGHT, use %precedence [-Wprecedence] input.y:48.8-9: warning: useless associativity for TO [-Wother]
input.y:162.1-5: warning: useless associativity for RADIUS, use %precedence [-Wprecedence] input.y:49.8-9: warning: useless associativity for AT [-Wother]
input.y:162.1-5: warning: useless associativity for WIDTH, use %precedence [-Wprecedence] input.y:53.8-12: warning: useless associativity for SOLID [-Wother]
input.y:162.1-5: warning: useless associativity for DIAMETER, use %precedence [-Wprecedence] input.y:54.8-13: warning: useless associativity for DOTTED [-Wother]
input.y:162.1-5: warning: useless associativity for FROM, use %precedence [-Wprecedence] input.y:55.8-13: warning: useless associativity for DASHED [-Wother]
input.y:162.1-5: warning: useless associativity for TO, use %precedence [-Wprecedence] input.y:56.8-11: warning: useless associativity for CHOP [-Wother]
input.y:162.1-5: warning: useless associativity for AT, use %precedence [-Wprecedence] input.y:59.8-12: warning: useless associativity for LJUST [-Wother]
input.y:153.1-5: warning: useless precedence and associativity for SOLID [-Wprecedence] input.y:60.8-12: warning: useless associativity for RJUST [-Wother]
input.y:153.1-5: warning: useless associativity for DOTTED, use %precedence [-Wprecedence] input.y:61.8-12: warning: useless associativity for ABOVE [-Wother]
input.y:153.1-5: warning: useless associativity for DASHED, use %precedence [-Wprecedence] input.y:62.8-12: warning: useless associativity for BELOW [-Wother]
input.y:153.1-5: warning: useless associativity for CHOP, use %precedence [-Wprecedence] input.y:63.8-9: warning: useless associativity for OF [-Wother]
input.y:147.1-5: warning: useless precedence and associativity for LJUST [-Wprecedence] input.y:66.8-14: warning: useless associativity for BETWEEN [-Wother]
input.y:147.1-5: warning: useless precedence and associativity for RJUST [-Wprecedence] input.y:67.8-10: warning: useless associativity for AND [-Wother]
input.y:147.1-5: warning: useless precedence and associativity for ABOVE [-Wprecedence] input.y:68.8-11: warning: useless associativity for HERE [-Wother]
input.y:147.1-5: warning: useless precedence and associativity for BELOW [-Wprecedence] input.y:69.8-12: warning: useless associativity for DOT_N [-Wother]
input.y:176.1-5: warning: useless associativity for OF, use %precedence [-Wprecedence] input.y:70.8-12: warning: useless associativity for DOT_E [-Wother]
input.y:176.1-5: warning: useless associativity for BETWEEN, use %precedence [-Wprecedence] input.y:71.8-12: warning: useless associativity for DOT_W [-Wother]
input.y:177.1-5: warning: useless associativity for AND, use %precedence [-Wprecedence] input.y:72.8-12: warning: useless associativity for DOT_S [-Wother]
input.y:157.1-5: warning: useless associativity for HERE, use %precedence [-Wprecedence] input.y:73.8-13: warning: useless associativity for DOT_NE [-Wother]
input.y:166.1-5: warning: useless associativity for DOT_N, use %precedence [-Wprecedence] input.y:74.8-13: warning: useless associativity for DOT_SE [-Wother]
input.y:166.1-5: warning: useless associativity for DOT_E, use %precedence [-Wprecedence] input.y:75.8-13: warning: useless associativity for DOT_NW [-Wother]
input.y:166.1-5: warning: useless associativity for DOT_W, use %precedence [-Wprecedence] input.y:76.8-13: warning: useless associativity for DOT_SW [-Wother]
input.y:166.1-5: warning: useless associativity for DOT_S, use %precedence [-Wprecedence] input.y:77.8-12: warning: useless associativity for DOT_C [-Wother]
input.y:166.1-5: warning: useless associativity for DOT_NE, use %precedence [-Wprecedence] input.y:78.8-16: warning: useless associativity for DOT_START [-Wother]
input.y:166.1-5: warning: useless associativity for DOT_SE, use %precedence [-Wprecedence] input.y:79.8-14: warning: useless associativity for DOT_END [-Wother]
input.y:166.1-5: warning: useless associativity for DOT_NW, use %precedence [-Wprecedence] input.y:85.8-10: warning: useless associativity for SIN [-Wother]
input.y:166.1-5: warning: useless associativity for DOT_SW, use %precedence [-Wprecedence] input.y:86.8-10: warning: useless associativity for COS [-Wother]
input.y:166.1-5: warning: useless associativity for DOT_C, use %precedence [-Wprecedence] input.y:87.8-12: warning: useless associativity for ATAN2 [-Wother]
input.y:167.1-5: warning: useless associativity for DOT_START, use %precedence [-Wprecedence] input.y:88.8-10: warning: useless associativity for LOG [-Wother]
input.y:167.1-5: warning: useless associativity for DOT_END, use %precedence [-Wprecedence] input.y:89.8-10: warning: useless associativity for EXP [-Wother]
input.y:156.1-5: warning: useless associativity for SIN, use %precedence [-Wprecedence] input.y:90.8-11: warning: useless associativity for SQRT [-Wother]
input.y:156.1-5: warning: useless associativity for COS, use %precedence [-Wprecedence] input.y:91.8-12: warning: useless associativity for K_MAX [-Wother]
input.y:156.1-5: warning: useless associativity for ATAN2, use %precedence [-Wprecedence] input.y:92.8-12: warning: useless associativity for K_MIN [-Wother]
input.y:156.1-5: warning: useless associativity for LOG, use %precedence [-Wprecedence] input.y:93.8-10: warning: useless associativity for INT [-Wother]
input.y:156.1-5: warning: useless associativity for EXP, use %precedence [-Wprecedence] input.y:94.8-11: warning: useless associativity for RAND [-Wother]
input.y:156.1-5: warning: useless associativity for SQRT, use %precedence [-Wprecedence] input.y:95.8-12: warning: useless associativity for SRAND [-Wother]
input.y:156.1-5: warning: useless associativity for K_MAX, use %precedence [-Wprecedence] input.y:98.8-10: warning: useless associativity for TOP [-Wother]
input.y:156.1-5: warning: useless associativity for K_MIN, use %precedence [-Wprecedence] input.y:99.8-13: warning: useless associativity for BOTTOM [-Wother]
input.y:156.1-5: warning: useless associativity for INT, use %precedence [-Wprecedence] input.y:100.8-12: warning: useless associativity for UPPER [-Wother]
input.y:156.1-5: warning: useless associativity for RAND, use %precedence [-Wprecedence] input.y:101.8-12: warning: useless associativity for LOWER [-Wother]
input.y:156.1-5: warning: useless associativity for SRAND, use %precedence [-Wprecedence] input.y:116.8-18: warning: useless associativity for LEFT_CORNER [-Wother]
input.y:167.1-5: warning: useless associativity for TOP, use %precedence [-Wprecedence] input.y:117.8-19: warning: useless associativity for RIGHT_CORNER [-Wother]
input.y:167.1-5: warning: useless associativity for BOTTOM, use %precedence [-Wprecedence] input.y:118.8-12: warning: useless associativity for NORTH [-Wother]
input.y:168.1-5: warning: useless associativity for UPPER, use %precedence [-Wprecedence] input.y:119.8-12: warning: useless associativity for SOUTH [-Wother]
input.y:168.1-5: warning: useless associativity for LOWER, use %precedence [-Wprecedence] input.y:120.8-11: warning: useless associativity for EAST [-Wother]
input.y:167.1-5: warning: useless associativity for LEFT_CORNER, use %precedence [-Wprecedence] input.y:121.8-11: warning: useless associativity for WEST [-Wother]
input.y:167.1-5: warning: useless associativity for RIGHT_CORNER, use %precedence [-Wprecedence] input.y:122.8-13: warning: useless associativity for CENTER [-Wother]
input.y:168.1-5: warning: useless associativity for NORTH, use %precedence [-Wprecedence] input.y:123.8-10: warning: useless associativity for END [-Wother]
input.y:168.1-5: warning: useless associativity for SOUTH, use %precedence [-Wprecedence] input.y:124.8-12: warning: useless associativity for START [-Wother]
input.y:168.1-5: warning: useless associativity for EAST, use %precedence [-Wprecedence] input.y:127.8-11: warning: useless associativity for PLOT [-Wother]
input.y:168.1-5: warning: useless associativity for WEST, use %precedence [-Wprecedence] input.y:128.8-16: warning: useless associativity for THICKNESS [-Wother]
input.y:168.1-5: warning: useless associativity for CENTER, use %precedence [-Wprecedence] input.y:129.8-11: warning: useless associativity for FILL [-Wother]
input.y:168.1-5: warning: useless associativity for END, use %precedence [-Wprecedence] input.y:130.8-14: warning: useless associativity for COLORED [-Wother]
input.y:168.1-5: warning: useless associativity for START, use %precedence [-Wprecedence] input.y:131.8-15: warning: useless associativity for OUTLINED [-Wother]
input.y:140.1-5: warning: useless associativity for PLOT, use %precedence [-Wprecedence] input.y:134.8-14: warning: useless associativity for SPRINTF [-Wother]
input.y:162.1-5: warning: useless associativity for THICKNESS, use %precedence [-Wprecedence] input.y:137.7-9: warning: useless associativity for '.' [-Wother]
input.y:153.1-5: warning: useless associativity for FILL, use %precedence [-Wprecedence] input.y:156.23-25: warning: useless associativity for '(' [-Wother]
input.y:153.1-5: warning: useless precedence and associativity for COLORED [-Wprecedence] input.y:157.20-22: warning: useless associativity for '`' [-Wother]
input.y:153.1-5: warning: useless precedence and associativity for OUTLINED [-Wprecedence] input.y:159.48-50: warning: useless associativity for '@<:@' [-Wother]
input.y:141.1-5: warning: useless associativity for SPRINTF, use %precedence [-Wprecedence] input.y:170.7-9: warning: useless associativity for ',' [-Wother]
input.y:137.1-5: warning: useless associativity for '.', use %precedence [-Wprecedence] input.y:181.8-10: warning: useless associativity for '!' [-Wother]
input.y:156.1-5: warning: useless associativity for '(', use %precedence [-Wprecedence]
input.y:157.1-5: warning: useless associativity for '`', use %precedence [-Wprecedence]
input.y:159.1-5: warning: useless associativity for '@<:@', use %precedence [-Wprecedence]
input.y:170.1-5: warning: useless associativity for ',', use %precedence [-Wprecedence]
input.y:181.1-6: warning: useless associativity for '!', use %precedence [-Wprecedence]
]], ]],
dnl LAST-STATE dnl LAST-STATE
+6 -6
View File
@@ -486,8 +486,8 @@ start:
; ;
%% %%
]AT_YYERROR_DEFINE[
]AT_YYLEX_DEFINE(["a"])[ ]AT_YYLEX_DEFINE(["a"])[
]AT_YYERROR_DEFINE[
]AT_MAIN_DEFINE[ ]AT_MAIN_DEFINE[
]]) ]])
AT_BISON_OPTION_POPDEFS AT_BISON_OPTION_POPDEFS
@@ -1015,17 +1015,17 @@ main (void)
int exit_status = yyparse (); int exit_status = yyparse ();
if (parent_rhs_before_value) if (parent_rhs_before_value)
{ {
fprintf (stderr, "'parent_rhs_before' destructor not called.\n"); fprintf (stderr, "`parent_rhs_before' destructor not called.\n");
exit_status = 1; exit_status = 1;
} }
if (merged_value) if (merged_value)
{ {
fprintf (stderr, "'merged' destructor not called.\n"); fprintf (stderr, "`merged' destructor not called.\n");
exit_status = 1; exit_status = 1;
} }
if (parent_rhs_after_value) if (parent_rhs_after_value)
{ {
fprintf (stderr, "'PARENT_RHS_AFTER' destructor not called.\n"); fprintf (stderr, "`PARENT_RHS_AFTER' destructor not called.\n");
exit_status = 1; exit_status = 1;
} }
return exit_status; return exit_status;
@@ -1449,7 +1449,7 @@ main (void)
int exit_status = yyparse () != 1; int exit_status = yyparse () != 1;
if (parent_rhs_before_value) if (parent_rhs_before_value)
{ {
fprintf (stderr, "'parent_rhs_before' destructor not called.\n"); fprintf (stderr, "`parent_rhs_before' destructor not called.\n");
exit_status = 1; exit_status = 1;
} }
return exit_status; return exit_status;
@@ -1679,8 +1679,8 @@ start:
b: 'b'; b: 'b';
d: /* nada. */; d: /* nada. */;
%% %%
]AT_YYERROR_DEFINE[
]AT_YYLEX_DEFINE(["abc"])[ ]AT_YYLEX_DEFINE(["abc"])[
]AT_YYERROR_DEFINE[
]AT_MAIN_DEFINE[ ]AT_MAIN_DEFINE[
]]) ]])
AT_BISON_OPTION_POPDEFS AT_BISON_OPTION_POPDEFS
+2 -2
View File
@@ -117,9 +117,9 @@ AT_SETUP([Several parsers])
# nor yy* identifiers in the header. Check that headers are # nor yy* identifiers in the header. Check that headers are
# self-contained, and can be compiled by a C++ compiler. # self-contained, and can be compiled by a C++ compiler.
m4_pushdef([AT_TEST], m4_pushdef([AT_TEST],
[AT_BISON_OPTION_PUSHDEFS([%define api.prefix {$1_} $2]) [AT_BISON_OPTION_PUSHDEFS([%define api.prefix "$1_" $2])
AT_DATA_GRAMMAR([$1.y], AT_DATA_GRAMMAR([$1.y],
[[%define api.prefix {$1_} [[%define api.prefix "$1_"
$2 $2
%error-verbose %error-verbose
%union %union
+144 -234
View File
@@ -20,29 +20,6 @@ AT_BANNER([[Input Processing.]])
# Mostly test that we are robust to mistakes. # Mostly test that we are robust to mistakes.
## ----------------- ##
## Invalid options. ##
## ----------------- ##
AT_SETUP([Invalid options])
AT_DATA([input.y],
[[%%
exp: '0'
]])
# We used to accept these, as -f, --report and others were sharing
# their code with -W.
AT_BISON_CHECK([-ferror=caret input.y], [1], [], [ignore])
AT_BISON_CHECK([--report=error=itemsets input.y], [1], [], [ignore])
# We used to accept any character after "-Werror", instead of ensuring
# this is "=".
AT_BISON_CHECK([-Werror?all input.y], [1], [], [ignore])
AT_CLEANUP
## ---------------- ## ## ---------------- ##
## Invalid inputs. ## ## Invalid inputs. ##
## ---------------- ## ## ---------------- ##
@@ -64,13 +41,14 @@ AT_CHECK([[$PERL -pi -e 's/\\(\d{3})/chr(oct($1))/ge' input.y || exit 77]])
AT_BISON_CHECK([input.y], [1], [], AT_BISON_CHECK([input.y], [1], [],
[[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: '?' input.y:3.1: error: invalid character: '?'
input.y:4.14: error: syntax error, unexpected } input.y:4.14: error: invalid character: '}'
input.y:5.1: error: invalid character: '%' input.y:5.1: error: invalid character: '%'
input.y:5.2: error: invalid character: '&' input.y:5.2: error: invalid character: '&'
input.y:6.1-17: error: invalid directive: '%a-does-not-exist' input.y:6.1-17: error: invalid directive: '%a-does-not-exist'
input.y:7.1: error: invalid character: '%' input.y:7.1: error: invalid character: '%'
input.y:7.2: error: invalid character: '-' input.y:7.2: error: invalid character: '-'
input.y:8.1-9.0: error: missing '%}' at end of file input.y:8.1-9.0: error: missing '%}' at end of file
input.y:8.1-9.0: error: syntax error, unexpected %{...%}
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -107,17 +85,17 @@ AT_SETUP([Invalid $n and @n])
AT_DATA([input.y], AT_DATA([input.y],
[[%% [[%%
exp: %empty { $$ = $1 ; }; exp: { $$ = $1 ; };
exp: %empty { @$ = @1 ; }; exp: { @$ = @1 ; };
]]) ]])
AT_BISON_CHECK([-fcaret input.y], [1], [], AT_BISON_CHECK([-fcaret input.y], [1], [],
[[input.y:2.20-21: error: integer out of range: '$1' [[input.y:2.13-14: error: integer out of range: '$1'
exp: %empty { $$ = $1 ; }; exp: { $$ = $1 ; };
^^ ^^
input.y:3.20-21: error: integer out of range: '@1' input.y:3.13-14: error: integer out of range: '@1'
exp: %empty { @$ = @1 ; }; exp: { @$ = @1 ; };
^^ ^^
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -136,7 +114,7 @@ AT_DATA([input.y],
%% %%
exp: foo { $$; } foo { $2; } foo exp: foo { $$; } foo { $2; } foo
| foo | foo
| %empty | /* empty. */
; ;
]]) ]])
@@ -153,9 +131,9 @@ input.y:5.6-32: warning: type clash on default action: <bar> != <> [-Wother]
input.y:6.6-8: warning: type clash on default action: <bar> != <> [-Wother] input.y:6.6-8: warning: type clash on default action: <bar> != <> [-Wother]
| foo | foo
^^^ ^^^
input.y:7.6-11: warning: empty rule for typed nonterminal, and no action [-Wother] input.y:7.5: warning: empty rule for typed nonterminal, and no action [-Wother]
| %empty | /* empty. */
^^^^^^ ^
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -191,7 +169,7 @@ start:
; ;
a: INT | INT { } INT { } INT { }; a: INT | INT { } INT { } INT { };
b: INT | %empty; b: INT | /* empty */;
c: INT | INT { $]1[; } INT { $<integer>2; } INT { $<integer>4; }; c: INT | INT { $]1[; } INT { $<integer>2; } INT { $<integer>4; };
d: INT | INT { } INT { $]1[; } INT { $<integer>2; }; d: INT | INT { } INT { $]1[; } INT { $<integer>2; };
e: INT | INT { } INT { } INT { $]1[; }; e: INT | INT { } INT { } INT { $]1[; };
@@ -219,9 +197,9 @@ input.y:11.18-20: warning: unused value: $][3 [-Wother]
input.y:11.26-28: warning: unused value: $][5 [-Wother] input.y:11.26-28: warning: unused value: $][5 [-Wother]
a: INT | INT { } INT { } INT { }; a: INT | INT { } INT { } INT { };
^^^ ^^^
input.y:12.10-15: warning: empty rule for typed nonterminal, and no action [-Wother] input.y:12.9: warning: empty rule for typed nonterminal, and no action [-Wother]
b: INT | %empty; b: INT | /* empty */;
^^^^^^ ^
]]m4_ifval($2, [[[input.y:13.14-20: warning: unset value: $][$ [-Wmidrule-values] ]]m4_ifval($2, [[[input.y:13.14-20: warning: unset value: $][$ [-Wmidrule-values]
c: INT | INT { $][1; } INT { $<integer>2; } INT { $<integer>4; }; c: INT | INT { $][1; } INT { $<integer>2; } INT { $<integer>4; };
^^^^^^^ ^^^^^^^
@@ -335,67 +313,104 @@ AT_CLEANUP
AT_SETUP([Default %printer and %destructor redeclared]) AT_SETUP([Default %printer and %destructor redeclared])
# AT_TEST([*]) AT_DATA([[input.y]],
# ------------ [[%destructor { destroy ($$); } <*> <*>
m4_pushdef([AT_TEST], %printer { print ($$); } <*> <*>
[AT_DATA([[input.y]],
[[%destructor { destroy ($$); } <$1> <$1>
%printer { print ($$); } <$1> <$1>
%destructor { destroy ($$); } <$1> %destructor { destroy ($$); } <*>
%printer { print ($$); } <$1> %printer { print ($$); } <*>
%destructor { destroy ($$); } <> <>
%printer { print ($$); } <> <>
%destructor { destroy ($$); } <>
%printer { print ($$); } <>
%% %%
start: %empty; start: ;
%destructor { destroy ($$); } <$1>; %destructor { destroy ($$); } <*>;
%printer { print ($$); } <$1>; %printer { print ($$); } <*>;
%destructor { destroy ($$); } <>;
%printer { print ($$); } <>;
]]) ]])
AT_BISON_CHECK([-fcaret input.y], [1], [], AT_BISON_CHECK([-fcaret input.y], [1], [],
[[input.y:1.13-29: error: %destructor redeclaration for <> [[input.y:1.13-29: error: %destructor redeclaration for <*>
%destructor { destroy ($$); } <> <> %destructor { destroy ($$); } <*> <*>
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
input.y:1.13-29: previous declaration input.y:1.13-29: previous declaration
%destructor { destroy ($$); } <> <> %destructor { destroy ($$); } <*> <*>
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
input.y:2.10-24: error: %printer redeclaration for <> input.y:2.10-24: error: %printer redeclaration for <*>
%printer { print ($$); } <> <> %printer { print ($$); } <*> <*>
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
input.y:2.10-24: previous declaration input.y:2.10-24: previous declaration
%printer { print ($$); } <*> <*>
^^^^^^^^^^^^^^^
input.y:4.13-29: error: %destructor redeclaration for <*>
%destructor { destroy ($$); } <*>
^^^^^^^^^^^^^^^^^
input.y:1.13-29: previous declaration
%destructor { destroy ($$); } <*> <*>
^^^^^^^^^^^^^^^^^
input.y:5.10-24: error: %printer redeclaration for <*>
%printer { print ($$); } <*>
^^^^^^^^^^^^^^^
input.y:2.10-24: previous declaration
%printer { print ($$); } <*> <*>
^^^^^^^^^^^^^^^
input.y:7.13-29: error: %destructor redeclaration for <>
%destructor { destroy ($$); } <> <>
^^^^^^^^^^^^^^^^^
input.y:7.13-29: previous declaration
%destructor { destroy ($$); } <> <>
^^^^^^^^^^^^^^^^^
input.y:8.10-24: error: %printer redeclaration for <>
%printer { print ($$); } <> <> %printer { print ($$); } <> <>
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
input.y:4.13-29: error: %destructor redeclaration for <> input.y:8.10-24: previous declaration
%printer { print ($$); } <> <>
^^^^^^^^^^^^^^^
input.y:10.13-29: error: %destructor redeclaration for <>
%destructor { destroy ($$); } <> %destructor { destroy ($$); } <>
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
input.y:1.13-29: previous declaration input.y:7.13-29: previous declaration
%destructor { destroy ($$); } <> <> %destructor { destroy ($$); } <> <>
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
input.y:5.10-24: error: %printer redeclaration for <> input.y:11.10-24: error: %printer redeclaration for <>
%printer { print ($$); } <> %printer { print ($$); } <>
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
input.y:2.10-24: previous declaration input.y:8.10-24: previous declaration
%printer { print ($$); } <> <> %printer { print ($$); } <> <>
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
input.y:11.13-29: error: %destructor redeclaration for <> input.y:17.13-29: error: %destructor redeclaration for <*>
%destructor { destroy ($$); } <*>;
^^^^^^^^^^^^^^^^^
input.y:4.13-29: previous declaration
%destructor { destroy ($$); } <*>
^^^^^^^^^^^^^^^^^
input.y:18.10-24: error: %printer redeclaration for <*>
%printer { print ($$); } <*>;
^^^^^^^^^^^^^^^
input.y:5.10-24: previous declaration
%printer { print ($$); } <*>
^^^^^^^^^^^^^^^
input.y:20.13-29: error: %destructor redeclaration for <>
%destructor { destroy ($$); } <>; %destructor { destroy ($$); } <>;
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
input.y:1.13-29: previous declaration input.y:10.13-29: previous declaration
%destructor { destroy ($$); } <> <> %destructor { destroy ($$); } <>
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
input.y:12.10-24: error: %printer redeclaration for <> input.y:21.10-24: error: %printer redeclaration for <>
%printer { print ($$); } <>; %printer { print ($$); } <>;
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
input.y:2.10-24: previous declaration input.y:11.10-24: previous declaration
%printer { print ($$); } <> <> %printer { print ($$); } <>
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
]]) ]])
])
AT_TEST([], [], [])
AT_TEST([], [*], [*])
m4_popdef([AT_TEST])
AT_CLEANUP AT_CLEANUP
@@ -415,7 +430,7 @@ AT_DATA([[input.y]],
%% %%
start: %empty; start: ;
%destructor { destroy ($$); } <field2> <field1>; %destructor { destroy ($$); } <field2> <field1>;
%printer { print ($$); } <field2> <field1>; %printer { print ($$); } <field2> <field1>;
@@ -425,17 +440,17 @@ AT_BISON_CHECK([input.y], [1], [],
[[input.y:4.13-29: error: %destructor redeclaration for <field1> [[input.y:4.13-29: error: %destructor redeclaration for <field1>
input.y:1.13-29: previous declaration input.y:1.13-29: previous declaration
input.y:4.13-29: error: %destructor redeclaration for <field1> input.y:4.13-29: error: %destructor redeclaration for <field1>
input.y:1.13-29: previous declaration input.y:4.13-29: previous declaration
input.y:5.10-24: error: %printer redeclaration for <field2> input.y:5.10-24: error: %printer redeclaration for <field2>
input.y:2.10-24: previous declaration input.y:2.10-24: previous declaration
input.y:5.10-24: error: %printer redeclaration for <field2> input.y:5.10-24: error: %printer redeclaration for <field2>
input.y:2.10-24: previous declaration input.y:5.10-24: previous declaration
input.y:11.13-29: error: %destructor redeclaration for <field2> input.y:11.13-29: error: %destructor redeclaration for <field2>
input.y:1.13-29: previous declaration input.y:1.13-29: previous declaration
input.y:11.13-29: error: %destructor redeclaration for <field1> input.y:11.13-29: error: %destructor redeclaration for <field1>
input.y:1.13-29: previous declaration input.y:4.13-29: previous declaration
input.y:12.10-24: error: %printer redeclaration for <field2> input.y:12.10-24: error: %printer redeclaration for <field2>
input.y:2.10-24: previous declaration input.y:5.10-24: previous declaration
input.y:12.10-24: error: %printer redeclaration for <field1> input.y:12.10-24: error: %printer redeclaration for <field1>
input.y:2.10-24: previous declaration input.y:2.10-24: previous declaration
]]) ]])
@@ -671,25 +686,25 @@ exp: foo;
]]) ]])
AT_BISON_CHECK([-fcaret input.y], [1], [], AT_BISON_CHECK([-fcaret input.y], [1], [],
[[input.y:8.7-11: error: %type redeclaration for "foo" [[input.y:8.7-11: error: %type redeclaration for foo
%type <baz> "foo" %type <baz> "foo"
^^^^^ ^^^^^
input.y:3.7-11: previous declaration input.y:3.7-11: previous declaration
%type <bar> foo %type <bar> foo
^^^^^ ^^^^^
input.y:9.10-14: error: %printer redeclaration for "foo" input.y:10.13-17: error: %destructor redeclaration for foo
%printer {baz} "foo"
^^^^^
input.y:4.10-14: previous declaration
%printer {bar} foo
^^^^^
input.y:10.13-17: error: %destructor redeclaration for "foo"
%destructor {baz} "foo" %destructor {baz} "foo"
^^^^^ ^^^^^
input.y:5.13-17: previous declaration input.y:5.13-17: previous declaration
%destructor {bar} foo %destructor {bar} foo
^^^^^ ^^^^^
input.y:11.1-5: error: %left redeclaration for "foo" input.y:9.10-14: error: %printer redeclaration for foo
%printer {baz} "foo"
^^^^^
input.y:4.10-14: previous declaration
%printer {bar} foo
^^^^^
input.y:11.1-5: error: %left redeclaration for foo
%left "foo" %left "foo"
^^^^^ ^^^^^
input.y:6.1-5: previous declaration input.y:6.1-5: previous declaration
@@ -811,7 +826,7 @@ exp: '@<:@' '\1' two '$' '@' '{' oline output.or.oline.opt
two: '\x000000000000000000000000000000000000000000000000000000000000000000002'; two: '\x000000000000000000000000000000000000000000000000000000000000000000002';
oline: '@' 'o' 'l' 'i' 'n' 'e' '@' '_' '_' 'o' 'l' 'i' 'n' 'e' '_' '_'; oline: '@' 'o' 'l' 'i' 'n' 'e' '@' '_' '_' 'o' 'l' 'i' 'n' 'e' '_' '_';
output.or.oline.opt: %empty;|oline;;|output;;; output.or.oline.opt: ;|oline;;|output;;;
output: '#' 'o' 'u' 't' 'p' 'u' 't' ' '; output: '#' 'o' 'u' 't' 'p' 'u' 't' ' ';
%% %%
/* Exercise M4 quoting: '@:>@@:>@', @<:@, 2. */ /* Exercise M4 quoting: '@:>@@:>@', @<:@, 2. */
@@ -893,7 +908,7 @@ m4_define([AT_CHECK_REQUIRE],
AT_DATA_GRAMMAR([input.y], AT_DATA_GRAMMAR([input.y],
[[%require "$1"; [[%require "$1";
%% %%
empty_file: %empty; empty_file: /* empty */;
]]) ]])
AT_BISON_CHECK([-o input.c input.y], $2, [], ignore) AT_BISON_CHECK([-o input.c input.y], $2, [], ignore)
AT_CLEANUP AT_CLEANUP
@@ -1051,7 +1066,7 @@ AT_DATA([input.y],
%% %%
start: %empty; start: ;
// Used to report a syntax error because it didn't see any kind of symbol // Used to report a syntax error because it didn't see any kind of symbol
// identifier. // identifier.
@@ -1096,7 +1111,7 @@ AT_SETUP([%start after first rule])
AT_DATA([input.y], AT_DATA([input.y],
[[%% [[%%
false_start: %empty; false_start: ;
start: false_start ; start: false_start ;
%start start; %start start;
]]) ]])
@@ -1117,7 +1132,7 @@ AT_SETUP([%prec takes a token])
AT_DATA([input.y], AT_DATA([input.y],
[[%% [[%%
start: PREC %prec PREC ; start: PREC %prec PREC ;
PREC: %empty; PREC: ;
]]) ]])
AT_BISON_CHECK([input.y], [1], [], AT_BISON_CHECK([input.y], [1], [],
@@ -1159,7 +1174,7 @@ AT_DATA([input-c.y],
%code bad {} %code bad {}
%code format {} %code format {}
%% %%
start: %empty; start: ;
]]) ]])
AT_BISON_CHECK([[input-c.y]], [[1]], [], AT_BISON_CHECK([[input-c.y]], [[1]], [],
[[input-c.y:1.7: error: %code qualifier 'q' is not used [[input-c.y:1.7: error: %code qualifier 'q' is not used
@@ -1173,7 +1188,7 @@ AT_DATA([input-c-glr.y],
%code bad {} %code bad {}
%code bad {} %code bad {}
%% %%
start: %empty; start: ;
]]) ]])
AT_BISON_CHECK([[input-c-glr.y]], [[1]], [], AT_BISON_CHECK([[input-c-glr.y]], [[1]], [],
[[input-c-glr.y:1.7: error: %code qualifier 'q' is not used [[input-c-glr.y:1.7: error: %code qualifier 'q' is not used
@@ -1186,7 +1201,7 @@ AT_DATA([input-c++.y],
%code bad {} %code bad {}
%code q {} %code q {}
%% %%
start: %empty; start: ;
]]) ]])
AT_BISON_CHECK([[input-c++.y]], [[1]], [], AT_BISON_CHECK([[input-c++.y]], [[1]], [],
[[input-c++.y:1.7: error: %code qualifier 'q' is not used [[input-c++.y:1.7: error: %code qualifier 'q' is not used
@@ -1199,7 +1214,7 @@ AT_DATA([input-c++-glr.y],
%code q {} %code q {}
%code q {} %code q {}
%% %%
start: %empty; start: ;
]]) ]])
AT_BISON_CHECK([[input-c++-glr.y]], [[1]], [], AT_BISON_CHECK([[input-c++-glr.y]], [[1]], [],
[[input-c++-glr.y:1.7-9: error: %code qualifier 'bad' is not used [[input-c++-glr.y:1.7-9: error: %code qualifier 'bad' is not used
@@ -1212,7 +1227,7 @@ AT_DATA([special-char-@@.y],
%code q {} %code q {}
%code q {} %code q {}
%% %%
start: %empty; start: ;
]]) ]])
AT_BISON_CHECK([[special-char-@@.y]], [[1]], [], AT_BISON_CHECK([[special-char-@@.y]], [[1]], [],
[[special-char-@@.y:1.7-9: error: %code qualifier 'bad' is not used [[special-char-@@.y:1.7-9: error: %code qualifier 'bad' is not used
@@ -1225,7 +1240,7 @@ AT_DATA([special-char-@:>@.y],
%code q {} %code q {}
%code q {} %code q {}
%% %%
start: %empty; start: ;
]]) ]])
AT_BISON_CHECK([[special-char-@:>@.y]], [[1]], [], AT_BISON_CHECK([[special-char-@:>@.y]], [[1]], [],
[[special-char-@:>@.y:1.7-9: error: %code qualifier 'bad' is not used [[special-char-@:>@.y:1.7-9: error: %code qualifier 'bad' is not used
@@ -1236,45 +1251,6 @@ special-char-@:>@.y:3.7: error: %code qualifier 'q' is not used
AT_CLEANUP AT_CLEANUP
## ---------------- ##
## Multiple %code. ##
## ---------------- ##
AT_SETUP([Multiple %code])
# Make sure that repeated arguments to %code are separated by
# end-of-lines. At some point, a missing eol would leave synclines
# appended to the previous value. Here, we use CPP directive to
# introduce dependency on the absence/presence of the eol.
AT_BISON_OPTION_PUSHDEFS
AT_DATA([input.y],
[[%code {#include <assert.h>}
%code {#define A B}
%code {#define B C}
%code {#define C D}
%code {#define D 42}
%code {
]AT_YYERROR_DECLARE[
]AT_YYLEX_DECLARE[
}
%%
start: %empty;
%%
]AT_YYERROR_DEFINE[
]AT_YYLEX_DEFINE[
int main (void)
{
assert (A == 42);
return 0;
}
]])
AT_FULL_COMPILE([input])
AT_PARSER_CHECK([./input])
AT_BISON_OPTION_POPDEFS
AT_CLEANUP()
## ---------------- ## ## ---------------- ##
## %define errors. ## ## %define errors. ##
## ---------------- ## ## ---------------- ##
@@ -1288,7 +1264,7 @@ AT_DATA([input-redefined.y],
%define special1 "@:>@" %define special1 "@:>@"
%define special2 "@<:@" %define special2 "@<:@"
%% %%
start: %empty; start: ;
]]) ]])
AT_BISON_CHECK([[input-redefined.y]], [[1]], [], AT_BISON_CHECK([[input-redefined.y]], [[1]], [],
@@ -1301,7 +1277,7 @@ input-redefined.y:2.9-11: previous definition
AT_DATA([input-unused.y], AT_DATA([input-unused.y],
[[%define var "value" [[%define var "value"
%% %%
start: %empty; start: ;
]]) ]])
AT_BISON_CHECK([[input-unused.y]], [[1]], [], AT_BISON_CHECK([[input-unused.y]], [[1]], [],
@@ -1329,7 +1305,7 @@ m4@&t@_divert_pop(0)
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%define var-dfg "gram" [[%define var-dfg "gram"
%% %%
start: %empty; start: ;
]]) ]])
AT_BISON_CHECK([[-Dvar-dd=cmd-d1 -Dvar-dd=cmd-d2 \ AT_BISON_CHECK([[-Dvar-dd=cmd-d1 -Dvar-dd=cmd-d2 \
-Fvar-ff=cmd-f1 -Fvar-ff=cmd-f2 \ -Fvar-ff=cmd-f1 -Fvar-ff=cmd-f2 \
@@ -1346,7 +1322,7 @@ var-fd: cmd-d
AT_DATA([[input-dg.y]], AT_DATA([[input-dg.y]],
[[%define var "gram" [[%define var "gram"
%% %%
start: %empty; start: ;
]]) ]])
AT_BISON_CHECK([[-Dvar=cmd-d input-dg.y]], [[1]], [], AT_BISON_CHECK([[-Dvar=cmd-d input-dg.y]], [[1]], [],
[[input-dg.y:1.9-11: error: %define variable 'var' redefined [[input-dg.y:1.9-11: error: %define variable 'var' redefined
@@ -1356,7 +1332,7 @@ AT_BISON_CHECK([[-Dvar=cmd-d input-dg.y]], [[1]], [],
AT_DATA([[input-dg.y]], AT_DATA([[input-dg.y]],
[[%define var "gram" [[%define var "gram"
%% %%
start: %empty; start: ;
]]) ]])
AT_BISON_CHECK([[-fcaret -Dvar=cmd-d input-dg.y]], [[1]], [], AT_BISON_CHECK([[-fcaret -Dvar=cmd-d input-dg.y]], [[1]], [],
[[input-dg.y:1.9-11: error: %define variable 'var' redefined [[input-dg.y:1.9-11: error: %define variable 'var' redefined
@@ -1367,7 +1343,7 @@ AT_BISON_CHECK([[-fcaret -Dvar=cmd-d input-dg.y]], [[1]], [],
AT_DATA([[input-unused.y]], AT_DATA([[input-unused.y]],
[[%% [[%%
start: %empty; start: ;
]]) ]])
AT_BISON_CHECK([[-Dunused-d -Funused-f input-unused.y]], [[1]], [], AT_BISON_CHECK([[-Dunused-d -Funused-f input-unused.y]], [[1]], [],
[[<command line>:2: error: %define variable 'unused-d' is not used [[<command line>:2: error: %define variable 'unused-d' is not used
@@ -1384,10 +1360,10 @@ AT_SETUP([["%define" Boolean variables]])
AT_DATA([Input.y], AT_DATA([Input.y],
[[%language "Java" [[%language "Java"
%define public maybe %define public "maybe"
%define parser_class_name {Input} %define parser_class_name "Input"
%% %%
start: %empty; start: ;
]]) ]])
AT_BISON_CHECK([[Input.y]], [1], [], AT_BISON_CHECK([[Input.y]], [1], [],
@@ -1396,72 +1372,6 @@ AT_BISON_CHECK([[Input.y]], [1], [],
AT_CLEANUP AT_CLEANUP
## ------------------------ ##
## %define code variables. ##
## ------------------------ ##
AT_SETUP([["%define" code variables]])
m4_pushdef([AT_TEST],
[AT_DATA([input.yy],
[[%skeleton "lalr1.cc" %locations
%define api.location.type ]$1[quux]$2[
%define api.namespace ]$1[quux]$2[
%define api.prefix ]$1[quux]$2[
%define api.token.prefix ]$1[quux]$2[
%token TOK // Otherwise api.token.prefix is unused.
%%
start: TOK;
]])
AT_BISON_CHECK([[input.yy]], [0], [],
[[input.yy:2.9-25: warning: %define variable 'api.location.type' requires '{...}' values [-Wdeprecated]
input.yy:4.9-18: warning: %define variable 'api.prefix' requires '{...}' values [-Wdeprecated]
input.yy:5.9-24: warning: %define variable 'api.token.prefix' requires '{...}' values [-Wdeprecated]
input.yy:3.9-21: warning: %define variable 'api.namespace' requires '{...}' values [-Wdeprecated]
]])
])
AT_TEST([], [])
AT_TEST(["], ["])
m4_popdef([AT_TEST])
AT_CLEANUP
## --------------------------- ##
## %define keyword variables. ##
## --------------------------- ##
AT_SETUP([["%define" keyword variables]])
m4_pushdef([AT_TEST],
[AT_DATA([input.y],
[[%define api.pure ]$1[true]$2[
%define api.push-pull ]$1[both]$2[
%define lr.default-reduction ]$1[most]$2[
%define lr.keep-unreachable-state ]$1[true]$2[
%define lr.type ]$1[lalr]$2[
%%
exp: %empty
]])
AT_BISON_CHECK([[input.y]], [0], [],
[[input.y:5.9-15: warning: %define variable 'lr.type' requires keyword values [-Wdeprecated]
input.y:3.9-28: warning: %define variable 'lr.default-reduction' requires keyword values [-Wdeprecated]
input.y:4.9-33: warning: %define variable 'lr.keep-unreachable-state' requires keyword values [-Wdeprecated]
input.y:2.9-21: warning: %define variable 'api.push-pull' requires keyword values [-Wdeprecated]
input.y:1.9-16: warning: %define variable 'api.pure' requires keyword values [-Wdeprecated]
]])
])
AT_TEST(["], ["])
AT_TEST([{], [}])
m4_popdef([AT_TEST])
AT_CLEANUP
## ------------------------ ## ## ------------------------ ##
## %define enum variables. ## ## %define enum variables. ##
## ------------------------ ## ## ------------------------ ##
@@ -1476,7 +1386,7 @@ AT_SETUP([["%define" enum variables]])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%define lr.default-reduction bogus [[%define lr.default-reduction bogus
%% %%
start: %empty; start: ;
]]) ]])
AT_BISON_CHECK([[-fcaret input.y]], [[1]], [[]], AT_BISON_CHECK([[-fcaret input.y]], [[1]], [[]],
[[input.y:1.9-28: error: invalid value for %define variable 'lr.default-reduction': 'bogus' [[input.y:1.9-28: error: invalid value for %define variable 'lr.default-reduction': 'bogus'
@@ -1491,7 +1401,7 @@ input.y:1.9-28: accepted value: 'accepting'
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%define api.push-pull neither [[%define api.push-pull neither
%% %%
start: %empty; start: ;
]]) ]])
AT_BISON_CHECK([[-fcaret input.y]], [[1]], [[]], AT_BISON_CHECK([[-fcaret input.y]], [[1]], [[]],
[[input.y:1.9-21: error: invalid value for %define variable 'api.push-pull': 'neither' [[input.y:1.9-21: error: invalid value for %define variable 'api.push-pull': 'neither'
@@ -1515,10 +1425,10 @@ AT_DATA([[input.y]],
[[%define api.push_pull both [[%define api.push_pull both
%define lr.keep_unreachable_states maybe %define lr.keep_unreachable_states maybe
%define namespace "foo" %define namespace "foo"
%define api.namespace {foo} %define api.namespace "foo"
%define variant %define variant
%% %%
start: %empty; start: ;
]]) ]])
AT_BISON_CHECK([[-fcaret input.y]], [1], [], AT_BISON_CHECK([[-fcaret input.y]], [1], [],
[[input.y:1.9-21: warning: deprecated directive, use '%define api.push-pull both' [-Wdeprecated] [[input.y:1.9-21: warning: deprecated directive, use '%define api.push-pull both' [-Wdeprecated]
@@ -1531,7 +1441,7 @@ input.y:3.9-17: warning: deprecated directive, use '%define api.namespace foo' [
%define namespace "foo" %define namespace "foo"
^^^^^^^^^ ^^^^^^^^^
input.y:4.9-21: error: %define variable 'api.namespace' redefined input.y:4.9-21: error: %define variable 'api.namespace' redefined
%define api.namespace {foo} %define api.namespace "foo"
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
input.y:3.9-17: previous definition input.y:3.9-17: previous definition
%define namespace "foo" %define namespace "foo"
@@ -1551,7 +1461,7 @@ AT_SETUP([[Unused %define api.pure]])
# AT_CHECK_API_PURE(DECLS, VALUE) # AT_CHECK_API_PURE(DECLS, VALUE)
# ------------------------------- # -------------------------------
# Make sure Bison reports that '%define api.pure VALUE' is unused when DECLS # Make sure Bison reports that `%define api.pure VALUE' is unused when DECLS
# are specified. # are specified.
m4_define([AT_CHECK_API_PURE], m4_define([AT_CHECK_API_PURE],
[ [
@@ -1559,7 +1469,7 @@ AT_DATA([[input.y]],
[[%define api.pure ]$2[ [[%define api.pure ]$2[
]$1[ ]$1[
%% %%
start: %empty; start: ;
]]) ]])
AT_BISON_CHECK([[input.y]], [[1]], [], AT_BISON_CHECK([[input.y]], [[1]], [],
@@ -1590,9 +1500,9 @@ m4_define([AT_CHECK_NAMESPACE_ERROR],
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%language "C++" [[%language "C++"
%defines %defines
%define api.namespace {]$1[} %define api.namespace "]$1["
%% %%
start: %empty; start: ;
]]) ]])
AT_BISON_CHECK([[input.y]], [1], [], AT_BISON_CHECK([[input.y]], [1], [],
@@ -1752,7 +1662,7 @@ AT_SETUP([[LAC: Errors for %define]])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%% [[%%
start: %empty; start: ;
]]) ]])
# parse.lac.* options are useless if LAC isn't actually activated. # parse.lac.* options are useless if LAC isn't actually activated.
@@ -1775,27 +1685,27 @@ AT_SETUP([[-Werror is not affected by -Wnone and -Wall]])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%% [[%%
a: '0' { $$ = $; }; foo-bar: ;
]]) ]])
# -Werror is not enabled by -Wall or equivalent. # -Werror is not enabled by -Wall or equivalent.
AT_BISON_CHECK([[-Wall input.y]], [[0]], [[]], AT_BISON_CHECK([[-Wall input.y]], [[0]], [[]],
[[input.y:2.15: warning: stray '$' [-Wother] [[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar [-Wyacc]
]]) ]])
AT_BISON_CHECK([[-W input.y]], [[0]], [[]], AT_BISON_CHECK([[-W input.y]], [[0]], [[]],
[[input.y:2.15: warning: stray '$' [-Wother] [[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar [-Wyacc]
]]) ]])
AT_BISON_CHECK([[-Wno-none input.y]], [[0]], [[]], AT_BISON_CHECK([[-Wno-none input.y]], [[0]], [[]],
[[input.y:2.15: warning: stray '$' [-Wother] [[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar [-Wyacc]
]]) ]])
# -Werror is not disabled by -Wnone or equivalent. # -Werror is not disabled by -Wnone or equivalent.
AT_BISON_CHECK([[-Werror,none,other input.y]], [[1]], [[]], AT_BISON_CHECK([[-Werror,none,yacc input.y]], [[1]], [[]], [[stderr]])
[[input.y:2.15: error: stray '$' [-Werror=other] AT_CHECK([[sed 's/^.*bison:/bison:/' stderr]], [[0]],
]]) [[input.y:2.1-7: error: POSIX Yacc forbids dashes in symbol names: foo-bar [-Werror=yacc]
AT_BISON_CHECK([[-Werror,no-all,other input.y]], [[1]], [[]],
[[input.y:2.15: error: stray '$' [-Werror=other]
]]) ]])
[mv stderr experr]
AT_BISON_CHECK([[-Werror,no-all,yacc input.y]], [[1]], [[]], [[experr]])
AT_CLEANUP AT_CLEANUP
@@ -1812,17 +1722,17 @@ m4_pushdef([AT_TEST],
[AT_DATA([[input.y]], [AT_DATA([[input.y]],
[[$1 [[$1
%% %%
exp: %empty; exp: /* empty */;
]]) ]])
AT_BISON_CHECK([[$2 input.y]], [[1]], [[]], AT_BISON_CHECK([[$2 input.y]], [[1]], [[]],
[[$3: error: '%name-prefix' and '%define api.prefix' cannot be used together [[$3: error: '%name-prefix' and '%define api.prefix' cannot be used together
]]) ]])
]) ])
AT_TEST([%define api.prefix {foo} %name-prefix "bar"], [], [input.y:1.9-18]) AT_TEST([%define api.prefix foo %name-prefix "bar"], [], [input.y:1.9-18])
AT_TEST([], [-Dapi.prefix={foo} -p bar], [<command line>:2]) AT_TEST([], [-Dapi.prefix=foo -p bar], [<command line>:2])
AT_TEST([%name-prefix "bar"], [-Dapi.prefix={foo}], [<command line>:2]) AT_TEST([%name-prefix "bar"], [-Dapi.prefix=foo], [<command line>:2])
AT_TEST([%define api.prefix {foo}], [-p bar], [input.y:1.9-18]) AT_TEST([%define api.prefix foo], [-p bar], [input.y:1.9-18])
m4_popdef([AT_TEST]) m4_popdef([AT_TEST])
+36 -35
View File
@@ -25,8 +25,8 @@ AT_BANNER([[Java Calculator.]])
# _AT_DATA_JAVA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES]) # _AT_DATA_JAVA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])
# ---------------------------------------------------- # ----------------------------------------------------
# Produce 'calc.y'. Don't call this macro directly, because it contains # Produce `calc.y'. Don't call this macro directly, because it contains
# some occurrences of '$1' etc. which will be interpreted by m4. So # some occurrences of `$1' etc. which will be interpreted by m4. So
# you should call it with $1, $2, and $3 as arguments, which is what # you should call it with $1, $2, and $3 as arguments, which is what
# AT_DATA_JAVA_CALC_Y does. # AT_DATA_JAVA_CALC_Y does.
m4_define([_AT_DATA_JAVA_CALC_Y], m4_define([_AT_DATA_JAVA_CALC_Y],
@@ -37,7 +37,7 @@ AT_DATA([Calc.y],
[[/* Infix notation calculator--calc */ [[/* Infix notation calculator--calc */
%language "Java" %language "Java"
%name-prefix "Calc" %name-prefix "Calc"
%define parser_class_name {Calc} %define parser_class_name "Calc"
%define public %define public
]$4[ ]$4[
@@ -206,7 +206,7 @@ AT_BISON_OPTION_POPDEFS
# AT_DATA_CALC_Y([BISON-OPTIONS]) # AT_DATA_CALC_Y([BISON-OPTIONS])
# ------------------------------- # -------------------------------
# Produce 'calc.y'. # Produce `calc.y'.
m4_define([AT_DATA_JAVA_CALC_Y], m4_define([AT_DATA_JAVA_CALC_Y],
[_AT_DATA_JAVA_CALC_Y($[1], $[2], $[3], [$1]) [_AT_DATA_JAVA_CALC_Y($[1], $[2], $[3], [$1])
]) ])
@@ -215,7 +215,7 @@ m4_define([AT_DATA_JAVA_CALC_Y],
# _AT_CHECK_JAVA_CALC_ERROR(BISON-OPTIONS, INPUT, # _AT_CHECK_JAVA_CALC_ERROR(BISON-OPTIONS, INPUT,
# [VERBOSE-AND-LOCATED-ERROR-MESSAGE]) # [VERBOSE-AND-LOCATED-ERROR-MESSAGE])
# -------------------------------------------------------------- # --------------------------------------------------------------
# Run 'calc' on INPUT, and expect a 'syntax error' message. # Run `calc' on INPUT, and expect a `syntax error' message.
# #
# If INPUT starts with a slash, it is used as absolute input file name, # If INPUT starts with a slash, it is used as absolute input file name,
# otherwise as contents. # otherwise as contents.
@@ -240,7 +240,7 @@ AT_DATA([[expout]],
AT_YYERROR_SEES_LOC_IF([], AT_YYERROR_SEES_LOC_IF([],
[[sed 's/^[-0-9.]*: //' expout >at-expout [[sed 's/^[-0-9.]*: //' expout >at-expout
mv at-expout expout]]) mv at-expout expout]])
# 3. If error-verbose is not used, strip the', unexpected....' part. # 3. If error-verbose is not used, strip the`, unexpected....' part.
m4_bmatch([$1], [%error-verbose], [], m4_bmatch([$1], [%error-verbose], [],
[[sed 's/syntax error, .*$/syntax error/' expout >at-expout [[sed 's/syntax error, .*$/syntax error/' expout >at-expout
mv at-expout expout]]) mv at-expout expout]])
@@ -250,7 +250,7 @@ AT_CHECK([cat stderr], 0, [expout])
# _AT_CHECK_JAVA_CALC([BISON-DIRECTIVES], [BISON-CODE]) # _AT_CHECK_JAVA_CALC([BISON-DIRECTIVES], [BISON-CODE])
# ----------------------------------------------------- # -----------------------------------------------------
# Start a testing chunk which compiles 'calc' grammar with # Start a testing chunk which compiles `calc' grammar with
# BISON-DIRECTIVES, and performs several tests over the parser. # BISON-DIRECTIVES, and performs several tests over the parser.
m4_define([_AT_CHECK_JAVA_CALC], m4_define([_AT_CHECK_JAVA_CALC],
[# We use integers to avoid dependencies upon the precision of doubles. [# We use integers to avoid dependencies upon the precision of doubles.
@@ -310,7 +310,7 @@ _AT_CHECK_JAVA_CALC_ERROR([$1], [/dev/null],
# - (* * *): nothing to pop, a lot to discard # - (* * *): nothing to pop, a lot to discard
# - (1 + 2 * *): some to pop and discard # - (1 + 2 * *): some to pop and discard
# #
# - test the action associated to 'error' # - test the action associated to `error'
# #
# - check the lookahead that triggers an error is not discarded # - check the lookahead that triggers an error is not discarded
# when we enter error recovery. Below, the lookahead causing the # when we enter error recovery. Below, the lookahead causing the
@@ -342,7 +342,7 @@ AT_CLEANUP
# AT_CHECK_JAVA_CALC([BISON-DIRECTIVES]) # AT_CHECK_JAVA_CALC([BISON-DIRECTIVES])
# -------------------------------------- # --------------------------------------
# Start a testing chunk which compiles 'calc' grammar with # Start a testing chunk which compiles `calc' grammar with
# BISON-DIRECTIVES, and performs several tests over the parser. # BISON-DIRECTIVES, and performs several tests over the parser.
# Run the test with and without %error-verbose. # Run the test with and without %error-verbose.
m4_define([AT_CHECK_JAVA_CALC], m4_define([AT_CHECK_JAVA_CALC],
@@ -444,8 +444,9 @@ m4_define([AT_CHECK_JAVA_MINIMAL_W_LEXER],
# Check that YYParser.java contains exactly COUNT lines matching ^LINE$ # Check that YYParser.java contains exactly COUNT lines matching ^LINE$
# with grep. # with grep.
m4_define([AT_CHECK_JAVA_GREP], m4_define([AT_CHECK_JAVA_GREP],
[AT_CHECK([grep -c '^$1$' YYParser.java], [ignore], [m4_default([$2], [1]) [AT_CHECK([grep -c '^$1$' YYParser.java], [], [m4_default([$2], [1])
])]) ])
])
# ------------------------------------- # # ------------------------------------- #
@@ -460,13 +461,13 @@ AT_CHECK_JAVA_GREP([[class YYParser]])
AT_CHECK_JAVA_MINIMAL([[%name-prefix "Prefix"]]) AT_CHECK_JAVA_MINIMAL([[%name-prefix "Prefix"]])
AT_CHECK_JAVA_GREP([[class PrefixParser]]) AT_CHECK_JAVA_GREP([[class PrefixParser]])
AT_CHECK_JAVA_MINIMAL([[%define api.token.prefix {TOK_}]]) AT_CHECK_JAVA_MINIMAL([[%define api.token.prefix "TOK_"]])
AT_CHECK_JAVA_GREP([[.*TOK_END.*]]) AT_CHECK_JAVA_GREP([[.*TOK_END.*]])
AT_CHECK_JAVA_MINIMAL([[%define parser_class_name {ParserClassName}]]) AT_CHECK_JAVA_MINIMAL([[%define parser_class_name "ParserClassName"]])
AT_CHECK_JAVA_GREP([[class ParserClassName]]) AT_CHECK_JAVA_GREP([[class ParserClassName]])
AT_CHECK_JAVA_MINIMAL([[%define package {user_java_package}]]) AT_CHECK_JAVA_MINIMAL([[%define package "user_java_package"]])
AT_CHECK_JAVA_GREP([[package user_java_package;]]) AT_CHECK_JAVA_GREP([[package user_java_package;]])
AT_CLEANUP AT_CLEANUP
@@ -529,7 +530,7 @@ AT_CHECK_JAVA_GREP([[public final strictfp class YYParser]])
# FIXME: Can't do a Java compile because javacomp.sh is configured for 1.3 # FIXME: Can't do a Java compile because javacomp.sh is configured for 1.3
AT_CHECK_JAVA_MINIMAL([[ AT_CHECK_JAVA_MINIMAL([[
%define annotations {/*@Deprecated @SupressWarnings("unchecked") @SupressWarnings({"unchecked", "deprecation"}) @SupressWarnings(value={"unchecked", "deprecation"})*/} %define annotations "/*@Deprecated @SupressWarnings(\"unchecked\") @SupressWarnings({\"unchecked\", \"deprecation\"}) @SupressWarnings(value={\"unchecked\", \"deprecation\"})*/"
%define public]]) %define public]])
AT_CHECK_JAVA_GREP([[/\*@Deprecated @SupressWarnings("unchecked") @SupressWarnings({"unchecked", "deprecation"}) @SupressWarnings(value={"unchecked", "deprecation"})\*/ public class YYParser]]) AT_CHECK_JAVA_GREP([[/\*@Deprecated @SupressWarnings("unchecked") @SupressWarnings({"unchecked", "deprecation"}) @SupressWarnings(value={"unchecked", "deprecation"})\*/ public class YYParser]])
@@ -542,15 +543,15 @@ AT_CLEANUP
AT_SETUP([Java parser class extends and implements]) AT_SETUP([Java parser class extends and implements])
AT_CHECK_JAVA_MINIMAL([[%define extends {Thread}]]) AT_CHECK_JAVA_MINIMAL([[%define extends "Thread"]])
AT_CHECK_JAVA_GREP([[class YYParser extends Thread]]) AT_CHECK_JAVA_GREP([[class YYParser extends Thread]])
AT_CHECK_JAVA_MINIMAL([[%define implements {Cloneable}]]) AT_CHECK_JAVA_MINIMAL([[%define implements "Cloneable"]])
AT_CHECK_JAVA_GREP([[class YYParser implements Cloneable]]) AT_CHECK_JAVA_GREP([[class YYParser implements Cloneable]])
AT_CHECK_JAVA_MINIMAL([[ AT_CHECK_JAVA_MINIMAL([[
%define extends {Thread} %define extends "Thread"
%define implements {Cloneable}]]) %define implements "Cloneable"]])
AT_CHECK_JAVA_GREP([[class YYParser extends Thread implements Cloneable]]) AT_CHECK_JAVA_GREP([[class YYParser extends Thread implements Cloneable]])
AT_CLEANUP AT_CLEANUP
@@ -642,9 +643,9 @@ AT_SETUP([Java throws specifications])
m4_define([AT_JT_lex_throws_define], [m4_case(AT_JT_lex_throws, m4_define([AT_JT_lex_throws_define], [m4_case(AT_JT_lex_throws,
-1, [], -1, [],
0, [[%define lex_throws {}]], 0, [[%define lex_throws ""]],
1, [[%define lex_throws {InterruptedException}]], 1, [[%define lex_throws "InterruptedException"]],
2, [[%define lex_throws {InterruptedException, IllegalAccessException}]])]) 2, [[%define lex_throws "InterruptedException, IllegalAccessException"]])])
m4_define([AT_JT_yylex_throws], [m4_case(AT_JT_lex_throws, m4_define([AT_JT_yylex_throws], [m4_case(AT_JT_lex_throws,
-1, [[ throws java.io.IOException]], -1, [[ throws java.io.IOException]],
@@ -661,9 +662,9 @@ m4_define([AT_JT_yylex_action], [m4_case(AT_JT_lex_throws,
m4_define([AT_JT_throws_define], [m4_case(AT_JT_throws, m4_define([AT_JT_throws_define], [m4_case(AT_JT_throws,
-1, [], -1, [],
0, [[%define throws {}]], 0, [[%define throws ""]],
1, [[%define throws {ClassNotFoundException}]], 1, [[%define throws "ClassNotFoundException"]],
2, [[%define throws {ClassNotFoundException, InstantiationException}]])]) 2, [[%define throws "ClassNotFoundException, InstantiationException"]])])
m4_define([AT_JT_yyaction_throws], [m4_case(AT_JT_throws, m4_define([AT_JT_yyaction_throws], [m4_case(AT_JT_throws,
-1, [], -1, [],
@@ -726,16 +727,16 @@ AT_CLEANUP
AT_SETUP([Java constructor init and init_throws]) AT_SETUP([Java constructor init and init_throws])
AT_CHECK_JAVA_MINIMAL([[ AT_CHECK_JAVA_MINIMAL([[
%define extends {Thread} %define extends "Thread"
%code init { super("Test Thread"); if (true) throw new InterruptedException(); } %code init { super("Test Thread"); if (true) throw new InterruptedException(); }
%define init_throws {InterruptedException} %define init_throws "InterruptedException"
%lex-param {int lex_param}]]) %lex-param {int lex_param}]])
AT_CHECK([[grep -q 'super("Test Thread"); if (true) throw new InterruptedException();' YYParser.java]]) AT_CHECK([[grep -q 'super("Test Thread"); if (true) throw new InterruptedException();' YYParser.java]])
AT_CHECK_JAVA_MINIMAL_W_LEXER([[ AT_CHECK_JAVA_MINIMAL_W_LEXER([[
%define extends {Thread} %define extends "Thread"
%code init { super("Test Thread"); if (true) throw new InterruptedException(); } %code init { super("Test Thread"); if (true) throw new InterruptedException(); }
%define init_throws {InterruptedException}]], [], [[return EOF;]]) %define init_throws "InterruptedException"]], [], [[return EOF;]])
AT_CHECK([[grep -q 'super("Test Thread"); if (true) throw new InterruptedException();' YYParser.java]]) AT_CHECK([[grep -q 'super("Test Thread"); if (true) throw new InterruptedException();' YYParser.java]])
AT_CLEANUP AT_CLEANUP
@@ -748,20 +749,20 @@ AT_CLEANUP
AT_SETUP([Java value, position, and location types]) AT_SETUP([Java value, position, and location types])
AT_CHECK_JAVA_MINIMAL([[ AT_CHECK_JAVA_MINIMAL([[
%define api.value.type {java.awt.Color} %define api.value.type "java.awt.Color"
%type<java.awt.Color> start; %type<java.awt.Color> start;
%define api.location.type {MyLoc} %define api.location.type "MyLoc"
%define api.position.type {MyPos} %define api.position.type "MyPos"
%code { class MyPos {} }]], [[$$ = $<java.awt.Color>1;]], [[MyPos]]) %code { class MyPos {} }]], [[$$ = $<java.awt.Color>1;]], [[MyPos]])
AT_CHECK([[grep 'java.awt.Color' YYParser.java]], [0], [ignore]) AT_CHECK([[grep 'java.awt.Color' YYParser.java]], [0], [ignore])
AT_CHECK([[$EGREP -v ' */?\*' YYParser.java | grep 'Position']], [1], [ignore]) AT_CHECK([[$EGREP -v ' */?\*' YYParser.java | grep 'Position']], [1], [ignore])
AT_CHECK([[$EGREP -v ' */?\*' YYParser.java | grep 'Location']], [1], [ignore]) AT_CHECK([[$EGREP -v ' */?\*' YYParser.java | grep 'Location']], [1], [ignore])
AT_CHECK_JAVA_MINIMAL_W_LEXER([[ AT_CHECK_JAVA_MINIMAL_W_LEXER([[
%define api.value.type {java.awt.Color} %define api.value.type "java.awt.Color"
%type<java.awt.Color> start; %type<java.awt.Color> start;
%define api.location.type {MyLoc} %define api.location.type "MyLoc"
%define api.position.type {MyPos} %define api.position.type "MyPos"
%code { class MyPos {} }]], [], [[return EOF;]], [], %code { class MyPos {} }]], [], [[return EOF;]], [],
[[$$ = $<java.awt.Color>1;]], [[$$ = $<java.awt.Color>1;]],
[[java.awt.Color]], [[MyPos]], [[MyLoc]]) [[java.awt.Color]], [[MyPos]], [[MyLoc]])
-864
View File
@@ -1,864 +0,0 @@
# Checking Java Push Parsing. -*- Autotest -*-
# Copyright (C) 2013 Free Software Foundation, Inc.
# 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/>.
# The Java push parser tests are intended primarily
# to verify that the sequence of states that the parser
# traverses is the same as a pull parser would traverse.
##################################################
# Provide a way to generate data with and without push parsing
# so it is possible to capture the output for comparison
# (except the "trivial" tests).
# Use "both" rather than "push" so we can also set it to "pull" to
# get the "experr" data.
m4_define([PUSHPULLFLAG],[-Dapi.push-pull=both])
# AT_CHECK_JAVA_GREP(FILE, [LINE], [COUNT=1])
# -------------------------------------------
# Check that FILE contains exactly COUNT lines matching ^LINE$
# with grep. Unquoted so that COUNT can be a shell expression.
m4_define([AT_CHECK_JAVA_GREP],
[AT_CHECK_UNQUOTED([grep -c '^$2$' $1], [ignore], [m4_default([$3], [1])
])])
##################################################
AT_BANNER([[Java Push Parsing Tests]])
# Define a single copy of the trivial parser grammar.
# This is missing main(), so two versions
# are instantiated with different main() procedures.
m4_define([AT_TRIVIAL_GRAMMAR],[
%define parser_class_name {YYParser}
%error-verbose
%code imports {
import java.io.*;
import java.util.*;
}
%%
start: 'a' 'b' 'c' ;
%%
])
# Define comon code across to be includede in
# class Main for the trivial parser tests.
m4_define([AT_TRIVIAL_COMMON],[
static class YYerror implements YYParser.Lexer
{
public Object getLVal() {return null;}
public int yylex () throws java.io.IOException { return 0; }
public void yyerror (String msg) { System.err.println(msg); }
}
static YYParser parser = null;
static YYerror yyerror = null;
static int teststate = -1;
static void setup()
throws IOException
{
yyerror = new YYerror();
parser = new YYParser(yyerror);
parser.setDebugLevel(1);
teststate = -1;
}
static String[[]] teststatename
= new String[[]]{"YYACCEPT","YYABORT","YYERROR","UNKNOWN","YYPUSH_MORE"};
static void check(int teststate, int expected, String msg)
{
System.err.println("teststate="+teststatename[[teststate]]
+"; expected="+teststatename[[expected]]);
if (teststate == expected)
return;
System.err.println("unexpected state: "+msg);
System.exit(1);
}
])
m4_define([AT_TRIVIAL_PARSER],[
AT_TRIVIAL_GRAMMAR
public class Main
{
AT_TRIVIAL_COMMON
static public void main (String[[]] argv)
throws IOException
{
setup();
teststate = parser.push_parse('a', null);
check(teststate,YYParser.YYPUSH_MORE,"push_parse('a', null)");
setup();
teststate = parser.push_parse('a', null);
check(teststate,YYParser.YYPUSH_MORE,"push_parse('a', null)");
teststate = parser.push_parse('b', null);
check(teststate,YYParser.YYPUSH_MORE,"push_parse('b', null)");
teststate = parser.push_parse('c', null);
check(teststate,YYParser.YYPUSH_MORE,"push_parse('c', null)");
teststate = parser.push_parse('\0', null);
check(teststate,YYParser.YYACCEPT,"push_parse('\\0', null)");
/* Reuse the parser instance and cause a failure */
teststate = parser.push_parse('b', null);
check(teststate,YYParser.YYABORT,"push_parse('b', null)");
System.exit(0);
}
}
])
m4_define([AT_TRIVIAL_PARSER_INITIAL_ACTION],[
AT_TRIVIAL_GRAMMAR
public class Main
{
AT_TRIVIAL_COMMON
static public void main (String[[]] argv)
throws IOException
{
setup();
teststate = parser.push_parse('a', null);
check(teststate,YYParser.YYPUSH_MORE,"push_parse('a', null)");
teststate = parser.push_parse('b', null);
check(teststate,YYParser.YYPUSH_MORE,"push_parse('b', null)");
teststate = parser.push_parse('c', null);
check(teststate,YYParser.YYPUSH_MORE,"push_parse('c', null)");
teststate = parser.push_parse('\0', null);
check(teststate,YYParser.YYACCEPT,"push_parse('\\0', null)");
System.exit(0);
}
}
])
## ----------------------------------------------------- ##
## Trivial Push Parser with api.push-pull verification. ##
## ----------------------------------------------------- ##
AT_SETUP([Trivial Push Parser with api.push-pull verification])
AT_BISON_OPTION_PUSHDEFS
AT_DATA([[input.y]],
[[%language "Java"
]AT_TRIVIAL_PARSER[
]])
# Verify that the proper procedure(s) are generated for each case.
AT_BISON_CHECK([[-Dapi.push-pull=pull -o Main.java input.y]])
AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public boolean parse ().*]],
[1])
# If BISON_USE_PUSH_FOR_PULL is set, then we have one occurrence of
# this function, otherwise it should not be there.
AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public int push_parse (int yylextoken, Object yylexval).*]],
[${BISON_USE_PUSH_FOR_PULL-0}])
AT_BISON_CHECK([[-Dapi.push-pull=both -o Main.java input.y]])
AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public boolean parse ().*]],
[1])
AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public int push_parse (int yylextoken, Object yylexval).*]],
[1])
AT_BISON_CHECK([[-Dapi.push-pull=push -o Main.java input.y]])
AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public boolean parse ().*]],
[0])
AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public int push_parse (int yylextoken, Object yylexval).*]],
[1])
AT_JAVA_COMPILE([[Main.java]])
AT_JAVA_PARSER_CHECK([Main], 0, [], [stderr-nolog])
AT_BISON_OPTION_POPDEFS
AT_CLEANUP
## ------------------------------------------ ##
## Trivial Push Parser with %initial-action. ##
## ------------------------------------------ ##
AT_SETUP([Trivial Push Parser with %initial-action])
AT_BISON_OPTION_PUSHDEFS
AT_DATA([[input.y]],[[%language "Java"
%initial-action {
System.err.println("Initial action invoked");
}
]AT_TRIVIAL_PARSER_INITIAL_ACTION[
]])
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-Dapi.push-pull=push -o Main.java input.y]])
AT_CHECK_JAVA_GREP([[Main.java]],
[[System.err.println("Initial action invoked");]])
AT_JAVA_COMPILE([[Main.java]])
AT_JAVA_PARSER_CHECK([Main], 0, [], [stderr-nolog])
# Verify that initial action is called exactly once.
AT_CHECK_JAVA_GREP(
[[stderr]],
[[Initial action invoked]],
[1])
AT_CLEANUP
# Define a single copy of the Calculator grammar.
m4_define([AT_CALC_BODY],[
%code imports {
import java.io.*;
}
%code {
static StringReader
getinput(String filename) throws IOException
{
StringBuilder buf = new StringBuilder();
FileReader file = new FileReader(filename);
int c;
while ((c=file.read()) > 0)
buf.append((char)c);
file.close();
return new StringReader(buf.toString());
}
}
/* Bison Declarations */
%token <Integer> NUM "number"
%type <Integer> exp
%nonassoc '=' /* comparison */
%left '-' '+'
%left '*' '/'
%left NEG /* negation--unary minus */
%right '^' /* exponentiation */
/* Grammar follows */
%%
input:
line
| input line
;
line:
'\n'
| exp '\n'
{System.out.println("total = "+$[]1);}
| error '\n'
;
exp:
NUM { $[]$ = $[]1;}
| exp '=' exp
{
if ($[]1.intValue() != $[]3.intValue())
yyerror (]AT_LOCATION_IF([[@$,]])[ "calc: error: " + $[]1 + " != " + $[]3);
}
| exp '+' exp
{ $[]$ = new Integer ($[]1.intValue () + $[]3.intValue ()); }
| exp '-' exp
{ $[]$ = new Integer ($[]1.intValue () - $[]3.intValue ()); }
| exp '*' exp
{ $[]$ = new Integer ($[]1.intValue () * $[]3.intValue ()); }
| exp '/' exp
{ $[]$ = new Integer ($[]1.intValue () / $[]3.intValue ()); }
| '-' exp %prec NEG
{ $[]$ = new Integer (-$[]2.intValue ()); }
| exp '^' exp
{ $[]$ = new Integer ((int)Math.pow ($[]1.intValue (),
$[]3.intValue ())); }
| '(' exp ')' { $[]$ = $[]2;}
| '(' error ')' { $[]$ = new Integer (1111);}
| '!' { $[]$ = new Integer (0); return YYERROR;}
| '-' error { $[]$ = new Integer (0); return YYERROR;}
;
])
# Test that the states transitioned by the push parser are the
# same as for the pull parser. This test is assumed to work
# if it produces the same partial trace of stack states as is
# produced when using pull parsing. The output is verbose,
# but seems essential for verifying push parsing.
AT_SETUP([Calc parser with api.push-pull both])
AT_BISON_OPTION_PUSHDEFS
# Define the calculator input.
# Warning: if you changes the input file
# then the locations test file position numbers
# may be incorrect and you will have
# to modify that file as well.
AT_DATA([input],[[1 + 2 * 3 = 7
1 + 2 * -3 = -5
-1^2 = -1
(-1)^2 = 1
---1 = -1
1 - 2 - 3 = -4
1 - (2 - 3) = 2
2^2^3 = 256
(2^2)^3 = 64
]])
# Compose pieces to build the actual .y file.
AT_DATA([Calc.y],[[/* Infix notation calculator--calc */
%language "Java"
%name-prefix "Calc"
%define parser_class_name {Calc}
%code {
static class UserLexer implements Calc.Lexer
{
StreamTokenizer st;
StringReader rdr;
public UserLexer(StringReader reader)
{
rdr = reader;
st = new StreamTokenizer(rdr);
st.resetSyntax();
st.eolIsSignificant(true);
st.whitespaceChars(9, 9);
st.whitespaceChars(32, 32);
st.wordChars(48, 57);
}
Integer yylval;
public Object getLVal() { return yylval; }
public void yyerror(String msg) { System.err.println(msg); }
public int yylex () throws IOException
{
switch (st.nextToken()) {
case StreamTokenizer.TT_EOF: return EOF;
case StreamTokenizer.TT_EOL: return (int) '\n';
case StreamTokenizer.TT_WORD:
yylval = new Integer (st.sval);
return NUM;
default: return st.ttype;
}
}
}
}
%code {
public static void main (String[] argv)
throws IOException
{
StringReader reader = getinput(argv[0]);
UserLexer lexer = new UserLexer(reader);
Calc calc = new Calc(lexer);
calc.setDebugLevel(1);
calc.parse();
}//main
}
]AT_CALC_BODY[
]])
# This data was captured from running a pull parser.
AT_DATA([[expout]],[[Stack now 0
Stack now 0 2
Stack now 0 9
Stack now 0 9 19
Stack now 0 9 19 2
Stack now 0 9 19 28
Stack now 0 9 19 28 20
Stack now 0 9 19 28 20 2
Stack now 0 9 19 28 20 29
Stack now 0 9 19 28
Stack now 0 9
Stack now 0 9 17
Stack now 0 9 17 2
Stack now 0 9 17 26
Stack now 0 9
Stack now 0 9 23
Stack now 0 8
Stack now 0 7
Stack now 0 7 2
Stack now 0 7 9
Stack now 0 7 9 19
Stack now 0 7 9 19 2
Stack now 0 7 9 19 28
Stack now 0 7 9 19 28 20
Stack now 0 7 9 19 28 20 3
Stack now 0 7 9 19 28 20 3 2
Stack now 0 7 9 19 28 20 3 12
Stack now 0 7 9 19 28 20 29
Stack now 0 7 9 19 28
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 3
Stack now 0 7 9 17 3 2
Stack now 0 7 9 17 3 12
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 4
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 3
Stack now 0 7 3 2
Stack now 0 7 3 12
Stack now 0 7 3 12 22
Stack now 0 7 3 12 22 2
Stack now 0 7 3 12 22 31
Stack now 0 7 3 12
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 3
Stack now 0 7 9 17 3 2
Stack now 0 7 9 17 3 12
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 5
Stack now 0 7 5 3
Stack now 0 7 5 3 2
Stack now 0 7 5 3 12
Stack now 0 7 5 14
Stack now 0 7 5 14 25
Stack now 0 7 9
Stack now 0 7 9 22
Stack now 0 7 9 22 2
Stack now 0 7 9 22 31
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 2
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 4
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 3
Stack now 0 7 3 3
Stack now 0 7 3 3 3
Stack now 0 7 3 3 3 2
Stack now 0 7 3 3 3 12
Stack now 0 7 3 3 12
Stack now 0 7 3 12
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 3
Stack now 0 7 9 17 3 2
Stack now 0 7 9 17 3 12
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 4
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 2
Stack now 0 7 9
Stack now 0 7 9 18
Stack now 0 7 9 18 2
Stack now 0 7 9 18 27
Stack now 0 7 9
Stack now 0 7 9 18
Stack now 0 7 9 18 2
Stack now 0 7 9 18 27
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 3
Stack now 0 7 9 17 3 2
Stack now 0 7 9 17 3 12
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 2
Stack now 0 7 9
Stack now 0 7 9 18
Stack now 0 7 9 18 5
Stack now 0 7 9 18 5 2
Stack now 0 7 9 18 5 14
Stack now 0 7 9 18 5 14 18
Stack now 0 7 9 18 5 14 18 2
Stack now 0 7 9 18 5 14 18 27
Stack now 0 7 9 18 5 14
Stack now 0 7 9 18 5 14 25
Stack now 0 7 9 18 27
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 2
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 4
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 2
Stack now 0 7 9
Stack now 0 7 9 22
Stack now 0 7 9 22 2
Stack now 0 7 9 22 31
Stack now 0 7 9 22 31 22
Stack now 0 7 9 22 31 22 2
Stack now 0 7 9 22 31 22 31
Stack now 0 7 9 22 31
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 2
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 5
Stack now 0 7 5 2
Stack now 0 7 5 14
Stack now 0 7 5 14 22
Stack now 0 7 5 14 22 2
Stack now 0 7 5 14 22 31
Stack now 0 7 5 14
Stack now 0 7 5 14 25
Stack now 0 7 9
Stack now 0 7 9 22
Stack now 0 7 9 22 2
Stack now 0 7 9 22 31
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 2
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 15
]])
AT_BISON_CHECK([PUSHPULLFLAG [-o Calc.java Calc.y]])
AT_JAVA_COMPILE([[Calc.java]])
#Verify that this is a push parser.
AT_CHECK_JAVA_GREP([[Calc.java]],
[[.*public void push_parse_initialize().*]])
# Capture stderr output for comparison purposes.
AT_JAVA_PARSER_CHECK([Calc input], 0, [ignore-nolog], [stderr-nolog])
# Extract the "Stack Now" lines from the error output,
# send them to stdout (via the sed command) and compare to expout.
# NOTE: because the target is "expout", this macro automatically
# compares the output of the sed command with the contents of
# the file "expout" (defined above).
AT_CHECK([[sed -e '/^Stack now.*$/p' -e d ./stderr]],
[ignore], [expout], [ignore-nolog])
AT_BISON_OPTION_POPDEFS
AT_CLEANUP
# This test looks for location reporting by looking
# at the lexer output with locations enabled.
# It defines a lexer that reports location info.
AT_SETUP([Calc parser with %locations %code lexer and api.push-pull both])
AT_BISON_OPTION_PUSHDEFS
AT_DATA([Calc.y],[[/* Infix notation calculator--calc. */
%language "Java"
%name-prefix "Calc"
%define parser_class_name {Calc}
%lex-param { Reader rdr }
%locations
%code imports {
import java.io.*;
}
%code lexer {
StreamTokenizer st;
Integer yylval;
public YYLexer(Reader rdr)
{
st = new StreamTokenizer(rdr);
st.resetSyntax();
st.eolIsSignificant(true);
st.whitespaceChars(9, 9);
st.whitespaceChars(32, 32);
st.wordChars(48, 57);
}
Position yypos = new Position (1, 0);
public Position getStartPos() { return yypos; }
public Position getEndPos() { return yypos; }
public Object getLVal() { return yylval; }
public void yyerror(Location loc, String msg)
{
System.err.println(loc+":"+msg);
}
public int yylex () throws IOException
{
yypos = new Position (yypos.lineno (),yypos.token () + 1);
switch (st.nextToken()) {
case StreamTokenizer.TT_EOF:
return EOF;
case StreamTokenizer.TT_EOL:
yypos = new Position (yypos.lineno () + 1, 0);
return (int) '\n';
case StreamTokenizer.TT_WORD:
yylval = new Integer (st.sval);
return NUM;
default:
return st.ttype;
}
}
}
%code {
class Position {
public int line;
public int token;
public Position () { line = 0; token = 0; }
public Position (int l, int t) { line = l; token = t; }
public boolean equals (Position l)
{
return l.line == line && l.token == token;
}
public String toString ()
{
return Integer.toString(line) + "." + Integer.toString(token);
}
public int lineno () { return line; }
public int token () { return token; }
}//Class Position
}
%code {
public static void main (String[] argv)
throws IOException
{
StringReader reader = getinput(argv[0]);
Calc calc = new Calc(reader);
calc.setDebugLevel(1);
calc.parse();
}
}
]AT_CALC_BODY[
]])
# Define the expected calculator output.
# This should match the output from a pull parser.
AT_DATA([output],[[total = 7
total = -5
total = -1
total = 1
total = -1
total = -4
total = 2
total = 256
total = 64
]])
AT_DATA([locations],[[Next token is token "number" (1.1: 1)
Next token is token '+' (1.2: 1)
Next token is token "number" (1.3: 2)
Next token is token '*' (1.4: 2)
Next token is token "number" (1.5: 3)
Next token is token '=' (1.6: 3)
Next token is token '=' (1.6: 3)
Next token is token '=' (1.6: 3)
Next token is token "number" (1.7: 7)
Next token is token '\n' (2.0: 7)
Next token is token '\n' (2.0: 7)
Next token is token "number" (2.1: 1)
Next token is token '+' (2.2: 1)
Next token is token "number" (2.3: 2)
Next token is token '*' (2.4: 2)
Next token is token '-' (2.5: 2)
Next token is token "number" (2.6: 3)
Next token is token '=' (2.7: 3)
Next token is token '=' (2.7: 3)
Next token is token '=' (2.7: 3)
Next token is token '=' (2.7: 3)
Next token is token '-' (2.8: 3)
Next token is token "number" (2.9: 5)
Next token is token '\n' (3.0: 5)
Next token is token '\n' (3.0: 5)
Next token is token '\n' (3.0: 5)
Next token is token '\n' (4.0: 5)
Next token is token '-' (4.1: 5)
Next token is token "number" (4.2: 1)
Next token is token '^' (4.3: 1)
Next token is token "number" (4.4: 2)
Next token is token '=' (4.5: 2)
Next token is token '=' (4.5: 2)
Next token is token '=' (4.5: 2)
Next token is token '-' (4.6: 2)
Next token is token "number" (4.7: 1)
Next token is token '\n' (5.0: 1)
Next token is token '\n' (5.0: 1)
Next token is token '\n' (5.0: 1)
Next token is token '(' (5.1: 1)
Next token is token '-' (5.2: 1)
Next token is token "number" (5.3: 1)
Next token is token ')' (5.4: 1)
Next token is token ')' (5.4: 1)
Next token is token '^' (5.5: 1)
Next token is token "number" (5.6: 2)
Next token is token '=' (5.7: 2)
Next token is token '=' (5.7: 2)
Next token is token "number" (5.8: 1)
Next token is token '\n' (6.0: 1)
Next token is token '\n' (6.0: 1)
Next token is token '\n' (7.0: 1)
Next token is token '-' (7.1: 1)
Next token is token '-' (7.2: 1)
Next token is token '-' (7.3: 1)
Next token is token "number" (7.4: 1)
Next token is token '=' (7.5: 1)
Next token is token '=' (7.5: 1)
Next token is token '=' (7.5: 1)
Next token is token '=' (7.5: 1)
Next token is token '-' (7.6: 1)
Next token is token "number" (7.7: 1)
Next token is token '\n' (8.0: 1)
Next token is token '\n' (8.0: 1)
Next token is token '\n' (8.0: 1)
Next token is token '\n' (9.0: 1)
Next token is token "number" (9.1: 1)
Next token is token '-' (9.2: 1)
Next token is token "number" (9.3: 2)
Next token is token '-' (9.4: 2)
Next token is token '-' (9.4: 2)
Next token is token "number" (9.5: 3)
Next token is token '=' (9.6: 3)
Next token is token '=' (9.6: 3)
Next token is token '-' (9.7: 3)
Next token is token "number" (9.8: 4)
Next token is token '\n' (10.0: 4)
Next token is token '\n' (10.0: 4)
Next token is token '\n' (10.0: 4)
Next token is token "number" (10.1: 1)
Next token is token '-' (10.2: 1)
Next token is token '(' (10.3: 1)
Next token is token "number" (10.4: 2)
Next token is token '-' (10.5: 2)
Next token is token "number" (10.6: 3)
Next token is token ')' (10.7: 3)
Next token is token ')' (10.7: 3)
Next token is token '=' (10.8: 3)
Next token is token '=' (10.8: 3)
Next token is token "number" (10.9: 2)
Next token is token '\n' (11.0: 2)
Next token is token '\n' (11.0: 2)
Next token is token '\n' (12.0: 2)
Next token is token "number" (12.1: 2)
Next token is token '^' (12.2: 2)
Next token is token "number" (12.3: 2)
Next token is token '^' (12.4: 2)
Next token is token "number" (12.5: 3)
Next token is token '=' (12.6: 3)
Next token is token '=' (12.6: 3)
Next token is token '=' (12.6: 3)
Next token is token "number" (12.7: 256)
Next token is token '\n' (13.0: 256)
Next token is token '\n' (13.0: 256)
Next token is token '(' (13.1: 256)
Next token is token "number" (13.2: 2)
Next token is token '^' (13.3: 2)
Next token is token "number" (13.4: 2)
Next token is token ')' (13.5: 2)
Next token is token ')' (13.5: 2)
Next token is token '^' (13.6: 2)
Next token is token "number" (13.7: 3)
Next token is token '=' (13.8: 3)
Next token is token '=' (13.8: 3)
Next token is token "number" (13.9: 64)
Next token is token '\n' (14.0: 64)
Next token is token '\n' (14.0: 64)
]])
# Define the calculator input.
# Warning: if you changes the input file
# then the locations test file position numbers
# may be incorrect and you will have
# to modify that file as well.
AT_DATA([input],[[1 + 2 * 3 = 7
1 + 2 * -3 = -5
-1^2 = -1
(-1)^2 = 1
---1 = -1
1 - 2 - 3 = -4
1 - (2 - 3) = 2
2^2^3 = 256
(2^2)^3 = 64
]])
AT_BISON_CHECK([PUSHPULLFLAG [-o Calc.java Calc.y]])
AT_JAVA_COMPILE([[Calc.java]])
# Verify that this is a push parser
AT_CHECK_JAVA_GREP([[Calc.java]],
[[.*public void push_parse_initialize().*]])
# Capture the stdout and stderr output for comparison purposes.
AT_JAVA_PARSER_CHECK([Calc input], 0, [stdout-nolog], [stderr-nolog])
# 1. Check that the token locations are correct
AT_CHECK([[cp -f ./locations ./expout]],[ignore],[ignore-nolog],[ignore-nolog])
AT_CHECK([[sed -e '/^Next token.*$/p' -e d ./stderr]],[ignore],[expout],[ignore-nolog])
# 2. Check that the calculator output matches that of a pull parser
AT_CHECK([[rm -f ./expout; cp -f ./output ./expout]],[ignore],[ignore-nolog],[ignore-nolog])
AT_CHECK([[cat ./stdout]],[ignore],[expout],[ignore-nolog])
AT_CLEANUP
+109 -155
View File
@@ -37,7 +37,7 @@ m4_define([AT_SETUP_STRIP],
[m4_bpatsubsts([$1], [m4_bpatsubsts([$1],
[%\(language\|skeleton\) "?\([^\" ]*\)"?], [%\(language\|skeleton\) "?\([^\" ]*\)"?],
[\2], [\2],
[%define "?\([-A-Za-z0-9_.]+\)"? \({[^\}]+}\|"[^\"]+"\|[-A-Za-z0-9_.]+\)], [%define "?\([-A-Za-z0-9_.]+\)"? \("[^\"]+"\|[-A-Za-z0-9_.]+\)],
[\1=\2], [\1=\2],
[%define "?\([-A-Za-z0-9_.]+\)"?], [%define "?\([-A-Za-z0-9_.]+\)"?],
[\1], [\1],
@@ -134,7 +134,7 @@ m4_define([AT_BISON_OPTION_PUSHDEFS],
# _AT_BISON_OPTION_PUSHDEFS($1, $2, [BISON-OPTIONS]) # _AT_BISON_OPTION_PUSHDEFS($1, $2, [BISON-OPTIONS])
# -------------------------------------------------- # --------------------------------------------------
# This macro works around the impossibility to define macros # This macro works around the impossibility to define macros
# inside macros, because issuing '[$1]' is not possible in M4 :(. # inside macros, because issuing `[$1]' is not possible in M4 :(.
# This sucks hard, GNU M4 should really provide M5-like $$1. # This sucks hard, GNU M4 should really provide M5-like $$1.
m4_define([_AT_BISON_OPTION_PUSHDEFS], m4_define([_AT_BISON_OPTION_PUSHDEFS],
[m4_if([$1$2], $[1]$[2], [], [m4_if([$1$2], $[1]$[2], [],
@@ -178,25 +178,23 @@ m4_bpatsubst([$3], [%parse-param { *\([^{}]*[^{} ]\) *}],
m4_pushdef([AT_PURE_IF], m4_pushdef([AT_PURE_IF],
[m4_bmatch([$3], [%define *api\.pure\|%pure-parser], [m4_bmatch([$3], [%define *api\.pure\|%pure-parser],
[m4_bmatch([$3], [%define *api\.pure *false], [$2], [$1])], [m4_bmatch([$3], [%define *api\.pure *"?false"?], [$2], [$1])],
[$2])]) [$2])])
# AT_NAME_PREFIX: also consider api.namespace. # AT_NAME_PREFIX: also consider api.namespace.
m4_pushdef([AT_NAME_PREFIX], m4_pushdef([AT_NAME_PREFIX],
[m4_bmatch([$3], [\(%define api\.\(namespace\|prefix\)\|%name-prefix\) .*], [m4_bmatch([$3], [\(%define api\.\(namespace\|prefix\)\|%name-prefix\) ".*"],
[m4_bregexp([$3], [m4_bregexp([$3], [\(%define api\.\(namespace\|prefix\)\|%name-prefix\) "\([^""]*\)"], [\3])],
[\(%define api\.\(namespace\|prefix\)\|%name-prefix\) [\{\"]\([^\"\}]*\)[\"\}]], [yy])])
[\3])],
[yy])])
m4_pushdef([AT_TOKEN_CTOR_IF], m4_pushdef([AT_TOKEN_CTOR_IF],
[m4_bmatch([$3], [%define api\.token\.constructor], [$1], [$2])]) [m4_bmatch([$3], [%define api\.token\.constructor], [$1], [$2])])
m4_pushdef([AT_TOKEN_PREFIX], m4_pushdef([AT_TOKEN_PREFIX],
[m4_bmatch([$3], [%define api\.token\.prefix {.*}], [m4_bmatch([$3], [%define api\.token\.prefix ".*"],
[m4_bregexp([$3], [%define api\.token\.prefix {\(.*\)}], [\1])])]) [m4_bregexp([$3], [%define api\.token\.prefix "\(.*\)"], [\1])])])
m4_pushdef([AT_VARIANT_IF], m4_pushdef([AT_VARIANT_IF],
[m4_bmatch([$3], [%define api\.value\.type variant], [$1], [$2])]) [m4_bmatch([$3], [%define api\.value\.type "?variant"?], [$1], [$2])])
m4_pushdef([AT_API_prefix], m4_pushdef([AT_API_prefix],
[m4_bmatch([$3], [%define api\.prefix {.*}], [m4_bmatch([$3], [%define api\.prefix ".*"],
[m4_bregexp([$3], [%define api\.prefix {\([^\}]*\)}], [\1])], [m4_bregexp([$3], [%define api\.prefix "\([^""]*\)"], [\1])],
[yy])]) [yy])])
m4_pushdef([AT_API_PREFIX], m4_pushdef([AT_API_PREFIX],
[m4_toupper(AT_API_prefix)]) [m4_toupper(AT_API_prefix)])
@@ -207,7 +205,7 @@ m4_pushdef([AT_API_PREFIX],
m4_pushdef([AT_YYERROR_ARG_LOC_IF], m4_pushdef([AT_YYERROR_ARG_LOC_IF],
[AT_LOCATION_IF([AT_PURE_IF([m4_bmatch([$3], [AT_LOCATION_IF([AT_PURE_IF([m4_bmatch([$3],
m4_quote(m4_join([\|], m4_quote(m4_join([\|],
[%define api\.pure full], [%define api\.pure "?full"?],
[%glr-parser], [%glr-parser],
[%parse-param], [%parse-param],
[%skeleton "?glr.c"?])), [%skeleton "?glr.c"?])),
@@ -319,29 +317,10 @@ AT_LOC_POPDEF])dnl
## Generating Grammar Files. ## ## Generating Grammar Files. ##
## -------------------------- ## ## -------------------------- ##
# _AT_LANG_DISPATCH(LANG, MACRO, ARGS)
# ------------------------------------
# Call the specialization of MACRO for LANG with ARGS. Complain if
# unavailable.
m4_define([_AT_LANG_DISPATCH],
[m4_ifdef([$2($1)],
[m4_indir([$2($1)], m4_shift2($@))],
[m4_fatal([$2: unknown language: $1])])])
# AT_LANG_DISPATCH(MACRO, ARGS)
# -----------------------------
# Call the specialization of MACRO for AT_LANG with ARGS. Complain if
# unavailable.
m4_define([AT_LANG_DISPATCH],
[_AT_LANG_DISPATCH(AT_LANG, $@)])
# AT_DATA_SOURCE_PROLOGUE # AT_DATA_SOURCE_PROLOGUE
# ----------------------- # ------------------------
# The prologue that should be included in any source code that is # The prologue that should be included in any source code that is
# meant to be compiled. Keep atlocal.in sync (BISON_CXX_WORKS). # meant to be compiled.
m4_define([AT_DATA_SOURCE_PROLOGUE], m4_define([AT_DATA_SOURCE_PROLOGUE],
[[#include <config.h> [[#include <config.h>
/* We don't need perfect functions for these tests. */ /* We don't need perfect functions for these tests. */
@@ -427,33 +406,24 @@ static
# AT_YYERROR_DEFINE # AT_YYERROR_DEFINE
# ------------------------- # -------------------------
# Must be called inside a AT_BISON_OPTION_PUSHDEFS/POPDEFS pair. # Must be called inside a AT_BISON_OPTION_PUSHDEFS/POPDEFS pair.
m4_define([AT_YYERROR_FORMALS], [AT_LANG_DISPATCH([$0], $@)]) m4_define([AT_YYERROR_FORMALS],
m4_define([AT_YYERROR_PROTOTYPE],[AT_LANG_DISPATCH([$0], $@)]) [m4_case(AT_LANG,
m4_define([AT_YYERROR_DECLARE_EXTERN], [AT_LANG_DISPATCH([$0], $@)]) [c], [AT_YYERROR_ARG_LOC_IF([AT_YYLTYPE const * const llocp, ])AT_PARSE_PARAMS [const char *msg]])[]dnl
m4_define([AT_YYERROR_DECLARE], [AT_LANG_DISPATCH([$0], $@)]) ])
m4_define([AT_YYERROR_DEFINE], [AT_LANG_DISPATCH([$0], $@)])
# AT_MAIN_DEFINE m4_define([AT_YYERROR_PROTOTYPE],
# -------------- [m4_case(AT_LANG,
m4_define([AT_MAIN_DEFINE], [AT_LANG_DISPATCH([$0], $@)]) [c], [[void ]AT_NAME_PREFIX[error (]AT_YYERROR_FORMALS[)]])[]dnl
])
m4_define([AT_YYERROR_DECLARE_EXTERN],
[m4_case(AT_LANG,
[c], [AT_YYERROR_PROTOTYPE;])[]dnl
])
m4_define([AT_YYERROR_DECLARE],
## --- ## [m4_case(AT_LANG,
## C. ## [c], [#include <stdio.h>
## --- ##
m4_define([AT_YYERROR_FORMALS(c)],
[AT_YYERROR_ARG_LOC_IF([AT_YYLTYPE const * const llocp, ])AT_PARSE_PARAMS[const char *msg]])
m4_define([AT_YYERROR_PROTOTYPE(c)],
[[void ]AT_NAME_PREFIX[error (]AT_YYERROR_FORMALS[)]])
m4_define([AT_YYERROR_DECLARE_EXTERN(c)],
[AT_YYERROR_PROTOTYPE;])
m4_define([AT_YYERROR_DECLARE(c)],
[#include <stdio.h>
]AT_LOCATION_IF([[ ]AT_LOCATION_IF([[
#if defined ]AT_YYLTYPE[_IS_TRIVIAL && ]AT_YYLTYPE[_IS_TRIVIAL #if defined ]AT_YYLTYPE[_IS_TRIVIAL && ]AT_YYLTYPE[_IS_TRIVIAL
static unsigned location_print (FILE *yyo, ]AT_YYLTYPE[ const * const yylocp); static unsigned location_print (FILE *yyo, ]AT_YYLTYPE[ const * const yylocp);
@@ -462,11 +432,12 @@ static unsigned location_print (FILE *yyo, ]AT_YYLTYPE[ const * const yylocp);
# endif # endif
#endif #endif
]])[ ]])[
static AT_YYERROR_DECLARE_EXTERN]) static AT_YYERROR_DECLARE_EXTERN])[]dnl
])
m4_define([AT_YYERROR_DEFINE],
m4_define([AT_YYERROR_DEFINE(c)], [m4_case(AT_LANG,
[[ [c], [[
]AT_LOCATION_IF([[ ]AT_LOCATION_IF([[
# if defined ]AT_YYLTYPE[_IS_TRIVIAL && ]AT_YYLTYPE[_IS_TRIVIAL # if defined ]AT_YYLTYPE[_IS_TRIVIAL && ]AT_YYLTYPE[_IS_TRIVIAL
/* Print *YYLOCP on YYO. */ /* Print *YYLOCP on YYO. */
@@ -507,10 +478,34 @@ AT_YYERROR_SEES_LOC_IF([[
LOCATION_PRINT (stderr, ]AT_LOC[); LOCATION_PRINT (stderr, ]AT_LOC[);
fprintf (stderr, ": ");]])[ fprintf (stderr, ": ");]])[
fprintf (stderr, "%s\n", msg); fprintf (stderr, "%s\n", msg);
}]]) }]],
[c++], [[/* A C++ error reporting function. */
void
]AT_NAME_PREFIX[::parser::error (]AT_LOCATION_IF([[const location_type& l, ]])[const std::string& m)
{
std::cerr << ]AT_LOCATION_IF([l << ": " << ])[m << std::endl;
}]],
[java], [AT_LOCATION_IF([[public void yyerror (Calc.Location l, String s)
{
if (l == null)
System.err.println (s);
else
System.err.println (l + ": " + s);
}
]], [[
public void yyerror (String s)
{
System.err.println (s);
}]])],
[m4_fatal([$0: invalid language: ]AT_LANG)])dnl
])
m4_define([AT_MAIN_DEFINE(c)], # AT_MAIN_DEFINE
# --------------
m4_define([AT_MAIN_DEFINE],
[m4_case(AT_LANG,
[c],
[[#include <stdlib.h> /* getenv. */ [[#include <stdlib.h> /* getenv. */
#include <string.h> /* strcmp. */ #include <string.h> /* strcmp. */
int int
@@ -523,27 +518,8 @@ main (int argc, char const* argv[])
(void) argc; (void) argc;
(void) argv;]])[ (void) argv;]])[
return ]AT_NAME_PREFIX[parse (); return ]AT_NAME_PREFIX[parse ();
}]]) }]],
[c++],
## ----- ##
## C++. ##
## ----- ##
# No need to declare, it's part of the class interface.
m4_define([AT_YYERROR_DECLARE(c++)], [])
m4_define([AT_YYERROR_DECLARE_EXTERN(c++)], [])
m4_define([AT_YYERROR_DEFINE(c++)],
[[/* A C++ error reporting function. */
void
]AT_NAME_PREFIX[::parser::error (]AT_LOCATION_IF([[const location_type& l, ]])[const std::string& m)
{
std::cerr << ]AT_LOCATION_IF([l << ": " << ])[m << std::endl;
}]])
m4_define([AT_MAIN_DEFINE(c++)],
[[#include <cstdlib> // getenv. [[#include <cstdlib> // getenv.
#include <cstring> // strcmp. #include <cstring> // strcmp.
int int
@@ -557,30 +533,8 @@ main (int argc, char const* argv[])
(void) argc; (void) argc;
(void) argv;]])[ (void) argv;]])[
return p.parse (); return p.parse ();
}]]) }]],
[java],
## ------ ##
## Java. ##
## ------ ##
m4_define([AT_YYERROR_DEFINE(java)],
[AT_LOCATION_IF([[public void yyerror (Calc.Location l, String s)
{
if (l == null)
System.err.println (s);
else
System.err.println (l + ": " + s);
}
]], [[
public void yyerror (String s)
{
System.err.println (s);
}
]])])
m4_define([AT_MAIN_DEFINE(java)],
[[class input [[class input
{ {
public static void main (String args[]) throws IOException public static void main (String args[]) throws IOException
@@ -588,8 +542,7 @@ m4_define([AT_MAIN_DEFINE(java)],
YYParser p = new YYParser (); YYParser p = new YYParser ();
p.parse (); p.parse ();
} }
}]]) }]])])
## --------------- ## ## --------------- ##
@@ -601,7 +554,7 @@ m4_define([AT_MAIN_DEFINE(java)],
# High-level routine that may call bison several times, under different # High-level routine that may call bison several times, under different
# conditions. # conditions.
# #
# Check Bison by invoking 'bison BISON_ARGS'. BISON_ARGS should not contain # Check Bison by invoking `bison BISON_ARGS'. BISON_ARGS should not contain
# shell constructs (such as redirection or pipes) that would prevent # shell constructs (such as redirection or pipes) that would prevent
# appending additional command-line arguments for bison. OTHER_AT_CHECK_ARGS # appending additional command-line arguments for bison. OTHER_AT_CHECK_ARGS
# are the usual remaining arguments to AT_CHECK: STATUS, STDOUT, etc. # are the usual remaining arguments to AT_CHECK: STATUS, STDOUT, etc.
@@ -754,7 +707,6 @@ AT_CHECK(m4_join([ ],
[m4_bmatch([$1], [[.]], [], [$LIBS])]), [m4_bmatch([$1], [[.]], [], [$LIBS])]),
0, [ignore], [ignore])]) 0, [ignore], [ignore])])
# AT_COMPILE_CXX(OUTPUT, [SOURCES = OUTPUT.cc]) # AT_COMPILE_CXX(OUTPUT, [SOURCES = OUTPUT.cc])
# --------------------------------------------- # ---------------------------------------------
# Compile SOURCES into OUTPUT. If the C++ compiler does not work, # Compile SOURCES into OUTPUT. If the C++ compiler does not work,
@@ -762,7 +714,7 @@ AT_CHECK(m4_join([ ],
# #
# If OUTPUT does not contain '.', assume that we are linking too, # If OUTPUT does not contain '.', assume that we are linking too,
# otherwise pass "-c"; this is a hack. The default SOURCES is OUTPUT # otherwise pass "-c"; this is a hack. The default SOURCES is OUTPUT
# with trailing ".o" removed, and ".cc" appended. # with trailing .o removed, and ".cc" appended.
m4_define([AT_COMPILE_CXX], m4_define([AT_COMPILE_CXX],
[AT_KEYWORDS(c++) [AT_KEYWORDS(c++)
AT_CHECK([$BISON_CXX_WORKS], 0, ignore, ignore) AT_CHECK([$BISON_CXX_WORKS], 0, ignore, ignore)
@@ -774,7 +726,6 @@ AT_CHECK(m4_join([ ],
[m4_bmatch([$1], [[.]], [], [$LIBS])]), [m4_bmatch([$1], [[.]], [], [$LIBS])]),
0, [ignore], [ignore])]) 0, [ignore], [ignore])])
# AT_JAVA_COMPILE(SOURCES) # AT_JAVA_COMPILE(SOURCES)
# ------------------------ # ------------------------
# Compile SOURCES into Java class files. Skip the test if java or javac # Compile SOURCES into Java class files. Skip the test if java or javac
@@ -783,10 +734,9 @@ m4_define([AT_JAVA_COMPILE],
[AT_KEYWORDS(java) [AT_KEYWORDS(java)
AT_SKIP_IF([[test -z "$CONF_JAVAC"]]) AT_SKIP_IF([[test -z "$CONF_JAVAC"]])
AT_SKIP_IF([[test -z "$CONF_JAVA"]]) AT_SKIP_IF([[test -z "$CONF_JAVA"]])
AT_CHECK([[$SHELL ../../../javacomp.sh ]$1], AT_CHECK([[$SHELL $abs_top_builddir/javacomp.sh ]$1],
[[0]], [ignore], [ignore])]) [[0]], [ignore], [ignore])])
# AT_LANG_COMPILE(OUTPUT, [SOURCES = OUTPUT.c] # AT_LANG_COMPILE(OUTPUT, [SOURCES = OUTPUT.c]
# -------------------------------------------- # --------------------------------------------
# Compile SOURCES into OUTPUT. Skip if compiler does not work. # Compile SOURCES into OUTPUT. Skip if compiler does not work.
@@ -794,11 +744,13 @@ AT_CHECK([[$SHELL ../../../javacomp.sh ]$1],
# If OUTPUT does not contain '.', assume that we are linking too, # If OUTPUT does not contain '.', assume that we are linking too,
# otherwise pass "-c"; this is a hack. The default SOURCES is OUTPUT # otherwise pass "-c"; this is a hack. The default SOURCES is OUTPUT
# with trailing .o removed, and ".c"/".cc" appended. # with trailing .o removed, and ".c"/".cc" appended.
m4_define([AT_LANG_COMPILE], [AT_LANG_DISPATCH([$0], $@)]) m4_define([AT_LANG_COMPILE],
m4_define([AT_LANG_COMPILE(c)], [AT_COMPILE([$1], [$2])]) [m4_case(AT_LANG,
m4_define([AT_LANG_COMPILE(c++)], [AT_COMPILE_CXX([$1], [$2])]) [c], [AT_COMPILE([$1], [$2])],
m4_define([AT_LANG_COMPILE(java)], [AT_JAVA_COMPILE([$1.java], [$2])]) [c++], [AT_COMPILE_CXX([$1], [$2])],
[java], [AT_JAVA_COMPILE([$1.java], [$2])],
[m4_fatal([unknown language: ]m4_defn([AT_LANG]))])[]dnl
])
# AT_FULL_COMPILE(OUTPUT, [OTHER1], [OTHER2]) # AT_FULL_COMPILE(OUTPUT, [OTHER1], [OTHER2])
# ------------------------------------------- # -------------------------------------------
@@ -807,31 +759,30 @@ m4_define([AT_LANG_COMPILE(java)], [AT_JAVA_COMPILE([$1.java], [$2])])
# OUTPUT-OTHER.c, OUTPUT-OTHER.cc, or OUTPUT-OTHER.java to OUTPUT or # OUTPUT-OTHER.c, OUTPUT-OTHER.cc, or OUTPUT-OTHER.java to OUTPUT or
# OUTPUT.java along with it. Relies on AT_SKEL_CC_IF and # OUTPUT.java along with it. Relies on AT_SKEL_CC_IF and
# AT_SKEL_JAVA_IF. # AT_SKEL_JAVA_IF.
m4_define([AT_FULL_COMPILE], [AT_LANG_DISPATCH([$0], $@)]) m4_define([AT_FULL_COMPILE],
m4_define([AT_FULL_COMPILE(c)], [m4_case(AT_LANG,
[AT_BISON_CHECK([-o $1.c $1.y]) [java],
AT_LANG_COMPILE([$1], [AT_BISON_CHECK([-o $1.java $1.y])
m4_join([ ], AT_LANG_COMPILE([$1],
[$1.c], m4_join([ ],
m4_ifval($2, [[$1-$2.c]]), [$1.java],
m4_ifval($3, [[$1-$3.c]])))]) m4_ifval($2, [[$1-$2.java]]),
m4_ifval($3, [[$1-$3.java]])))],
m4_define([AT_FULL_COMPILE(c++)], [c++],
[AT_BISON_CHECK([-o $1.cc $1.y]) [AT_BISON_CHECK([-o $1.cc $1.y])
AT_LANG_COMPILE([$1], AT_LANG_COMPILE([$1],
m4_join([ ], m4_join([ ],
[$1.cc], [$1.cc],
m4_ifval($2, [[$1-$2.cc]]), m4_ifval($2, [[$1-$2.cc]]),
m4_ifval($3, [[$1-$3.cc]])))]) m4_ifval($3, [[$1-$3.cc]])))],
[c],
m4_define([AT_FULL_COMPILE(java)], [AT_BISON_CHECK([-o $1.c $1.y])
[AT_BISON_CHECK([-o $1.java $1.y]) AT_LANG_COMPILE([$1],
AT_LANG_COMPILE([$1], m4_join([ ],
m4_join([ ], [$1.c],
[$1.java], m4_ifval($2, [[$1-$2.c]]),
m4_ifval($2, [[$1-$2.java]]), m4_ifval($3, [[$1-$3.c]])))])
m4_ifval($3, [[$1-$3.java]])))]) ])
@@ -879,7 +830,7 @@ AT_PARSER_CHECK([./c-and-cxx])
# AT_PARSER_CHECK(COMMAND, EXIT-STATUS, EXPOUT, EXPERR, [PRE]) # AT_PARSER_CHECK(COMMAND, EXIT-STATUS, EXPOUT, EXPERR, [PRE])
# ------------------------------------------------------------ # ------------------------------------------------------------
# So that we can run './testsuite PREPARSER='valgrind -q' for instance. # So that we can run `./testsuite PREPARSER='valgrind -q' for instance.
# #
# Get rid of spurious messages when compiled with --coverage: # Get rid of spurious messages when compiled with --coverage:
# +profiling:/[...]/lib/fprintf.gcda:Merge mismatch for summaries # +profiling:/[...]/lib/fprintf.gcda:Merge mismatch for summaries
@@ -893,7 +844,7 @@ AT_CHECK([sed >&2 -e '/^profiling:.*:Merge mismatch for summaries/d' stderr],
# AT_JAVA_PARSER_CHECK(COMMAND, EXIT-STATUS, EXPOUT, EXPERR, [PRE]) # AT_JAVA_PARSER_CHECK(COMMAND, EXIT-STATUS, EXPOUT, EXPERR, [PRE])
# ----------------------------------------------------------------- # -----------------------------------------------------------------
m4_define([AT_JAVA_PARSER_CHECK], m4_define([AT_JAVA_PARSER_CHECK],
[AT_CHECK([$5[ $SHELL ../../../javaexec.sh ]$1], [$2], [$3], [$4])]) [AT_CHECK([$5[ $SHELL $abs_top_builddir/javaexec.sh ]$1], [$2], [$3], [$4])])
# AT_TEST_TABLES_AND_PARSE(TITLE, COND-VALUE, TEST-SPEC, # AT_TEST_TABLES_AND_PARSE(TITLE, COND-VALUE, TEST-SPEC,
@@ -921,16 +872,16 @@ m4_define([AT_JAVA_PARSER_CHECK],
# that Bison exits with value 0, has no stdout, and has stderr # that Bison exits with value 0, has no stdout, and has stderr
# BISON-STDERR. # BISON-STDERR.
# #
# If TEST-SPEC contains the attribute 'last-state', check that the value # If TEST-SPEC contains the attribute `last-state', check that the value
# of TABLES-OR-LAST-STATE is the index of the last state generated for # of TABLES-OR-LAST-STATE is the index of the last state generated for
# the grammar; in other words, check the number of states (minus one). # the grammar; in other words, check the number of states (minus one).
# Otherwise, check that everything in the '.output' file starting with # Otherwise, check that everything in the `.output' file starting with
# the definition of state 0 is the same as the entire value of # the definition of state 0 is the same as the entire value of
# TABLES-OR-LAST-STATE. # TABLES-OR-LAST-STATE.
# #
# Expand the M4 in OTHER-CHECKS to perform additional checks of the # Expand the M4 in OTHER-CHECKS to perform additional checks of the
# '.output' file, which is named 'input.output', and/or grammar file, # `.output' file, which is named `input.output', and/or grammar file,
# which is named 'input.y'. # which is named `input.y'.
# #
# Finally, compile the generated parser and then run it using # Finally, compile the generated parser and then run it using
# AT_PARSER_CHECK with PARSER-EXIT-VALUE, PARSER-STDOUT, and # AT_PARSER_CHECK with PARSER-EXIT-VALUE, PARSER-STDOUT, and
@@ -1011,7 +962,7 @@ yylex (void)
m4_if(m4_index(m4_quote($3), [no-xml]), -1, m4_if(m4_index(m4_quote($3), [no-xml]), -1,
[AT_BISON_CHECK], [AT_BISON_CHECK],
[AT_BISON_CHECK_NO_XML])([[-Wall --report=all --defines -o input.c input.y]], [AT_BISON_CHECK_NO_XML])([[--report=all --defines -o input.c input.y]],
[0], [], m4_dquote($7)) [0], [], m4_dquote($7))
m4_if(m4_index(m4_quote($3), [last-state]), -1, m4_if(m4_index(m4_quote($3), [last-state]), -1,
@@ -1071,6 +1022,9 @@ m4_define([AT_SETUP],
AT_ARG_OPTION([compile-c-with-cxx], AT_ARG_OPTION([compile-c-with-cxx],
[compile C parsers with the C++ compiler]) [compile C parsers with the C++ compiler])
AT_ARG_OPTION([release],
[check xml and use push for pull])
AT_COLOR_TESTS AT_COLOR_TESTS
AT_TESTED([bison]) AT_TESTED([bison])
+22 -17
View File
@@ -53,7 +53,6 @@ TESTSUITE_AT = \
tests/headers.at \ tests/headers.at \
tests/input.at \ tests/input.at \
tests/java.at \ tests/java.at \
tests/javapush.at \
tests/local.at \ tests/local.at \
tests/named-refs.at \ tests/named-refs.at \
tests/output.at \ tests/output.at \
@@ -64,8 +63,7 @@ TESTSUITE_AT = \
tests/sets.at \ tests/sets.at \
tests/skeletons.at \ tests/skeletons.at \
tests/synclines.at \ tests/synclines.at \
tests/torture.at \ tests/torture.at
tests/types.at
TESTSUITE = $(top_srcdir)/tests/testsuite TESTSUITE = $(top_srcdir)/tests/testsuite
@@ -82,8 +80,17 @@ $(TESTSUITE): $(TESTSUITE_AT)
## Run the test suite. ## ## Run the test suite. ##
## -------------------- ## ## -------------------- ##
# Move into tests/ so that testsuite.dir etc. be created there. # Move into tests/ so that testsuite.dir etc. be created there. If a suffix is
RUN_TESTSUITE = $(TESTSUITE) -C tests $(TESTSUITEFLAGS) # specified, create it in a corresponding subdirectory of tests/.
RUN_TESTSUITE = dir=tests/$$suf \
&& { test -d $$dir || mkdir $$dir; } \
&& { test -f $$dir/atconfig \
&& diff -q $$dir/atconfig tests/atconfig \
|| cp tests/atconfig $$dir; } \
&& { test -f $$dir/atlocal \
&& diff -q $$dir/atlocal tests/atlocal \
|| cp tests/atlocal $$dir; } \
&& $(TESTSUITE) -C $$dir $$TESTSUITEFLAGS
check_SCRIPTS = $(BISON) tests/atconfig tests/atlocal check_SCRIPTS = $(BISON) tests/atconfig tests/atlocal
RUN_TESTSUITE_deps = $(TESTSUITE) $(check_SCRIPTS) RUN_TESTSUITE_deps = $(TESTSUITE) $(check_SCRIPTS)
@@ -101,28 +108,26 @@ installcheck-local: $(RUN_TESTSUITE_deps)
# Be real mean with it. # Be real mean with it.
.PHONY: maintainer-check-g++ .PHONY: maintainer-check-g++
maintainer-check-g++: $(RUN_TESTSUITE_deps) maintainer-check-g++: $(RUN_TESTSUITE_deps)
$(RUN_TESTSUITE) --compile-c-with-cxx suf=$@ $(RUN_TESTSUITE) --compile-c-with-cxx
.PHONY: maintainer-check-posix .PHONY: maintainer-check-posix
maintainer-check-posix: $(RUN_TESTSUITE_deps) maintainer-check-posix: $(RUN_TESTSUITE_deps)
$(RUN_TESTSUITE) POSIXLY_CORRECT=1 _POSIX2_VERSION=200112 suf=$@ $(RUN_TESTSUITE) POSIXLY_CORRECT=1 _POSIX2_VERSION=200112
.PHONY: maintainer-check-valgrind .PHONY: maintainer-check-valgrind
maintainer-check-valgrind: $(RUN_TESTSUITE_deps) maintainer-check-valgrind: $(RUN_TESTSUITE_deps)
test -z '$(VALGRIND)' || \ test -z '$(VALGRIND)' || \
$(RUN_TESTSUITE) \ suf=$@ $(RUN_TESTSUITE) \
PREBISON='$(VALGRIND_PREBISON)' PREPARSER='$(VALGRIND) -q' \ PREBISON='$(VALGRIND_PREBISON)' PREPARSER='$(VALGRIND) -q' \
VALGRIND_OPTS='--leak-check=full --show-reachable=yes' VALGRIND_OPTS='--leak-check=full --show-reachable=yes'
.PHONY: maintainer-check .PHONY: maintainer-check
maintainer-check: maintainer-check-posix maintainer-check-valgrind maintainer-check-g++ maintainer-check: maintainer-check-posix maintainer-check-valgrind maintainer-check-g++
.PHONY: maintainer-push-check .PHONY: maintainer-release-check
maintainer-push-check: maintainer-release-check:
$(MAKE) $(AM_MAKEFLAGS) maintainer-check \ $(MAKE) $(AM_MAKEFLAGS) \
TESTSUITEFLAGS='BISON_USE_PUSH_FOR_PULL=1 $(TESTSUITEFLAGS)' maintainer-check-g++ \
maintainer-check-posix \
.PHONY: maintainer-xml-check maintainer-check-valgrind \
maintainer-xml-check: TESTSUITEFLAGS+='--release'
$(MAKE) $(AM_MAKEFLAGS) maintainer-check \
TESTSUITEFLAGS='BISON_TEST_XML=1 $(TESTSUITEFLAGS)'
+6 -12
View File
@@ -37,11 +37,10 @@ foo: {};
]AT_BISON_CHECK([$3 $1 $5], 0)[ ]AT_BISON_CHECK([$3 $1 $5], 0)[
# Ignore the files non-generated files # Ignore the files non-generated files
]AT_CHECK([[find . -type f | ]AT_CHECK([find . -type f -and -not -path './$1' -and -not -path './testsuite.log' |
$PERL -ne ' sed 's,\./,,' |
s,\./,,; chomp; sort |
push @file, $_ unless m{^($1|testsuite.log)$}; xargs echo],
END { print join (" ", sort @file), "\n" }']],
[], [$4 [], [$4
])[ ])[
]$6[ ]$6[
@@ -63,13 +62,8 @@ AT_CHECK_OUTPUT([foo.y], [], [-dv -o foo.c],
[foo.c foo.h foo.output]) [foo.c foo.h foo.output])
AT_CHECK_OUTPUT([foo.y], [], [-dv -o foo.tab.c], AT_CHECK_OUTPUT([foo.y], [], [-dv -o foo.tab.c],
[foo.output foo.tab.c foo.tab.h]) [foo.output foo.tab.c foo.tab.h])
AT_CHECK_OUTPUT([foo.y], [], [-dv -y],
AT_CHECK_OUTPUT([foo.y], [], [-dv -g --xml -y], [y.output y.tab.c y.tab.h])
[y.dot y.output y.tab.c y.tab.h y.xml])
# With '-o y.tab.c', we expect 'y.output' etc. (for compatility with Yacc).
AT_CHECK_OUTPUT([foo.y], [], [-dv -g --xml -o y.tab.c],
[y.dot y.output y.tab.c y.tab.h y.xml])
AT_CHECK_OUTPUT([foo.y], [], [-dv -b bar], AT_CHECK_OUTPUT([foo.y], [], [-dv -b bar],
[bar.output bar.tab.c bar.tab.h]) [bar.output bar.tab.c bar.tab.h])
AT_CHECK_OUTPUT([foo.y], [], [-dv -g -o foo.c], AT_CHECK_OUTPUT([foo.y], [], [-dv -g -o foo.c],
+38 -6
View File
@@ -201,6 +201,28 @@ input.y:14.11-13: warning: rule useless in grammar [-Wother]
^^^ ^^^
]]) ]])
AT_BISON_CHECK([[input.y]], 0, [],
[[input.y: warning: 9 nonterminals useless in grammar [-Wother]
input.y: warning: 9 rules useless in grammar [-Wother]
input.y:6.1-8: warning: nonterminal useless in grammar: useless1 [-Wother]
input.y:7.1-8: warning: nonterminal useless in grammar: useless2 [-Wother]
input.y:8.1-8: warning: nonterminal useless in grammar: useless3 [-Wother]
input.y:9.1-8: warning: nonterminal useless in grammar: useless4 [-Wother]
input.y:10.1-8: warning: nonterminal useless in grammar: useless5 [-Wother]
input.y:11.1-8: warning: nonterminal useless in grammar: useless6 [-Wother]
input.y:12.1-8: warning: nonterminal useless in grammar: useless7 [-Wother]
input.y:13.1-8: warning: nonterminal useless in grammar: useless8 [-Wother]
input.y:14.1-8: warning: nonterminal useless in grammar: useless9 [-Wother]
input.y:6.11-13: warning: rule useless in grammar: useless1: '1' [-Wother]
input.y:7.11-13: warning: rule useless in grammar: useless2: '2' [-Wother]
input.y:8.11-13: warning: rule useless in grammar: useless3: '3' [-Wother]
input.y:9.11-13: warning: rule useless in grammar: useless4: '4' [-Wother]
input.y:10.11-13: warning: rule useless in grammar: useless5: '5' [-Wother]
input.y:11.11-13: warning: rule useless in grammar: useless6: '6' [-Wother]
input.y:12.11-13: warning: rule useless in grammar: useless7: '7' [-Wother]
input.y:13.11-13: warning: rule useless in grammar: useless8: '8' [-Wother]
input.y:14.11-13: warning: rule useless in grammar: useless9: '9' [-Wother]
]])
AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0, AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0,
[[Nonterminals useless in grammar [[Nonterminals useless in grammar
@@ -295,6 +317,16 @@ not-reduced.y:17.17-18.63: warning: rule useless in grammar [-Wother]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
]]) ]])
AT_BISON_CHECK([[not-reduced.y]], 0, [],
[[not-reduced.y: warning: 2 nonterminals useless in grammar [-Wother]
not-reduced.y: warning: 3 rules useless in grammar [-Wother]
not-reduced.y:14.1-13: warning: nonterminal useless in grammar: not_reachable [-Wother]
not-reduced.y:11.6-19: warning: nonterminal useless in grammar: non_productive [-Wother]
not-reduced.y:11.6-57: warning: rule useless in grammar: exp: non_productive [-Wother]
not-reduced.y:14.16-56: warning: rule useless in grammar: not_reachable: useful [-Wother]
not-reduced.y:17.17-18.63: warning: rule useless in grammar: non_productive: non_productive useless_token [-Wother]
]])
AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' not-reduced.output]], 0, AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' not-reduced.output]], 0,
[[Nonterminals useless in grammar [[Nonterminals useless in grammar
not_reachable not_reachable
@@ -365,9 +397,9 @@ AT_BISON_CHECK([[input.y]], 0, [],
input.y: warning: 3 rules useless in grammar [-Wother] input.y: warning: 3 rules useless in grammar [-Wother]
input.y:5.15-25: warning: nonterminal useless in grammar: underivable [-Wother] input.y:5.15-25: warning: nonterminal useless in grammar: underivable [-Wother]
input.y:6.14-24: warning: nonterminal useless in grammar: indirection [-Wother] input.y:6.14-24: warning: nonterminal useless in grammar: indirection [-Wother]
input.y:5.15-25: warning: rule useless in grammar [-Wother] input.y:5.15-25: warning: rule useless in grammar: exp: underivable [-Wother]
input.y:6.14-24: warning: rule useless in grammar [-Wother] input.y:6.14-24: warning: rule useless in grammar: underivable: indirection [-Wother]
input.y:7.14-24: warning: rule useless in grammar [-Wother] input.y:7.14-24: warning: rule useless in grammar: indirection: underivable [-Wother]
]]) ]])
AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0, AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0,
@@ -933,7 +965,7 @@ S: 'a' A 'a'
A: 'a' 'a' B A: 'a' 'a' B
; ;
B: 'a' B: 'a'
| %empty %prec 'a' | %prec 'a'
; ;
c: 'a' 'a' 'b' c: 'a' 'a' 'b'
| A | A
@@ -1533,8 +1565,8 @@ a: 'a' ;
and multiple reductions. The first reduction has more lookaheads than the and multiple reductions. The first reduction has more lookaheads than the
second, so the first should always be preferred as the default reduction if second, so the first should always be preferred as the default reduction if
enabled. The second reduction has one lookahead. */ enabled. The second reduction has one lookahead. */
b: %empty; b: ;
c: %empty; c: ;
]], ]],
dnl Visit each state mentioned above. dnl Visit each state mentioned above.
[['a', 'a']], [['a', 'a']],
+17 -16
View File
@@ -263,11 +263,11 @@ AT_CHECK([cat input.output], [],
0 $accept: expr $end 0 $accept: expr $end
1 $@1: %empty 1 $@1: /* empty */
2 expr: 'a' $@1 'b' 2 expr: 'a' $@1 'b'
3 $@2: %empty 3 $@2: /* empty */
4 expr: $@2 'c' 4 expr: $@2 'c'
@@ -373,13 +373,13 @@ AT_DATA([input.y],
%token <operator> LE 134 "<=" %token <operator> LE 134 "<="
%left OR "<=" %left OR "<="
%% %%
exp: %empty; exp: ;
%% %%
]]) ]])
AT_BISON_CHECK([-v -Wall -o input.c input.y], 0, [], AT_BISON_CHECK([-v -o input.c input.y], 0, [],
[[input.y:3.1-5: warning: useless precedence and associativity for "||" [-Wprecedence] [[input.y:1.29-32: warning: useless associativity for "||" [-Wother]
input.y:3.1-5: warning: useless precedence and associativity for "<=" [-Wprecedence] input.y:2.29-32: warning: useless associativity for "<=" [-Wother]
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -405,13 +405,14 @@ default: 'a' }
AT_BISON_CHECK([input.y], [1], [], AT_BISON_CHECK([input.y], [1], [],
[[input.y:2.1: error: invalid character: '?' [[input.y:2.1: error: invalid character: '?'
input.y:3.14: error: syntax error, unexpected } input.y:3.14: error: invalid character: '}'
input.y:4.1: error: invalid character: '%' input.y:4.1: error: invalid character: '%'
input.y:4.2: error: invalid character: '&' input.y:4.2: error: invalid character: '&'
input.y:5.1-17: error: invalid directive: '%a-does-not-exist' input.y:5.1-17: error: invalid directive: '%a-does-not-exist'
input.y:6.1: error: invalid character: '%' input.y:6.1: error: invalid character: '%'
input.y:6.2: error: invalid character: '-' input.y:6.2: error: invalid character: '-'
input.y:7.1-8.0: error: missing '%}' at end of file input.y:7.1-8.0: error: missing '%}' at end of file
input.y:7.1-8.0: error: syntax error, unexpected %{...%}
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -572,7 +573,7 @@ AT_CHECK([cat input.output], 0,
2 CONST_DEC_LIST: CONST_DEC 2 CONST_DEC_LIST: CONST_DEC
3 | CONST_DEC_LIST CONST_DEC 3 | CONST_DEC_LIST CONST_DEC
4 $@1: %empty 4 $@1: /* empty */
5 CONST_DEC: $@1 undef_id_tok '=' const_id_tok ';' 5 CONST_DEC: $@1 undef_id_tok '=' const_id_tok ';'
@@ -720,7 +721,7 @@ AT_KEYWORDS([report])
AT_DATA([input.y], AT_DATA([input.y],
[[%% [[%%
statement: struct_stat; statement: struct_stat;
struct_stat: %empty | if else; struct_stat: /* empty. */ | if else;
if: "if" "const" "then" statement; if: "if" "const" "then" statement;
else: "else" statement; else: "else" statement;
%% %%
@@ -868,7 +869,7 @@ type: DATA
| INVALID | INVALID
; ;
body: %empty body: /* empty */
| body member | body member
; ;
@@ -928,7 +929,7 @@ $1
%token B %token B
%% %%
program: %empty program: /* empty */
| program e ';' | program e ';'
| program error ';'; | program error ';';
@@ -1144,15 +1145,15 @@ sr_conflict:
]AT_YYLEX_DEFINE([{ 1, 2, 3, 0 }])[ ]AT_YYLEX_DEFINE([{ 1, 2, 3, 0 }])[
]AT_MAIN_DEFINE[ ]AT_MAIN_DEFINE[
]]) ]])
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-Wall -o input.c input.y]], [[0]],, AT_BISON_CHECK([[-o input.c input.y]], [[0]],,
[[input.y:24.5-19: warning: rule useless in parser due to conflicts [-Wother] [[input.y:24.5-19: warning: rule useless in parser due to conflicts: start: start [-Wother]
input.y:28.5-19: warning: rule useless in parser due to conflicts [-Wother] input.y:28.5-19: warning: rule useless in parser due to conflicts: sr_conflict: TK2 "tok alias" [-Wother]
input.y:18.1-5: warning: useless precedence and associativity for TK1 [-Wprecedence] input.y:18.7-9: warning: useless associativity for TK1 [-Wother]
]]) ]])
AT_COMPILE([[input]]) AT_COMPILE([[input]])
AT_PARSER_CHECK([[./input]]) AT_PARSER_CHECK([[./input]])
AT_BISON_OPTION_POPDEFS
AT_CLEANUP AT_CLEANUP
+5 -5
View File
@@ -86,7 +86,7 @@ AT_CHECK([[cat sets]], [],
0 e $end 0 e $end
e derives e derives
1 'e' 1 'e'
2 %empty 2 /* empty */
NULLABLE NULLABLE
$accept: no $accept: no
e: yes e: yes
@@ -100,10 +100,10 @@ FDERIVES
$accept derives $accept derives
0 e $end 0 e $end
1 'e' 1 'e'
2 %empty 2 /* empty */
e derives e derives
1 'e' 1 'e'
2 %empty 2 /* empty */
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -113,7 +113,7 @@ AT_CLEANUP
## Broken Closure. ## ## Broken Closure. ##
## ---------------- ## ## ---------------- ##
# TC was once broken during a massive 'simplification' of the code. # TC was once broken during a massive `simplification' of the code.
# It resulted in bison dumping core on the following grammar (the # It resulted in bison dumping core on the following grammar (the
# computation of FIRSTS uses TC). It managed to produce a pretty # computation of FIRSTS uses TC). It managed to produce a pretty
# exotic closure: # exotic closure:
@@ -263,7 +263,7 @@ AT_CLEANUP
# In some weird cases Bison could compute an incorrect final state # In some weird cases Bison could compute an incorrect final state
# number. This happens only if the $end token is used in the user # number. This happens only if the $end token is used in the user
# grammar, which is a very suspicious accidental feature introduced as # grammar, which is a very suspicious accidental feature introduced as
# a side effect of allowing the user to name $end using '%token END 0 # a side effect of allowing the user to name $end using `%token END 0
# "end of file"'. # "end of file"'.
AT_SETUP([Accept]) AT_SETUP([Accept])
+1 -1
View File
@@ -23,7 +23,7 @@ AT_BANNER([[User Actions.]])
# -------------------------- # --------------------------
# Compile FILE expecting an error, and save in the file stdout the # Compile FILE expecting an error, and save in the file stdout the
# normalized output. Ignore the exit status, since some compilers # normalized output. Ignore the exit status, since some compilers
# (e.g. c89 on IRIX 6.5) trigger warnings on '#error', instead of # (e.g. c89 on IRIX 6.5) trigger warnings on `#error', instead of
# errors. # errors.
m4_define([AT_SYNCLINES_COMPILE], m4_define([AT_SYNCLINES_COMPILE],
[AT_CHECK([$CC $CFLAGS $CPPFLAGS -c $1], [ignore], [], [stderr]) [AT_CHECK([$CC $CFLAGS $CPPFLAGS -c $1], [ignore], [], [stderr])
+5 -9
View File
@@ -35,9 +35,6 @@ m4_include([sets.at])
# Testing grammar reduction. # Testing grammar reduction.
m4_include([reduce.at]) m4_include([reduce.at])
# Testing conflicts detection and resolution.
m4_include([conflicts.at])
# Testing that #lines are correct. # Testing that #lines are correct.
m4_include([synclines.at]) m4_include([synclines.at])
@@ -47,8 +44,8 @@ m4_include([headers.at])
# Testing that user actions are properly performed. # Testing that user actions are properly performed.
m4_include([actions.at]) m4_include([actions.at])
# Testing semantic types support. # Testing conflicts detection and resolution.
m4_include([types.at]) m4_include([conflicts.at])
# Fulling testing (compilation and execution of the parser) on calc. # Fulling testing (compilation and execution of the parser) on calc.
m4_include([calc.at]) m4_include([calc.at])
@@ -63,18 +60,17 @@ m4_include([existing.at])
# Some old bugs. # Some old bugs.
m4_include([regression.at]) m4_include([regression.at])
# Push parsing specific tests.
m4_include([push.at])
# Some C++ specific tests. # Some C++ specific tests.
m4_include([c++.at]) m4_include([c++.at])
# And some Java specific tests. # And some Java specific tests.
m4_include([java.at]) m4_include([java.at])
m4_include([javapush.at])
# GLR tests: # GLR tests:
# C++ types, simplified # C++ types, simplified
m4_include([cxx-type.at]) m4_include([cxx-type.at])
# Regression tests # Regression tests
m4_include([glr-regression.at]) m4_include([glr-regression.at])
# Push parsing specific tests.
m4_include([push.at])
-230
View File
@@ -1,230 +0,0 @@
# Value type. -*- Autotest -*-
# Copyright (C) 2013 Free Software Foundation, Inc.
# 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/>.
AT_BANNER([[Value type tests.]])
## ----------------------------------- ##
## %union vs. %define api.value.type. ##
## ----------------------------------- ##
AT_SETUP([[%union vs. %define api.value.type]])
AT_DATA([[input.y]],
[[%union { int ival; }
%define api.value.type union-directive
%%
exp: %empty;
]])
AT_BISON_CHECK([[input.y]], [[1]], [[]],
[[input.y:2.9-22: error: '%union' and '%define api.value.type' cannot be used together
]])
AT_CLEANUP
## ---------------------------------------- ##
## %yacc vs. %define api.value.type union. ##
## ---------------------------------------- ##
AT_SETUP([[%yacc vs. %define api.value.type union]])
AT_DATA([[input.y]],
[[%yacc
%define api.value.type union
%%
exp: %empty;
]])
AT_BISON_CHECK([[input.y]], [[1]], [[]],
[[input.y:2.9-22: error: '%yacc' and '%define api.value.type "union"' cannot be used together
]])
AT_CLEANUP
## ---------------- ##
## api.value.type. ##
## ---------------- ##
# AT_TEST($1: BISON-DIRECTIVES,
# $2: MORE-BISON-DIRECTIVES,
# $3: PARSER-ACTION,
# $4: INPUT, $5: SCANNER-ACTION,
# $6: RESULT)
# --------------------------------------
# Compile the grammar and check the expected result.
# BISON-DIRECTIVES are passed to AT_SETUP, contrary to MORE-BISON-DIRECTIVES.
m4_pushdef([AT_TEST],
[
AT_SETUP([$1])
AT_KEYWORDS([api.value.type])
AT_BISON_OPTION_PUSHDEFS([%debug $1 $2])
AT_DATA_GRAMMAR([test.y],
[[%debug
%code
{
# include <stdio.h>
# include <stdlib.h>
]AT_YYERROR_DECLARE[
]AT_YYLEX_DECLARE[
}
]$1[
]$2[
%%
start: $3;
%%
]AT_YYERROR_DEFINE[
]AT_YYLEX_DEFINE([$4], [$5])[
]AT_MAIN_DEFINE[
]])
AT_FULL_COMPILE([[test]])
AT_PARSER_CHECK([./test], 0, [$6
], [stderr])
AT_BISON_OPTION_POPDEFS
AT_CLEANUP
])
m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc], [glr.cc]],
[# A built-in type.
AT_TEST([%skeleton "]b4_skel["
%define api.value.type {double}],
[],
['1' '2' { printf ("%2.1f\n", $1 + $2); }],
["12"],
[AT_VAL = (res - '0') / 10.0],
[0.3])
# A typedef which looks like a Bison keyword, but it's using braces.
AT_TEST([%skeleton "]b4_skel["
%define api.value.type {variant}],
[%code requires { typedef double variant; }],
['1' '2' { printf ("%2.1f\n", $1 + $2); }],
["12"],
[AT_VAL = (res - '0') / 10.0],
[0.3])
# A user defined struct.
AT_TEST([%skeleton "]b4_skel["
%define api.value.type {struct foo}],
[%code requires { struct foo { float fval; int ival; }; }],
['1' '2'
{ printf ("%d %2.1f\n", $1.ival + $2.ival, $1.fval + $2.fval); }],
["12"],
[AT_VAL.ival = (res - '0') * 10;
AT_VAL.fval = (res - '0') / 10.f],
[30 0.3])
# A user defined struct that uses pointers.
AT_TEST([%skeleton "]b4_skel["
%define api.value.type {struct bar}],
[%code requires
{
struct u
{
int ival;
};
struct bar
{
struct u *up;
};
}
%token <up->ival> '1' '2'
%printer { ]AT_SKEL_CC_IF([[yyoutput << $$]],
[[fprintf (yyo, "%d", $$)]])[; } <up->ival>
],
['1' '2'
{
printf ("%d %d\n", $1, $<up->ival>2);
free ($<up>1);
free ($<up>2);
}],
["12"],
[AT_VAL.up = (struct u *) malloc (sizeof *AT_VAL.up);
assert (AT_VAL.up);
AT_VAL.up->ival = res - '0';],
[1 2])
# A user defined union.
AT_TEST([%skeleton "]b4_skel["
%define api.value.type {union foo}],
[%code requires { union foo { float fval; int ival; }; }],
['1' '2' { printf ("%d %2.1f\n", $1.ival, $2.fval); }],
["12"],
[if (res == '1')
AT_VAL.ival = 10;
else
AT_VAL.fval = .2f],
[10 0.2])
# A %union.
AT_TEST([%skeleton "]b4_skel["
%union { float fval; int ival; };],
[%token <ival> '1';
%token <fval> '2';],
['1' '2' { printf ("%d %2.1f\n", $1, $2); }],
["12"],
[if (res == '1')
AT_VAL.ival = 10;
else
AT_VAL.fval = 0.2f],
[10 0.2])
# A Bison-defined union.
# The tokens names are not available directly in C++, we use their
# user number to keep it simple between C and C++.
AT_TEST([%skeleton "]b4_skel["
%define api.value.type union],
[%token <int> ONE 101;
%token <float> TWO 102 THREE 103;
%printer { ]AT_SKEL_CC_IF([[yyoutput << $$]],
[[fprintf (yyo, "%d", $$)]])[; } <int>
%printer { ]AT_SKEL_CC_IF([[yyoutput << $$]],
[[fprintf (yyo, "%f", $$)]])[; } <float>
],
[ONE TWO THREE { printf ("%d %2.1f %2.1f\n", $1, $2, $3); }],
[{ 101, 102, 103, EOF }],
[if (res == 101)
AT_VAL.ONE = 10;
else if (res == 102)
AT_VAL.TWO = .2f;
else if (res == 103)
AT_VAL.THREE = 3.3f],
[10 0.2 3.3])
# A Bison-defined variant, for lalr1.cc only.
m4_if(b4_skel, [lalr1.cc], [
AT_TEST([%skeleton "]b4_skel["
%define api.value.type variant],
[%token <int> '1';
%token <std::string> '2';],
['1' '2' { std::cout << $1 << ", " << $2 << std::endl; }],
["12"],
[if (res == '1')
AT_VAL.build(10);
else
AT_VAL.build<std::string>("two");],
[10, two])])
])
m4_popdef([AT_TEST])