* Noteworthy changes in release ?.? (????-??-??) [?]
+** Incompatible changes
+
+*** Obsolete features
+
+ Support for YYFAIL is removed (deprecated in Bison 2.4.2).
+ Support for yystype and yyltype (instead of YYSTYPE and YYLTYPE)
+ is removed (deprecated in Bison 1.875).
+ Support for YYPARSE_PARAM is removed (deprecated in Bison 1.875).
+
+** Warnings
+
+*** Deprecated constructs
+
+ The new 'deprecated' warning category flags obsolete constructs whose
+ support will be discontinued. It is enabled by default. These warnings
+ used to be reported as 'other' warnings.
+
+*** Warning categories are now displayed
+
+ For instance:
+
+ foo.y:4.6: warning: type clash on default action: <foo> != <bar> [-Wother]
+
+*** Useless semantic types
+
+ Bison now warns about useless (uninhabited) semantic types. Since
+ semantic types are not declared to Bison (they are defined in the opaque
+ %union structure), it is %printer/%destructor directives about useless
+ types that trigger the warning:
+
+ %token <type1> term
+ %type <type2> nterm
+ %printer {} <type1> <type3>
+ %destructor {} <type2> <type4>
+ %%
+ nterm: term { $$ = $1; };
+
+ 3.28-34: warning: type <type3> is used, but is not associated to any symbol
+ 4.28-34: warning: type <type4> is used, but is not associated to any symbol
+
+*** Undefined but unused symbols
+
+ Bison used to raise an error for undefined symbols that are not used in
+ the grammar. This is now only a warning.
+
+ %printer {} symbol1
+ %destructor {} symbol2
+ %type <type> symbol3
+ %%
+ exp: "a";
+
+*** Useless destructors or printers
+
+ Bison now warns about useless destructors or printers. In the following
+ example, the printer for <type1>, and the destructor for <type2> are
+ useless: all symbols of <type1> (token1) already have a printer, and all
+ symbols of type <type2> (token2) already have a destructor.
+
+ %token <type1> token1
+ <type2> token2
+ <type3> token3
+ <type4> token4
+ %printer {} token1 <type1> <type3>
+ %destructor {} token2 <type2> <type4>
+
+*** Conflicts
+
+ The warnings and error messages about shift/reduce and reduce/reduce
+ conflicts have been normalized. For instance on the following foo.y file:
+
+ %glr-parser
+ %%
+ exp: exp '+' exp | '0' | '0';
+
+ compare the previous version of bison:
+
+ $ bison foo.y
+ foo.y: conflicts: 1 shift/reduce, 2 reduce/reduce
+ $ bison -Werror foo.y
+ bison: warnings being treated as errors
+ foo.y: conflicts: 1 shift/reduce, 2 reduce/reduce
+
+ with the new behavior:
+
+ $ bison foo.y
+ foo.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
+ foo.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
+ $ bison -Werror foo.y
+ bison: warnings being treated as errors
+ foo.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
+ foo.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
+
+ When %expect or %expect-rr is used, such as with bar.y:
+
+ %expect 0
+ %glr-parser
+ %%
+ exp: exp '+' exp | '0' | '0';
+
+ Former behavior:
+
+ $ bison bar.y
+ bar.y: conflicts: 1 shift/reduce, 2 reduce/reduce
+ bar.y: expected 0 shift/reduce conflicts
+ bar.y: expected 0 reduce/reduce conflicts
+
+ New one:
+
+ $ bison bar.y
+ bar.y: shift/reduce conflicts: 1 found, 0 expected
+ bar.y: reduce/reduce conflicts: 2 found, 0 expected
+
+** Additional yylex/yyparse arguments
+
+ The new directive %param declares additional arguments to both yylex and
+ yyparse. The %lex-param, %parse-param, and %param directives support one
+ or more arguments. Instead of
+
+ %lex-param {arg1_type *arg1}
+ %lex-param {arg2_type *arg2}
+ %parse-param {arg1_type *arg1}
+ %parse-param {arg2_type *arg2}
+
+ one may now declare
+
+ %param {arg1_type *arg1} {arg2_type *arg2}
+
+** Java skeleton improvements
+
+ 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"
+ and "%define init_throws".
+
+** C++ skeletons improvements
+
+*** The parser header is no longer mandatory (lalr1.cc, glr.cc)
+
+ Using %defines is now optional. Without it, the needed support classes
+ are defined in the generated parser, instead of additional files (such as
+ location.hh, position.hh and stack.hh).
+
+*** Locations are no longer mandatory (lalr1.cc, glr.cc)
+
+ Both lalr1.cc and glr.cc no longer require %location.
+
+*** syntax_error exception (lalr1.cc)
+
+ The C++ parser features a syntax_error exception, which can be
+ thrown from the scanner or from user rules to raise syntax errors.
+ This facilitates reporting errors caught in sub-functions (e.g.,
+ rejecting too large integral literals from a conversion function
+ used by the scanner, or rejecting invalid combinations from a
+ factory invoked by the user actions).
+
+** Variable api.tokens.prefix
+
+ The variable api.tokens.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.tokens.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.namespace
+
+ The 'namespace' variable is renamed 'api.namespace'. Backward
+ compatibility is ensured, but upgrading is recommended.
+
+** 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".
+
+** Semantic predicates
+
+ 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.
+
+* Noteworthy changes in release ?.? (????-??-??) [?]
+
** Bug fixes
Bugs in the test suite have been fixed.
Incorrect definitions of YY_, issued by yacc.c when no parser header is
generated, are removed.
+ ** Changes in the format of errors and exceptions output
+
+ This used to be the format of many error reports:
+
+ foo.y:5.10-24: result type clash on merge function 'merge': <t3> != <t2>
+ foo.y:4.13-27: previous declaration
+
+ It is now:
+
+ foo.y:5.10-25: result type clash on merge function 'merge': <t3> != <t2>
+ foo.y:4.13-27: previous declaration
+
* Noteworthy changes in release 2.6.2 (2012-08-03) [stable]
** Bug fixes
* Noteworthy changes in release 2.6.1 (2012-07-30) [stable]
- Bison no longer executes user-specified M4 code when processing a grammar.
+ Bison no longer executes user-specified M4 code when processing a grammar.
** Future Changes
* Noteworthy changes in release 2.6 (2012-07-19) [stable]
-** Future Changes
+** Future changes:
The next major release of Bison will drop support for the following
deprecated features. Please report disagreements to bug-bison@gnu.org.
LocalWords: namespaces strerror const autoconfiguration Dconst Autoconf's FDL
LocalWords: Automake TMPDIR LESSEQ ylwrap endif yydebug YYTOKEN YYLSP ival hh
LocalWords: extern YYTOKENTYPE TOKENTYPE yytokentype tokentype STYPE lval pdf
- LocalWords: lang yyoutput dvi html ps POSIX lvalp llocp
+ LocalWords: lang yyoutput dvi html ps POSIX lvalp llocp Wother nterm arg init
+ LocalWords: TOK
Local Variables:
mode: outline
Matt Rosing rosing@peakfive.com
Michael Hayes m.hayes@elec.canterbury.ac.nz
Michael Raskin 7c6f434c@mail.ru
+Michiel De Wilde mdewilde.agilent@gmail.com
Mickael Labau labau_m@epita.fr
Mike Castle dalgoda@ix.netcom.com
Neil Booth NeilB@earthling.net
Peter Fales psfales@lucent.com
Peter Hamorsky hamo@upjs.sk
Piotr Gackiewicz gacek@intertel.com.pl
+Quentin Hocquet hocquet@gostai.com
Quoc Peyrot chojin@lrde.epita.fr
R Blake blakers@mac.com
Raja R Harinath harinath@cs.umn.edu
Stefano Lattarini stefano.lattarini@gmail.com
Steve Murphy murf@parsetree.com
Sum Wu sum@geekhouse.org
+ Théophile Ranquet theophile.ranquet@gmail.com
Thiru Ramakrishnan thiru.ramakrishnan@gmail.com
Tim Josling tej@melbpc.org.au
Tim Landscheidt tim@tim-landscheidt.de
Local Variables:
mode: text
+ coding: utf-8
End:
-----
#include "files.h"
#include "getargs.h"
+warnings warnings_flag =
+ Wconflicts_sr | Wconflicts_rr | Wdeprecated | Wother;
+
bool complaint_issued;
static unsigned *indent_ptr = 0;
-\f
+void
+warnings_print_categories (warnings warn_flags)
+{
+ if (! (warn_flags & silent))
+ {
+ char const *warn_names[] =
+ {
+ "midrule-values",
+ "yacc",
+ "conflicts-sr",
+ "conflicts-rr",
+ "deprecated",
+ "other"
+ };
+
+ bool any = false;
+ int i;
+ for (i = 0; i < ARRAY_CARDINALITY (warn_names); ++i)
+ if (warn_flags & 1 << i)
+ {
+ fprintf (stderr, "%s-W%s", any ? ", " : " [", warn_names[i]);
+ any = true;
+ }
+ if (any)
+ fprintf (stderr, "]");
+ }
+}
/** Report an error message.
*
* \param loc the location, defaulting to the current file,
* or the program name.
+ * \param flags the category for this message.
* \param prefix put before the message (e.g., "warning").
* \param message the error message, a printf format string. Iff it
* ends with ": ", then no trailing newline is printed,
*/
static
void
-error_message (location *loc,
- const char *prefix,
- const char *message, va_list args)
+error_message (const location *loc, warnings flags, const char *prefix,
+ const char *message, va_list args)
{
+ (void) flags;
unsigned pos = 0;
if (loc)
fprintf (stderr, "%s: ", prefix);
vfprintf (stderr, message, args);
+ warnings_print_categories (flags);
{
size_t l = strlen (message);
- if (l < 2 || message[l-2] != ':' || message[l-1] != ' ') {
- putc ('\n', stderr);
- fflush (stderr);
- }
+ if (l < 2 || message[l-2] != ':' || message[l-1] != ' ')
+ {
+ putc ('\n', stderr);
+ fflush (stderr);
+ }
}
}
-/** Wrap error_message() with varargs handling. */
-#define ERROR_MESSAGE(Loc, Prefix, Message) \
-{ \
- va_list args; \
- va_start (args, Message); \
- error_message (Loc, Prefix, Message, args); \
- va_end (args); \
-}
-
-
-/*--------------------------------.
-| Report a warning, and proceed. |
-`--------------------------------*/
+/** Raise a complaint. That can be a fatal error, a complaint or just a
+ warning. */
-void
-set_warning_issued (void)
+static inline void
+complains (const location *loc, warnings flags, const char *message,
+ va_list args)
{
- static bool warning_issued = false;
- if (!warning_issued && (warnings_flag & warnings_error))
+ if (flags & complaint)
{
- error_message (loc, complaint, NULL, message, args);
- fprintf (stderr, "%s: warnings being treated as errors\n", program_name);
++ error_message (loc, complaint,
++ indent_ptr && *indent_ptr ? NULL : _("error"),
++ message, args);
complaint_issued = true;
}
- warning_issued = true;
-}
-
-void
-warn_at (location loc, const char *message, ...)
-{
- if (!(warnings_flag & warnings_other))
- return;
- set_warning_issued ();
- ERROR_MESSAGE (&loc, _("warning"), message);
-}
-
-void
-warn_at_indent (location loc, unsigned *indent,
- const char *message, ...)
-{
- if (!(warnings_flag & warnings_other))
- return;
- set_warning_issued ();
- indent_ptr = indent;
- ERROR_MESSAGE (&loc, *indent ? NULL : _("warning"), message);
+ else if (flags & fatal)
+ {
+ error_message (loc, fatal, _("fatal error"), message, args);
+ exit (EXIT_FAILURE);
+ }
+ else if (flags & Wyacc)
+ {
+ if (yacc_flag)
+ {
+ error_message (loc, flags, NULL, message, args);
+ complaint_issued = true;
+ }
+ else if (warnings_flag & Wyacc)
+ {
+ set_warning_issued ();
- error_message (loc, flags, _("warning"), message, args);
++ error_message (loc, flags,
++ indent_ptr && *indent_ptr ? NULL : _("warning"),
++ message, args);
+ }
+ }
+ else if (warnings_flag & flags)
+ {
+ set_warning_issued ();
- error_message (loc, flags, _("warning"), message, args);
++ error_message (loc, flags,
++ indent_ptr && *indent_ptr ? NULL : _("warning"),
++ message, args);
+ }
}
void
-warn (const char *message, ...)
+complain (warnings flags, const char *message, ...)
{
- if (!(warnings_flag & warnings_other))
- return;
- set_warning_issued ();
- ERROR_MESSAGE (NULL, _("warning"), message);
+ va_list args;
+ va_start (args, message);
+ complains (NULL, flags, message, args);
+ va_end (args);
}
-
-/*-----------------------------------------------------------.
-| An error has occurred, but we can proceed, and die later. |
-`-----------------------------------------------------------*/
-
void
-complain_at (location loc, const char *message, ...)
+complain_at (location loc, warnings flags, const char *message, ...)
{
- ERROR_MESSAGE (&loc, _("error"), message);
- complaint_issued = true;
+ va_list args;
+ va_start (args, message);
+ complains (&loc, flags, message, args);
+ va_end (args);
}
-void
-complain_at_indent (location loc, unsigned *indent,
- const char *message, ...)
+void complain_at_indent (location loc, warnings flags, unsigned *indent,
+ const char *message, ...)
{
indent_ptr = indent;
- ERROR_MESSAGE (&loc, *indent ? NULL : _("error"), message);
- complaint_issued = true;
-}
-void
-complain (const char *message, ...)
-{
- ERROR_MESSAGE (NULL, _("error"), message);
- complaint_issued = true;
+ va_list args;
+ va_start (args, message);
+ complains (&loc, flags, message, args);
+ va_end (args);
}
-/*--------------------------------------------------------------.
-| An incompatibility with POSIX Yacc: mapped either to warn* or |
-| complain* depending on yacc_flag. |
-`--------------------------------------------------------------*/
+
+/*--------------------------------.
+| Report a warning, and proceed. |
+`--------------------------------*/
void
-yacc_at (location loc, const char *message, ...)
+set_warning_issued (void)
{
- if (yacc_flag)
+ static bool warning_issued = false;
+ if (!warning_issued && (warnings_flag & Werror))
{
- ERROR_MESSAGE (&loc, NULL, message);
+ fprintf (stderr, "%s: warnings being treated as errors\n", program_name);
complaint_issued = true;
}
- else if (warnings_flag & warnings_yacc)
- {
- set_warning_issued ();
- ERROR_MESSAGE (&loc, _("warning"), message);
- }
-}
-
-void
-midrule_value_at (location loc, const char *message, ...)
-{
- if (!(warnings_flag & warnings_midrule_values))
- return;
- set_warning_issued ();
- ERROR_MESSAGE (&loc, _("warning"), message);
-}
-
-/*-------------------------------------------------.
-| A severe error has occurred, we cannot proceed. |
-`-------------------------------------------------*/
-
-void
-fatal_at (location loc, const char *message, ...)
-{
- ERROR_MESSAGE (&loc, _("fatal error"), message);
- exit (EXIT_FAILURE);
-}
-
-void
-fatal (const char *message, ...)
-{
- ERROR_MESSAGE (NULL, _("fatal error"), message);
- exit (EXIT_FAILURE);
+ warning_issued = true;
}
# include "location.h"
-# ifdef __cplusplus
-extern "C" {
-# endif
+/*-------------.
+| --warnings. |
+`-------------*/
+
+typedef enum
+ {
+ Wnone = 0, /**< Issue no warnings. */
+ Wmidrule_values = 1 << 0, /**< Unset or unused midrule values. */
+ Wyacc = 1 << 1, /**< POSIXME. */
+ Wconflicts_sr = 1 << 2, /**< S/R conflicts. */
+ Wconflicts_rr = 1 << 3, /**< R/R conflicts. */
+ Wdeprecated = 1 << 4, /**< Obsolete constructs. */
+ Wother = 1 << 5, /**< All other warnings. */
+
+ Werror = 1 << 10, /**< Warnings are treated as errors. */
+ complaint = 1 << 11, /**< All complaints. */
+ fatal = 1 << 12, /**< All fatal errors. */
+ silent = 1 << 13, /**< Do not display the warning type. */
+ Wall = ~Werror /**< All above warnings. */
+ } warnings;
+
+/** What warnings are issued. */
+extern warnings warnings_flag;
+
+/** Display a "[-Wyacc]" like message on stderr. */
+void warnings_print_categories (warnings warn_flags);
+ /* Sub-messages indent. */
+ #define SUB_INDENT (4)
+
/** Record that a warning is about to be issued, and treat it as an
- error if <tt>warnings_flag & warnings_error</tt>. This is exported
+ error if <tt>warnings_flag & Werror</tt>. This is exported
only for the sake of Yacc-compatible conflict reports in conflicts.c.
All other warnings should be implemented in complain.c and should use
the normal warning format. */
void set_warning_issued (void);
-/** Informative messages, but we proceed. Report iff
- <tt>warnings_flag & warnings_other</tt>. */
-
-void warn (char const *format, ...)
- __attribute__ ((__format__ (__printf__, 1, 2)));
-
-void warn_at (location loc, char const *format, ...)
+/** Make a complaint, but don't specify any location. */
+void complain (warnings flags, char const *message, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
-/* Generate a message aligned by an indent.
- When *indent == 0, assign message's indent to *indent,
- When *indent > 0, align the message by *indent value. */
-void warn_at_indent (location loc, unsigned *indent,
- char const *format, ...)
+/** Make a complaint with location. */
+void complain_at (location loc, warnings flags, char const *message, ...)
__attribute__ ((__format__ (__printf__, 3, 4)));
-/** An error, but we continue and die later. */
-
-void complain (char const *format, ...)
- __attribute__ ((__format__ (__printf__, 1, 2)));
-
-void complain_at (location loc, char const *format, ...)
- __attribute__ ((__format__ (__printf__, 2, 3)));
-
-/* Generate a message aligned by an indent.
- When *indent == 0, assign message's indent to *indent,
- When *indent > 0, align the message by *indent value. */
-void complain_at_indent (location loc, unsigned *indent,
- char const *format, ...)
- __attribute__ ((__format__ (__printf__, 3, 4)));
-
-/** An incompatibility with POSIX Yacc: mapped either to warn* or
- complain* depending on yacc_flag. */
-
-void yacc_at (location loc, char const *format, ...)
- __attribute__ ((__format__ (__printf__, 2, 3)));
-
-/** A midrule-value warning. Report iff
- <tt>warnings_flag & warnings_midrule_values</tt>. */
-
-void midrule_value_at (location loc, char const *format, ...)
- __attribute__ ((__format__ (__printf__, 2, 3)));
-
-/** A fatal error, causing immediate exit. */
-
-void fatal (char const *format, ...)
- __attribute__ ((__noreturn__, __format__ (__printf__, 1, 2)));
-
-void fatal_at (location loc, char const *format, ...)
- __attribute__ ((__noreturn__, __format__ (__printf__, 2, 3)));
+/** Make a complaint with location and some indentation. */
+void complain_at_indent (location loc, warnings flags, unsigned *indent,
+ char const *message, ...)
+ __attribute__ ((__format__ (__printf__, 4, 5)));
/** Whether an error was reported. */
extern bool complaint_issued;
-# ifdef __cplusplus
-}
-# endif
-
#endif /* !COMPLAIN_H_ */
#include <c-strcase.h>
#include <configmake.h>
#include <error.h>
-
-/* Hack to get <getopt.h> to declare getopt with a prototype. */
-#if lint && ! defined __GNU_LIBRARY__
-# define __GNU_LIBRARY__
-# define HACK_FOR___GNU_LIBRARY___PROTOTYPE 1
-#endif
-
#include <getopt.h>
-
-#ifdef HACK_FOR___GNU_LIBRARY___PROTOTYPE
-# undef __GNU_LIBRARY__
-# undef HACK_FOR___GNU_LIBRARY___PROTOTYPE
-#endif
-
#include <progname.h>
#include "complain.h"
#include "quote.h"
#include "uniqstr.h"
-bool debug_flag;
bool defines_flag;
bool graph_flag;
bool xml_flag;
-bool locations_flag;
bool no_lines_flag;
bool token_table_flag;
-bool yacc_flag; /* for -y */
-
-bool error_verbose = false;
+bool yacc_flag; /* for -y */
bool nondeterministic_parser = false;
bool glr_parser = false;
int report_flag = report_none;
int trace_flag = trace_none;
-int warnings_flag = warnings_conflicts_sr | warnings_conflicts_rr
- | warnings_other;
static struct bison_language const valid_languages[] = {
{ "c", "c-skel.m4", ".c", ".h", true },
*/
static void
flags_argmatch (const char *option,
- const char * const keys[], const int values[],
- int all, int *flags, char *args)
+ const char * const keys[], const int values[],
+ int all, int *flags, char *args)
{
if (args)
{
args = strtok (args, ",");
while (args)
- {
- int no = strncmp (args, "no-", 3) == 0 ? 3 : 0;
- int value = XARGMATCH (option, args + no, keys, values);
- if (value == 0)
- {
- if (no)
- *flags |= all;
- else
- *flags &= ~all;
- }
- else
- {
- if (no)
- *flags &= ~value;
- else
- *flags |= value;
- }
- args = strtok (NULL, ",");
- }
+ {
+ int no = STRPREFIX_LIT ("no-", args) ? 3 : 0;
+ int value = XARGMATCH (option, args + no, keys, values);
+ if (value == 0)
+ {
+ if (no)
+ *flags |= all;
+ else
+ *flags &= ~all;
+ }
+ else
+ {
+ if (no)
+ *flags &= ~value;
+ else
+ *flags |= value;
+ }
+ args = strtok (NULL, ",");
+ }
}
else
*flags |= all;
*
* \param FlagName the flag familly to update.
* \param Args the effective sub arguments to decode.
+ * \param All the "all" value.
*
* \arg FlagName_args the list of keys.
* \arg FlagName_types the list of values.
- * \arg FlagName_all the all value.
* \arg FlagName_flag the flag to update.
*/
-#define FLAGS_ARGMATCH(FlagName, Args) \
+#define FLAGS_ARGMATCH(FlagName, Args, All) \
flags_argmatch ("--" #FlagName, FlagName ## _args, FlagName ## _types, \
- FlagName ## _all, &FlagName ## _flag, Args)
+ All, &FlagName ## _flag, Args)
/*----------------------.
"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",
static const int warnings_types[] =
{
- warnings_none,
- warnings_midrule_values,
- warnings_yacc,
- warnings_conflicts_sr,
- warnings_conflicts_rr,
- warnings_other,
- warnings_all,
- warnings_error
+ Wnone,
+ Wmidrule_values,
+ Wyacc,
+ Wconflicts_sr,
+ Wconflicts_rr,
+ Wdeprecated,
+ Wother,
+ Wall,
+ Werror
};
ARGMATCH_VERIFY (warnings_args, warnings_types);
-
/*-------------------------------------------.
| Display the help message and exit STATUS. |
`-------------------------------------------*/
{
if (status != 0)
fprintf (stderr, _("Try `%s --help' for more information.\n"),
- program_name);
+ program_name);
else
{
/* For ../build-aux/cross-options.pl to work, use the format:
- ^ -S, --long[=ARGS] (whitespace)
- A --long option is required.
- Otherwise, add exceptions to ../build-aux/cross-options.pl. */
+ ^ -S, --long[=ARGS] (whitespace)
+ A --long option is required.
+ Otherwise, add exceptions to ../build-aux/cross-options.pl. */
printf (_("Usage: %s [OPTION]... FILE\n"), program_name);
fputs (_("\
-L, --language=LANGUAGE specify the output programming language\n\
(this is an experimental feature)\n\
-S, --skeleton=FILE specify the skeleton to use\n\
- -t, --debug instrument the parser for debugging\n\
+ -t, --debug instrument the parser for tracing\n\
+ same as `-Dparse.trace'\n\
--locations enable location support\n\
-D, --define=NAME[=VALUE] similar to '%define NAME \"VALUE\"'\n\
-F, --force-define=NAME[=VALUE] override '%define NAME \"VALUE\"'\n\
`yacc' incompatibilities with POSIX Yacc\n\
`conflicts-sr' S/R conflicts (enabled by default)\n\
`conflicts-rr' R/R conflicts (enabled by default)\n\
+ `deprecated' obsolete constructs\n\
`other' all other warnings (enabled by default)\n\
`all' all the warnings\n\
`no-CATEGORY' turn off warnings in CATEGORY\n\
`none' turn off all the warnings\n\
`error' treat warnings as errors\n\
- \n\
"), stdout);
+ putc ('\n', stdout);
fputs (_("\
THINGS is a list of comma separated words that can include:\n\
Note we still output for 'C' so that it gets included in the
man page. */
const char *lc_messages = setlocale (LC_MESSAGES, NULL);
- if (lc_messages && strcmp (lc_messages, "en_"))
+ if (lc_messages && !STREQ (lc_messages, "en_"))
/* TRANSLATORS: Replace LANG_CODE in this URL with your language
code <http://translationproject.org/team/LANG_CODE.html> to
form one of the URLs at http://translationproject.org/team/.
putc ('\n', stdout);
fprintf (stdout,
- _("Copyright (C) %d Free Software Foundation, Inc.\n"),
- PACKAGE_COPYRIGHT_YEAR);
+ _("Copyright (C) %d Free Software Foundation, Inc.\n"),
+ PACKAGE_COPYRIGHT_YEAR);
fputs (_("\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
"),
- stdout);
+ stdout);
}
skeleton = arg;
}
else if (prio == skeleton_prio)
- complain_at (loc, _("multiple skeleton declarations are invalid"));
+ complain_at (loc, complaint,
+ _("multiple skeleton declarations are invalid"));
}
void
else
return;
- complain_at (loc, msg, quotearg_colon (arg));
+ complain_at (loc, complaint, msg, quotearg_colon (arg));
}
/*----------------------.
static struct option const long_options[] =
{
/* Operation modes. */
- { "help", no_argument, 0, 'h' },
- { "version", no_argument, 0, 'V' },
- { "print-localedir", no_argument, 0, PRINT_LOCALEDIR_OPTION },
- { "print-datadir", no_argument, 0, PRINT_DATADIR_OPTION },
+ { "help", no_argument, 0, 'h' },
+ { "version", no_argument, 0, 'V' },
+ { "print-localedir", no_argument, 0, PRINT_LOCALEDIR_OPTION },
+ { "print-datadir", no_argument, 0, PRINT_DATADIR_OPTION },
{ "warnings", optional_argument, 0, 'W' },
/* Parser. */
- { "name-prefix", required_argument, 0, 'p' },
+ { "name-prefix", required_argument, 0, 'p' },
{ "include", required_argument, 0, 'I' },
/* Output. */
- { "file-prefix", required_argument, 0, 'b' },
- { "output", required_argument, 0, 'o' },
- { "output-file", required_argument, 0, 'o' },
- { "graph", optional_argument, 0, 'g' },
+ { "file-prefix", required_argument, 0, 'b' },
+ { "output", required_argument, 0, 'o' },
+ { "output-file", required_argument, 0, 'o' },
+ { "graph", optional_argument, 0, 'g' },
{ "xml", optional_argument, 0, 'x' },
- { "report", required_argument, 0, 'r' },
+ { "report", required_argument, 0, 'r' },
{ "report-file", required_argument, 0, REPORT_FILE_OPTION },
- { "verbose", no_argument, 0, 'v' },
+ { "verbose", no_argument, 0, 'v' },
/* Hidden. */
{ "trace", optional_argument, 0, 'T' },
/* Operation modes. */
{ "fixed-output-files", no_argument, 0, 'y' },
- { "yacc", no_argument, 0, 'y' },
+ { "yacc", no_argument, 0, 'y' },
/* Parser. */
- { "debug", no_argument, 0, 't' },
- { "define", required_argument, 0, 'D' },
+ { "debug", no_argument, 0, 't' },
+ { "define", required_argument, 0, 'D' },
{ "force-define", required_argument, 0, 'F' },
- { "locations", no_argument, 0, LOCATIONS_OPTION },
+ { "locations", no_argument, 0, LOCATIONS_OPTION },
{ "no-lines", no_argument, 0, 'l' },
{ "raw", no_argument, 0, 0 },
{ "skeleton", required_argument, 0, 'S' },
int c;
while ((c = getopt_long (argc, argv, short_options, long_options, NULL))
- != -1)
+ != -1)
switch (c)
{
/* ASCII Sorting for short options (i.e., upper case then
lower case), and then long-only options. */
case 0:
- /* Certain long options cause getopt_long to return 0. */
- break;
+ /* Certain long options cause getopt_long to return 0. */
+ break;
case 'D': /* -DNAME[=VALUE]. */
case 'F': /* -FNAME[=VALUE]. */
{
char* name = optarg;
- char* value = mbschr (optarg, '=');
+ char* value = strchr (optarg, '=');
if (value)
*value++ = 0;
muscle_percent_define_insert (name, command_line_location (),
c == 'D' ? MUSCLE_PERCENT_DEFINE_D
: MUSCLE_PERCENT_DEFINE_F);
}
- break;
+ break;
case 'I':
- include = AS_FILE_NAME (optarg);
- break;
+ include = AS_FILE_NAME (optarg);
+ break;
case 'L':
- language_argmatch (optarg, command_line_prio,
- command_line_location ());
- break;
+ language_argmatch (optarg, command_line_prio,
+ command_line_location ());
+ break;
case 'S':
- skeleton_arg (AS_FILE_NAME (optarg), command_line_prio,
- command_line_location ());
- break;
+ skeleton_arg (AS_FILE_NAME (optarg), command_line_prio,
+ command_line_location ());
+ break;
case 'T':
- FLAGS_ARGMATCH (trace, optarg);
- break;
+ FLAGS_ARGMATCH (trace, optarg, trace_all);
+ break;
case 'V':
- version ();
- exit (EXIT_SUCCESS);
+ version ();
+ exit (EXIT_SUCCESS);
case 'W':
- FLAGS_ARGMATCH (warnings, optarg);
- break;
+ FLAGS_ARGMATCH (warnings, optarg, Wall);
+ break;
case 'b':
- spec_file_prefix = AS_FILE_NAME (optarg);
- break;
+ spec_file_prefix = AS_FILE_NAME (optarg);
+ break;
case 'd':
/* Here, the -d and --defines options are differentiated. */
break;
case 'g':
- graph_flag = true;
- if (optarg)
+ graph_flag = true;
+ if (optarg)
{
free (spec_graph_file);
spec_graph_file = xstrdup (AS_FILE_NAME (optarg));
}
- break;
+ break;
case 'h':
- usage (EXIT_SUCCESS);
+ usage (EXIT_SUCCESS);
case 'k':
- token_table_flag = true;
- break;
+ token_table_flag = true;
+ break;
case 'l':
- no_lines_flag = true;
- break;
+ no_lines_flag = true;
+ break;
case 'o':
- spec_outfile = AS_FILE_NAME (optarg);
- break;
+ spec_outfile = AS_FILE_NAME (optarg);
+ break;
case 'p':
- spec_name_prefix = optarg;
- break;
+ spec_name_prefix = optarg;
+ break;
case 'r':
- FLAGS_ARGMATCH (report, optarg);
- break;
+ FLAGS_ARGMATCH (report, optarg, report_all);
+ break;
case 't':
- debug_flag = true;
- break;
+ muscle_percent_define_insert ("parse.trace",
+ command_line_location (), "",
+ MUSCLE_PERCENT_DEFINE_D);
+ break;
case 'v':
- report_flag |= report_states;
- break;
+ report_flag |= report_states;
+ break;
case 'x':
- xml_flag = true;
- if (optarg)
+ xml_flag = true;
+ if (optarg)
{
free (spec_xml_file);
spec_xml_file = xstrdup (AS_FILE_NAME (optarg));
}
- break;
+ break;
case 'y':
- yacc_flag = true;
- break;
+ yacc_flag = true;
+ break;
case LOCATIONS_OPTION:
- locations_flag = true;
- break;
+ muscle_percent_define_ensure ("locations",
+ command_line_location (), true);
+ break;
case PRINT_LOCALEDIR_OPTION:
- printf ("%s\n", LOCALEDIR);
- exit (EXIT_SUCCESS);
+ printf ("%s\n", LOCALEDIR);
+ exit (EXIT_SUCCESS);
case PRINT_DATADIR_OPTION:
- printf ("%s\n", compute_pkgdatadir ());
- exit (EXIT_SUCCESS);
+ printf ("%s\n", pkgdatadir ());
+ exit (EXIT_SUCCESS);
case REPORT_FILE_OPTION:
free (spec_verbose_file);
- spec_verbose_file = xstrdup (AS_FILE_NAME (optarg));
- break;
+ spec_verbose_file = xstrdup (AS_FILE_NAME (optarg));
+ break;
default:
- usage (EXIT_FAILURE);
+ usage (EXIT_FAILURE);
}
if (argc - optind != 1)
{
muscle_entry const *m1 = x;
muscle_entry const *m2 = y;
- return strcmp (m1->key, m2->key) == 0;
+ return STREQ (m1->key, m2->key);
}
static size_t
obstack_init (&muscle_obstack);
muscle_table = hash_initialize (HT_INITIAL_CAPACITY, NULL, hash_muscle,
- hash_compare_muscles, muscle_entry_free);
+ hash_compare_muscles, muscle_entry_free);
/* Version and input file. */
MUSCLE_INSERT_STRING ("version", VERSION);
{
/* Grow the current value. */
char *new_val;
- obstack_sgrow (&muscle_obstack, entry->value);
+ obstack_printf (&muscle_obstack, "%s%s%s", entry->value, separator, val);
free (entry->storage);
- obstack_sgrow (&muscle_obstack, separator);
- obstack_sgrow (&muscle_obstack, val);
- obstack_1grow (&muscle_obstack, 0);
- new_val = obstack_finish (&muscle_obstack);
+ new_val = obstack_finish0 (&muscle_obstack);
entry->value = entry->storage = xstrdup (new_val);
obstack_free (&muscle_obstack, new_val);
}
obstack_quote (&muscle_obstack,
quotearg_style (c_quoting_style, loc.start.file));
obstack_sgrow (&muscle_obstack, ")[");
- obstack_1grow (&muscle_obstack, 0);
- extension = obstack_finish (&muscle_obstack);
+ extension = obstack_finish0 (&muscle_obstack);
muscle_grow (key, extension, "");
obstack_free (&muscle_obstack, extension);
}
void muscle_pair_list_grow (const char *muscle,
- const char *a1, const char *a2)
+ const char *a1, const char *a2)
{
char *pair;
obstack_sgrow (&muscle_obstack, "[");
obstack_sgrow (&muscle_obstack, ", ");
obstack_quote (&muscle_obstack, a2);
obstack_sgrow (&muscle_obstack, "]");
- obstack_1grow (&muscle_obstack, 0);
- pair = obstack_finish (&muscle_obstack);
+ pair = obstack_finish0 (&muscle_obstack);
muscle_grow (muscle, pair, ",\n");
obstack_free (&muscle_obstack, pair);
}
char *extension;
obstack_sgrow (&muscle_obstack, "[[");
obstack_escape (&muscle_obstack, bound.file);
- obstack_1grow (&muscle_obstack, ':');
- obstack_printf (&muscle_obstack, "%d", bound.line);
- obstack_1grow (&muscle_obstack, '.');
- obstack_printf (&muscle_obstack, "%d", bound.column);
- obstack_sgrow (&muscle_obstack, "]]");
- obstack_1grow (&muscle_obstack, '\0');
- extension = obstack_finish (&muscle_obstack);
+ obstack_printf (&muscle_obstack, ":%d.%d]]", bound.line, bound.column);
+ extension = obstack_finish0 (&muscle_obstack);
muscle_grow (key, extension, "");
obstack_free (&muscle_obstack, extension);
}
static char *
string_decode (char const *key)
{
- char const *value;
+ char const *value = muscle_find_const (key);
char *value_decoded;
char *result;
- value = muscle_find_const (key);
if (!value)
return NULL;
do {
{
char *boundary_str;
aver (*++value == ']');
- obstack_1grow (&muscle_obstack, '\0');
- boundary_str = obstack_finish (&muscle_obstack);
+ boundary_str = obstack_finish0 (&muscle_obstack);
switch (*++value)
{
case ',':
muscle_grow (key, "]]", "");
}
+/** If the \a variable name is obsolete, return the name to use,
+ * otherwise \a variable. */
+static
+char const *
+muscle_percent_variable_update (char const *variable, location variable_loc)
+{
+ typedef struct
+ {
+ const char *obsolete;
+ const char *updated;
+ } conversion_type;
+ const conversion_type conversion[] =
+ {
+ { "api.push_pull", "api.push-pull", },
+ { "lr.keep_unreachable_states", "lr.keep-unreachable-states", },
+ { "namespace", "api.namespace", },
+ };
+ char const *res = variable;
+ int i;
+ for (i = 0; i < ARRAY_CARDINALITY (conversion); ++i)
+ if (STREQ (conversion[i].obsolete, variable))
+ {
+ res = conversion[i].updated;
+ complain_at (variable_loc, Wdeprecated,
+ _("deprecated %%define variable name: %s, use %s"),
+ quote (variable), quote_n (1, res));
+ break;
+ }
+ return res;
+}
+
void
muscle_percent_define_insert (char const *variable, location variable_loc,
char const *value,
muscle_percent_define_how how)
{
- char *variable_tr = NULL;
char const *name;
char const *loc_name;
char const *syncline_name;
char const *how_name;
/* Permit certain names with underscores for backward compatibility. */
- if (0 == strcmp (variable, "api.push_pull")
- || 0 == strcmp (variable, "lr.keep_unreachable_states"))
- {
- variable_tr = strdup (variable);
- tr (variable_tr, '_', '-');
- variable = variable_tr;
- }
+ variable = muscle_percent_variable_update (variable, variable_loc);
name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
if (how == MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE
&& muscle_find_const (name))
{
- muscle_percent_define_how how_old =
- atoi (muscle_find_const (how_name));
+ muscle_percent_define_how how_old = atoi (muscle_find_const (how_name));
+ unsigned i = 0;
if (how_old == MUSCLE_PERCENT_DEFINE_F)
- {
- free (variable_tr);
- return;
- }
- complain_at_indent (variable_loc, &i,
- _("%%define variable %s redefined"), quote (variable));
+ return;
- complain_at (variable_loc, complaint, _("%%define variable %s redefined"),
- quote (variable));
- location loc = muscle_percent_define_get_loc (variable);
- complain_at (loc, complaint, _("previous definition"));
++ complain_at_indent (variable_loc, complaint, &i,
++ _("%%define variable %s redefined"),
++ quote (variable));
+ i += SUB_INDENT;
- complain_at_indent (muscle_percent_define_get_loc (variable), &i,
++ complain_at_indent (muscle_percent_define_get_loc (variable),
++ complaint, &i,
+ _("previous definition"));
}
MUSCLE_INSERT_STRING (name, value);
muscle_user_name_list_grow ("percent_define_user_variables", variable,
variable_loc);
MUSCLE_INSERT_INT (how_name, how);
+}
+
+/* This is used for backward compatibility, e.g., "%define api.pure"
+ supersedes "%pure-parser". */
+void
+muscle_percent_define_ensure (char const *variable, location loc,
+ bool value)
+{
+ char const *val = value ? "" : "false";
+ char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
- free (variable_tr);
+ /* %pure-parser is deprecated in favor of `%define api.pure', so use
+ `%define api.pure' in a backward-compatible manner here. First,
+ don't complain if %pure-parser is specified multiple times. */
+ if (!muscle_find_const (name))
+ 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);
}
char *
muscle_percent_define_get (char const *variable)
{
- char const *name;
- char const *usage_name;
- char *value;
-
- name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
- usage_name = UNIQSTR_CONCAT ("percent_define_bison_variables(",
- variable, ")");
-
- muscle_insert (usage_name, "");
- value = string_decode (name);
+ char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
+ char const *usage_name =
+ UNIQSTR_CONCAT ("percent_define_bison_variables(", variable, ")");
+ char *value = string_decode (name);
if (!value)
value = xstrdup ("");
+
+ muscle_insert (usage_name, "");
return value;
}
location
muscle_percent_define_get_loc (char const *variable)
{
- char const *loc_name;
- loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
+ char const *loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
if (!muscle_find_const (loc_name))
- fatal(_("%s: undefined %%define variable %s"),
- "muscle_percent_define_get_loc", quote (variable));
+ complain (fatal, _("%s: undefined %%define variable %s"),
+ "muscle_percent_define_get_loc", quote (variable));
return location_decode (loc_name);
}
char const *
muscle_percent_define_get_syncline (char const *variable)
{
- char const *syncline_name;
- char const *syncline;
- syncline_name =
+ char const *syncline_name =
UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
- syncline = muscle_find_const (syncline_name);
+ char const *syncline = muscle_find_const (syncline_name);
if (!syncline)
- fatal(_("%s: undefined %%define variable %s"),
- "muscle_percent_define_get_syncline", quote (variable));
+ complain (fatal, _("%s: undefined %%define variable %s"),
+ "muscle_percent_define_get_syncline", quote (variable));
return syncline;
}
bool
muscle_percent_define_ifdef (char const *variable)
{
- char const *name;
- char const *usage_name;
- char const *value;
-
- name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
- usage_name =
+ char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
+ char const *usage_name =
UNIQSTR_CONCAT ("percent_define_bison_variables(", variable, ")");
-
- value = muscle_find_const (name);
+ char const *value = muscle_find_const (name);
if (value)
{
muscle_insert (usage_name, "");
bool
muscle_percent_define_flag_if (char const *variable)
{
- char const *invalid_boolean_name;
- bool result = false;
-
- invalid_boolean_name =
+ char const *invalid_boolean_name =
UNIQSTR_CONCAT ("percent_define_invalid_boolean(", variable, ")");
+ bool result = false;
if (muscle_percent_define_ifdef (variable))
{
char *value = muscle_percent_define_get (variable);
- if (value[0] == '\0' || 0 == strcmp (value, "true"))
+ if (value[0] == '\0' || STREQ (value, "true"))
result = true;
- else if (0 == strcmp (value, "false"))
+ else if (STREQ (value, "false"))
result = false;
else if (!muscle_find_const (invalid_boolean_name))
{
muscle_insert (invalid_boolean_name, "");
- complain_at(muscle_percent_define_get_loc (variable),
- _("invalid value for %%define Boolean variable %s"),
- quote (variable));
+ location loc = muscle_percent_define_get_loc (variable);
+ complain_at (loc, complaint,
+ _("invalid value for %%define Boolean variable %s"),
+ quote (variable));
}
free (value);
}
else
- fatal(_("%s: undefined %%define variable %s"),
- "muscle_percent_define_flag", quote (variable));
+ complain (fatal, _("%s: undefined %%define variable %s"),
+ "muscle_percent_define_flag", quote (variable));
return result;
}
void
muscle_percent_define_default (char const *variable, char const *value)
{
- char const *name;
- char const *loc_name;
- char const *syncline_name;
- name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
- loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
- syncline_name =
+ 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))
{
for (; *values; ++values)
{
char const * const *variablep = values;
- char const *name;
- char *value;
-
- name = UNIQSTR_CONCAT ("percent_define(", *variablep, ")");
-
- value = string_decode (name);
+ char const *name = UNIQSTR_CONCAT ("percent_define(", *variablep, ")");
+ char *value = string_decode (name);
if (value)
{
for (++values; *values; ++values)
{
- if (0 == strcmp (value, *values))
+ if (STREQ (value, *values))
break;
}
if (!*values)
{
+ unsigned i = 0;
location loc = muscle_percent_define_get_loc (*variablep);
- complain_at (loc, complaint,
- _("invalid value for %%define variable %s: %s"),
- quote (*variablep), quote_n (1, value));
- complain_at_indent (loc, &i,
- _("invalid value for %%define variable %s: %s"),
- quote (*variablep), quote_n (1, value));
++ complain_at_indent
++ (loc, complaint, &i,
++ _("invalid value for %%define variable %s: %s"),
++ quote (*variablep), quote_n (1, value));
+ i += SUB_INDENT;
for (values = variablep + 1; *values; ++values)
- complain_at (loc, complaint, _("accepted value: %s"),
- quote (*values));
- complain_at_indent (loc, &i, _("accepted value: %s"),
++ complain_at_indent (loc, complaint, &i, _("accepted value: %s"),
+ quote (*values));
}
else
{
free (value);
}
else
- fatal (_("%s: undefined %%define variable %s"),
- "muscle_percent_define_check_values", quote (*variablep));
+ complain (fatal, _("%s: undefined %%define variable %s"),
+ "muscle_percent_define_check_values", quote (*variablep));
}
}
muscle_percent_code_grow (char const *qualifier, location qualifier_loc,
char const *code, location code_loc)
{
- char const *name;
- name = UNIQSTR_CONCAT ("percent_code(", qualifier, ")");
+ char const *name = UNIQSTR_CONCAT ("percent_code(", qualifier, ")");
muscle_code_grow (name, code, code_loc);
muscle_user_name_list_grow ("percent_code_user_qualifiers", qualifier,
qualifier_loc);
static inline bool
muscle_m4_output (muscle_entry *entry, FILE *out)
{
- fprintf (out, "m4_define([b4_%s],\n", entry->key);
- fprintf (out, "[[%s]])\n\n\n", entry->value);
+ fprintf (out,
+ "m4_define([b4_%s],\n"
+ "[[%s]])\n\n\n", entry->key, entry->value);
return true;
}
grammar_start_symbol_set (symbol *sym, location loc)
{
if (start_flag)
- complain_at (loc, _("multiple %s declarations"), "%start");
+ complain_at (loc, complaint, _("multiple %s declarations"), "%start");
else
{
start_flag = true;
syms->next = xmalloc (sizeof syms->next[0]);
syms->next->name = uniqstr_new (name);
/* After all symbol type declarations have been parsed, packgram invokes
- record_merge_function_type to set the type. */
+ record_merge_function_type to set the type. */
syms->next->type = NULL;
syms->next->next = NULL;
merge_functions = head.next;
aver (merge_function != NULL && merger_find == merger);
if (merge_function->type != NULL && !UNIQSTR_EQ (merge_function->type, type))
{
- complain_at (declaration_loc, complaint,
- _("result type clash on merge function %s: <%s> != <%s>"),
- quote (merge_function->name), type, merge_function->type);
- complain_at (merge_function->type_declaration_location, complaint,
- _("previous declaration"));
+ unsigned indent = 0;
- complain_at_indent (declaration_loc, &indent,
++ complain_at_indent (declaration_loc, complaint, &indent,
+ _("result type clash on merge function %s: "
+ "<%s> != <%s>"),
+ quote (merge_function->name), type,
+ merge_function->type);
+ indent += SUB_INDENT;
- complain_at_indent (merge_function->type_declaration_location, &indent,
++ complain_at_indent (merge_function->type_declaration_location, complaint,
++ &indent,
+ _("previous declaration"));
- }
+ }
merge_function->type = uniqstr_new (type);
merge_function->type_declaration_location = declaration_loc;
}
/*--------------------------------------.
-| Free all merge-function definitions. |
+| Free all merge-function definitions. |
`--------------------------------------*/
void
if (name->id == sym->tag)
{
- warn_at (name->loc,
- _("duplicated symbol name for %s ignored"),
- quote (sym->tag));
+ complain_at (name->loc, Wother,
+ _("duplicated symbol name for %s ignored"),
+ quote (sym->tag));
named_ref_free (name);
}
else
void
grammar_current_rule_begin (symbol *lhs, location loc,
- named_ref *lhs_name)
+ named_ref *lhs_name)
{
symbol_list* p;
++nvars;
}
else if (lhs->class == token_sym)
- complain_at (loc, _("rule given for %s, which is a token"), lhs->tag);
+ complain_at (loc, complaint, _("rule given for %s, which is a token"),
+ lhs->tag);
}
static bool
symbol_should_be_used (symbol_list const *s, bool *midrule_warning)
{
- if (symbol_destructor_get (s->content.sym)->code)
+ if (symbol_code_props_get (s->content.sym, destructor)->code)
return true;
if ((s->midrule && s->midrule->action_props.is_value_used)
|| (s->midrule_parent_rule
symbol *first_rhs = r->next->content.sym;
/* If $$ is being set in default way, report if any type mismatch. */
if (first_rhs)
- {
- char const *lhs_type = r->content.sym->type_name;
- const char *rhs_type =
- first_rhs->type_name ? first_rhs->type_name : "";
- if (!UNIQSTR_EQ (lhs_type, rhs_type))
- warn_at (r->location,
- _("type clash on default action: <%s> != <%s>"),
- lhs_type, rhs_type);
- }
+ {
+ char const *lhs_type = r->content.sym->type_name;
+ const char *rhs_type =
+ first_rhs->type_name ? first_rhs->type_name : "";
+ if (!UNIQSTR_EQ (lhs_type, rhs_type))
+ complain_at (r->location, Wother,
+ _("type clash on default action: <%s> != <%s>"),
+ lhs_type, rhs_type);
+ }
/* Warn if there is no default for $$ but we need one. */
else
- warn_at (r->location,
- _("empty rule for typed nonterminal, and no action"));
+ complain_at (r->location, Wother,
+ _("empty rule for typed nonterminal, and no action"));
}
/* Check that symbol values that should be used are in fact used. */
/* The default action, $$ = $1, `uses' both. */
&& (r->action_props.code || (n != 0 && n != 1)))
{
- void (*warn_at_ptr)(location, char const*, ...) =
- midrule_warning ? midrule_value_at : warn_at;
+ warnings warn_flag = midrule_warning ? Wmidrule_values : Wother;
if (n)
- warn_at_ptr (r->location, _("unused value: $%d"), n);
+ complain_at (r->location, warn_flag, _("unused value: $%d"), n);
else
- warn_at_ptr (r->location, _("unset value: $$"));
+ complain_at (r->location, warn_flag, _("unset value: $$"));
}
}
}
it for char literals and strings, which are always tokens. */
if (r->ruleprec
&& r->ruleprec->tag[0] != '\'' && r->ruleprec->tag[0] != '"'
- && !r->ruleprec->declared && !r->ruleprec->prec)
- warn_at (r->location, _("token for %%prec is not defined: %s"),
- r->ruleprec->tag);
+ && r->ruleprec->status != declared && !r->ruleprec->prec)
+ complain_at (r->location, Wother,
+ _("token for %%prec is not defined: %s"), r->ruleprec->tag);
}
code_props_rule_action_init (&midrule->action_props,
current_rule->action_props.code,
current_rule->action_props.location,
- midrule, 0);
+ midrule, 0,
+ current_rule->action_props.is_predicate);
code_props_none_init (¤t_rule->action_props);
if (previous_rule_end)
token. */
symbol_class_set (precsym, token_sym, loc, false);
if (current_rule->ruleprec)
- complain_at (loc, _("only one %s allowed per rule"), "%prec");
+ complain_at (loc, complaint, _("only one %s allowed per rule"), "%prec");
current_rule->ruleprec = precsym;
}
grammar_current_rule_dprec_set (int dprec, location loc)
{
if (! glr_parser)
- warn_at (loc, _("%s affects only GLR parsers"), "%dprec");
+ complain_at (loc, Wother, _("%s affects only GLR parsers"),
+ "%dprec");
if (dprec <= 0)
- complain_at (loc, _("%s must be followed by positive number"), "%dprec");
+ complain_at (loc, complaint, _("%s must be followed by positive number"),
+ "%dprec");
else if (current_rule->dprec != 0)
- complain_at (loc, _("only one %s allowed per rule"), "%dprec");
+ complain_at (loc, complaint, _("only one %s allowed per rule"), "%dprec");
current_rule->dprec = dprec;
}
grammar_current_rule_merge_set (uniqstr name, location loc)
{
if (! glr_parser)
- warn_at (loc, _("%s affects only GLR parsers"), "%merge");
+ complain_at (loc, Wother, _("%s affects only GLR parsers"),
+ "%merge");
if (current_rule->merger != 0)
- complain_at (loc, _("only one %s allowed per rule"), "%merge");
+ complain_at (loc, complaint, _("only one %s allowed per rule"), "%merge");
current_rule->merger = get_merge_function (name);
current_rule->merger_declaration_location = loc;
}
void
grammar_current_rule_symbol_append (symbol *sym, location loc,
- named_ref *name)
+ named_ref *name)
{
symbol_list *p;
if (current_rule->action_props.code)
p = grammar_symbol_append (sym, loc);
if (name)
assign_named_ref(p, name);
+ if (sym->status == undeclared || sym->status == used)
+ sym->status = needed;
}
/* Attach an ACTION to the current rule. */
void
grammar_current_rule_action_append (const char *action, location loc,
- named_ref *name)
+ named_ref *name, bool is_predicate)
{
if (current_rule->action_props.code)
grammar_midrule_action ();
/* After all symbol declarations have been parsed, packgram invokes
code_props_translate_code. */
code_props_rule_action_init (¤t_rule->action_props, action, loc,
- current_rule, name);
+ current_rule, name, is_predicate);
}
\f
int rule_length = 0;
symbol *ruleprec = p->ruleprec;
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].number = ruleno;
rules[ruleno].lhs = p->content.sym;
rules[ruleno].useful = true;
rules[ruleno].action = p->action_props.code;
rules[ruleno].action_location = p->action_props.location;
+ rules[ruleno].is_predicate = p->action_props.is_predicate;
/* 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
- %destructor and %printer apply. */
+ symbol name so that it's a user-defined symbol so that the default
+ %destructor and %printer apply. */
if (p->midrule_parent_rule
&& (p->action_props.is_value_used
- || symbol_list_n_get (p->midrule_parent_rule,
- p->midrule_parent_rhs_index)
+ || symbol_list_n_get (p->midrule_parent_rule,
+ p->midrule_parent_rhs_index)
->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
- symbols may appear unused, but the parsing algorithm ensures that
- %destructor's are invoked appropriately. */
+ symbols may appear unused, but the parsing algorithm ensures that
+ %destructor's are invoked appropriately. */
if (p != grammar)
- grammar_rule_check (p);
+ grammar_rule_check (p);
for (p = p->next; p && p->content.sym; p = p->next)
- {
- ++rule_length;
+ {
+ ++rule_length;
- /* Don't allow rule_length == INT_MAX, since that might
- cause confusion with strtol if INT_MAX == LONG_MAX. */
- if (rule_length == INT_MAX)
- fatal_at (rules[ruleno].location, _("rule is too long"));
+ /* Don't allow rule_length == INT_MAX, since that might
+ cause confusion with strtol if INT_MAX == LONG_MAX. */
+ if (rule_length == INT_MAX)
+ complain_at (rules[ruleno].location, fatal, _("rule is too long"));
- /* item_number = symbol_number.
- But the former needs to contain more: negative rule numbers. */
- ritem[itemno++] =
+ /* item_number = symbol_number.
+ But the former needs to contain more: negative rule numbers. */
+ ritem[itemno++] =
symbol_number_as_item_number (p->content.sym->number);
- /* A rule gets by default the precedence and associativity
- of its last token. */
- if (p->content.sym->class == token_sym && default_prec)
- rules[ruleno].prec = p->content.sym;
- }
+ /* A rule gets by default the precedence and associativity
+ of its last token. */
+ if (p->content.sym->class == token_sym && default_prec)
+ rules[ruleno].prec = p->content.sym;
+ }
/* If this rule has a %prec,
the specified symbol's precedence replaces the default. */
if (ruleprec)
- {
- rules[ruleno].precsym = ruleprec;
- rules[ruleno].prec = ruleprec;
- }
+ {
+ rules[ruleno].precsym = ruleprec;
+ rules[ruleno].prec = ruleprec;
+ }
/* An item ends by the rule number (negated). */
ritem[itemno++] = rule_number_as_item_number (ruleno);
aver (itemno < ITEM_NUMBER_MAX);
aver (ruleno < RULE_NUMBER_MAX);
if (p)
- p = p->next;
+ p = p->next;
}
aver (itemno == nritems);
default. */
muscle_percent_define_default ("lr.type", "lalr");
lr_type = muscle_percent_define_get ("lr.type");
- if (0 != strcmp (lr_type, "canonical-lr"))
+ if (STRNEQ (lr_type, "canonical-lr"))
muscle_percent_define_default ("lr.default-reductions", "most");
else
muscle_percent_define_default ("lr.default-reductions", "accepting");
/*-------------------------------------------------------------.
| Check the grammar that has just been read, and convert it to |
-| internal form. |
+| internal form. |
`-------------------------------------------------------------*/
static void
{
/* Grammar has been read. Do some checking. */
if (nrules == 0)
- fatal (_("no rules in the input grammar"));
+ complain (fatal, _("no rules in the input grammar"));
/* If the user did not define her ENDTOKEN, do it now. */
if (!endtoken)
`-------------------------------------------------------------------*/
static symbol **symbols_sorted = NULL;
+static symbol **semantic_types_sorted = NULL;
/*------------------------.
| Distinguished symbols. |
symbol *startsymbol = NULL;
location startsymbol_location;
-/*---------------------------------------.
-| Default %destructor's and %printer's. |
-`---------------------------------------*/
-
-static code_props default_tagged_destructor = CODE_PROPS_NONE_INIT;
-static code_props default_tagless_destructor = CODE_PROPS_NONE_INIT;
-static code_props default_tagged_printer = CODE_PROPS_NONE_INIT;
-static code_props default_tagless_printer = CODE_PROPS_NONE_INIT;
/*---------------------------------.
| Create a new symbol, named TAG. |
/* If the tag is not a string (starts with a double quote), check
that it is valid for Yacc. */
- if (tag[0] != '\"' && tag[0] != '\'' && mbschr (tag, '-'))
- yacc_at (loc, _("POSIX Yacc forbids dashes in symbol names: %s"),
- tag);
+ if (tag[0] != '\"' && tag[0] != '\'' && strchr (tag, '-'))
+ complain_at (loc, Wyacc,
+ _("POSIX Yacc forbids dashes in symbol names: %s"), tag);
res->tag = tag;
res->location = loc;
res->type_name = NULL;
- code_props_none_init (&res->destructor);
- code_props_none_init (&res->printer);
+ for (int i = 0; i < CODE_PROPS_SIZE; ++i)
+ code_props_none_init (&res->props[i]);
res->number = NUMBER_UNDEFINED;
res->prec = 0;
res->alias = NULL;
res->class = unknown_sym;
- res->declared = false;
+ res->status = undeclared;
if (nsyms == SYMBOL_NUMBER_MAXIMUM)
- fatal (_("too many symbols in input grammar (limit is %d)"),
- SYMBOL_NUMBER_MAXIMUM);
+ complain (fatal, _("too many symbols in input grammar (limit is %d)"),
+ SYMBOL_NUMBER_MAXIMUM);
nsyms++;
return res;
}
+char const *
+code_props_type_string (code_props_type kind)
+{
+ switch (kind)
+ {
+ case destructor:
+ return "%destructor";
+ case printer:
+ return "%printer";
+ }
+ assert (0);
+}
+
/*----------------------------------------.
| Create a new semantic type, named TAG. |
`----------------------------------------*/
static semantic_type *
-semantic_type_new (uniqstr tag)
+semantic_type_new (uniqstr tag, const location *loc)
{
semantic_type *res = xmalloc (sizeof *res);
uniqstr_assert (tag);
res->tag = tag;
- code_props_none_init (&res->destructor);
- code_props_none_init (&res->printer);
+ if (loc)
+ res->location = *loc;
+ for (int i = 0; i < CODE_PROPS_SIZE; ++i)
+ code_props_none_init (&res->props[i]);
return res;
}
| Print a symbol. |
`-----------------*/
-#define SYMBOL_ATTR_PRINT(Attr) \
- if (s->Attr) \
+#define SYMBOL_ATTR_PRINT(Attr) \
+ if (s->Attr) \
fprintf (f, " %s { %s }", #Attr, s->Attr)
-#define SYMBOL_CODE_PRINT(Attr) \
- if (s->Attr.code) \
- fprintf (f, " %s { %s }", #Attr, s->Attr.code)
+#define SYMBOL_CODE_PRINT(Attr) \
+ if (s->props[Attr].code) \
+ fprintf (f, " %s { %s }", #Attr, s->props[Attr].code)
void
-symbol_print (symbol *s, FILE *f)
+symbol_print (symbol const *s, FILE *f)
{
if (s)
{
#undef SYMBOL_ATTR_PRINT
#undef SYMBOL_CODE_PRINT
+
+/*----------------------------------.
+| Whether S is a valid identifier. |
+`----------------------------------*/
+
+static bool
+is_identifier (uniqstr s)
+{
+ static char const alphanum[26 + 26 + 1 + 10] =
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "_"
+ "0123456789";
+ if (!s || ! memchr (alphanum, *s, sizeof alphanum - 10))
+ return false;
+ for (++s; *s; ++s)
+ if (! memchr (alphanum, *s, sizeof alphanum))
+ return false;
+ return true;
+}
+
+
+/*-----------------------------------------------.
+| Get the identifier associated to this symbol. |
+`-----------------------------------------------*/
+uniqstr
+symbol_id_get (symbol const *sym)
+{
+ aver (sym->user_token_number != USER_NUMBER_HAS_STRING_ALIAS);
+ if (sym->alias)
+ sym = sym->alias;
+ return is_identifier (sym->tag) ? sym->tag : 0;
+}
+
+
/*------------------------------------------------------------------.
| Complain that S's WHAT is redeclared at SECOND, and was first set |
| at FIRST. |
symbol_redeclaration (symbol *s, const char *what, location first,
location second)
{
- complain_at (second, complaint, _("%s redeclaration for %s"), what, s->tag);
- complain_at (first, complaint, _("previous declaration"));
+ unsigned i = 0;
- complain_at_indent (second, &i, _("%s redeclaration for %s"), what, s->tag);
++ complain_at_indent (second, complaint, &i,
++ _("%s redeclaration for %s"), what, s->tag);
+ i += SUB_INDENT;
- complain_at_indent (first, &i, _("previous declaration"));
++ complain_at_indent (first, complaint, &i,
++ _("previous declaration"));
}
static void
semantic_type_redeclaration (semantic_type *s, const char *what, location first,
location second)
{
- complain_at (second, complaint, _("%s redeclaration for <%s>"), what, s->tag);
- complain_at (first, complaint, _("previous declaration"));
+ unsigned i = 0;
- complain_at_indent (second, &i, _("%s redeclaration for <%s>"), what, s->tag);
++ complain_at_indent (second, complaint, &i,
++ _("%s redeclaration for <%s>"), what, s->tag);
+ i += SUB_INDENT;
- complain_at_indent (first, &i, _("previous declaration"));
++ complain_at_indent (first, complaint, &i,
++ _("previous declaration"));
}
if (type_name)
{
if (sym->type_name)
- symbol_redeclaration (sym, "%type", sym->type_location, loc);
+ symbol_redeclaration (sym, "%type", sym->type_location, loc);
uniqstr_assert (type_name);
sym->type_name = type_name;
sym->type_location = loc;
}
}
-/*-----------------------------------------.
-| Set the DESTRUCTOR associated with SYM. |
-`-----------------------------------------*/
+/*--------------------------------------------------------.
+| Set the DESTRUCTOR or PRINTER associated with the SYM. |
+`--------------------------------------------------------*/
void
-symbol_destructor_set (symbol *sym, code_props const *destructor)
+symbol_code_props_set (symbol *sym, code_props_type kind,
+ code_props const *code)
{
- if (sym->destructor.code)
- symbol_redeclaration (sym, "%destructor", sym->destructor.location,
- destructor->location);
- sym->destructor = *destructor;
+ if (sym->props[kind].code)
+ symbol_redeclaration (sym, code_props_type_string (kind),
+ sym->props[kind].location,
+ code->location);
+ sym->props[kind] = *code;
}
-/*------------------------------------------.
-| Set the DESTRUCTOR associated with TYPE. |
-`------------------------------------------*/
+/*-----------------------------------------------------.
+| Set the DESTRUCTOR or PRINTER associated with TYPE. |
+`-----------------------------------------------------*/
void
-semantic_type_destructor_set (semantic_type *type,
- code_props const *destructor)
+semantic_type_code_props_set (semantic_type *type,
+ code_props_type kind,
+ code_props const *code)
{
- if (type->destructor.code)
- semantic_type_redeclaration (type, "%destructor",
- type->destructor.location,
- destructor->location);
- type->destructor = *destructor;
+ if (type->props[kind].code)
+ semantic_type_redeclaration (type, code_props_type_string (kind),
+ type->props[kind].location,
+ code->location);
+ type->props[kind] = *code;
}
-/*---------------------------------------.
-| Get the computed %destructor for SYM. |
-`---------------------------------------*/
+/*---------------------------------------------------.
+| Get the computed %destructor or %printer for SYM. |
+`---------------------------------------------------*/
-code_props const *
-symbol_destructor_get (symbol const *sym)
+code_props *
+symbol_code_props_get (symbol *sym, code_props_type kind)
{
- /* Per-symbol %destructor. */
- if (sym->destructor.code)
- return &sym->destructor;
+ /* Per-symbol code props. */
+ if (sym->props[kind].code)
+ return &sym->props[kind];
- /* Per-type %destructor. */
+ /* Per-type code props. */
if (sym->type_name)
{
- code_props const *destructor =
- &semantic_type_get (sym->type_name)->destructor;
- if (destructor->code)
- return destructor;
+ code_props *code =
+ &semantic_type_get (sym->type_name, NULL)->props[kind];
+ if (code->code)
+ return code;
}
- /* Apply default %destructor's only to user-defined symbols. */
- if (sym->tag[0] == '$' || sym == errtoken)
- return &code_props_none;
-
- if (sym->type_name)
- return &default_tagged_destructor;
- return &default_tagless_destructor;
-}
-
-/*--------------------------------------.
-| Set the PRINTER associated with SYM. |
-`--------------------------------------*/
-
-void
-symbol_printer_set (symbol *sym, code_props const *printer)
-{
- if (sym->printer.code)
- symbol_redeclaration (sym, "%printer",
- sym->printer.location, printer->location);
- sym->printer = *printer;
-}
-
-/*---------------------------------------.
-| Set the PRINTER associated with TYPE. |
-`---------------------------------------*/
-
-void
-semantic_type_printer_set (semantic_type *type, code_props const *printer)
-{
- if (type->printer.code)
- semantic_type_redeclaration (type, "%printer",
- type->printer.location, printer->location);
- type->printer = *printer;
-}
-
-/*------------------------------------.
-| Get the computed %printer for SYM. |
-`------------------------------------*/
-
-code_props const *
-symbol_printer_get (symbol const *sym)
-{
- /* Per-symbol %printer. */
- if (sym->printer.code)
- return &sym->printer;
-
- /* Per-type %printer. */
- if (sym->type_name)
+ /* Apply default code props's only to user-defined symbols. */
+ if (sym->tag[0] != '$' && sym != errtoken)
{
- code_props const *printer = &semantic_type_get (sym->type_name)->printer;
- if (printer->code)
- return printer;
+ code_props *code =
+ &semantic_type_get (sym->type_name ? "*" : "", NULL)->props[kind];
+ if (code->code)
+ return code;
}
-
- /* Apply the default %printer only to user-defined symbols. */
- if (sym->tag[0] == '$' || sym == errtoken)
- return &code_props_none;
-
- if (sym->type_name)
- return &default_tagged_printer;
- return &default_tagless_printer;
+ return &code_props_none;
}
/*-----------------------------------------------------------------.
if (a != undef_assoc)
{
if (sym->prec != 0)
- symbol_redeclaration (sym, assoc_to_string (a), sym->prec_location,
+ symbol_redeclaration (sym, assoc_to_string (a), sym->prec_location,
loc);
sym->prec = prec;
sym->assoc = a;
void
symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring)
{
+ bool warned = false;
if (sym->class != unknown_sym && sym->class != class)
{
- complain_at (loc, _("symbol %s redefined"), sym->tag);
- sym->declared = false;
+ complain_at (loc, complaint, _("symbol %s redefined"), sym->tag);
+ // Don't report both "redefined" and "redeclared".
+ warned = true;
}
if (class == nterm_sym && sym->class != nterm_sym)
if (declaring)
{
- if (sym->declared)
- warn_at (loc, _("symbol %s redeclared"), sym->tag);
- sym->declared = true;
+ if (sym->status == declared && !warned)
+ complain_at (loc, Wother, _("symbol %s redeclared"), sym->tag);
+ sym->status = declared;
}
}
user_token_numberp = &sym->alias->user_token_number;
if (*user_token_numberp != USER_NUMBER_UNDEFINED
&& *user_token_numberp != user_token_number)
- complain_at (loc, _("redefining user token number of %s"), sym->tag);
+ complain_at (loc, complaint, _("redefining user token number of %s"),
+ sym->tag);
*user_token_numberp = user_token_number;
/* User defined $end token? */
{
endtoken = sym;
/* It is always mapped to 0, so it was already counted in
- NTOKENS. */
+ NTOKENS. */
if (endtoken->number != NUMBER_UNDEFINED)
--ntokens;
endtoken->number = 0;
{
if (sym->class == unknown_sym)
{
- complain_at
- (sym->location,
- _("symbol %s is used, but is not defined as a token and has no rules"),
- sym->tag);
+ assert (sym->status != declared);
+ complain_at (sym->location,
+ sym->status == needed ? complaint : Wother,
+ _("symbol %s is used, but is not defined as a token"
+ " and has no rules"),
+ sym->tag);
sym->class = nterm_sym;
sym->number = nvars++;
}
+ for (int i = 0; i < 2; ++i)
+ symbol_code_props_get (sym, i)->is_used = true;
+
+ /* Set the semantic type status associated to the current symbol to
+ 'declared' so that we could check semantic types unnecessary uses. */
+ if (sym->type_name)
+ {
+ semantic_type *sem_type = semantic_type_get (sym->type_name, NULL);
+ if (sem_type)
+ sem_type->status = declared;
+ }
+
+ return true;
+}
+
+static inline bool
+semantic_type_check_defined (semantic_type *sem_type)
+{
+ // <*> and <> do not have to be "declared".
+ if (sem_type->status == declared
+ || !*sem_type->tag
+ || STREQ(sem_type->tag, "*"))
+ {
+ for (int i = 0; i < 2; ++i)
+ if (sem_type->props[i].kind != CODE_PROPS_NONE
+ && ! sem_type->props[i].is_used)
+ complain_at (sem_type->location, Wother,
+ _("useless %s for type <%s>"),
+ code_props_type_string (i), sem_type->tag);
+ }
+ else
+ complain_at (sem_type->location, Wother,
+ _("type <%s> is used, but is not associated to any symbol"),
+ sem_type->tag);
+
return true;
}
return symbol_check_defined (sym);
}
+static bool
+semantic_type_check_defined_processor (void *sem_type,
+ void *null ATTRIBUTE_UNUSED)
+{
+ return semantic_type_check_defined (sem_type);
+}
+
void
symbol_make_alias (symbol *sym, symbol *str, location loc)
{
if (str->alias)
- warn_at (loc, _("symbol %s used more than once as a literal string"),
- str->tag);
+ complain_at (loc, Wother,
+ _("symbol %s used more than once as a literal string"), str->tag);
else if (sym->alias)
- warn_at (loc, _("symbol %s given more than one literal string"),
- sym->tag);
+ complain_at (loc, Wother,
+ _("symbol %s given more than one literal string"), sym->tag);
else
{
str->class = token_sym;
if (str->type_name != sym->type_name)
{
if (str->type_name)
- symbol_type_set (sym, str->type_name, str->type_location);
+ symbol_type_set (sym, str->type_name, str->type_location);
else
- symbol_type_set (str, sym->type_name, sym->type_location);
+ symbol_type_set (str, sym->type_name, sym->type_location);
}
- if (str->destructor.code || sym->destructor.code)
- {
- if (str->destructor.code)
- symbol_destructor_set (sym, &str->destructor);
- else
- symbol_destructor_set (str, &sym->destructor);
- }
-
- if (str->printer.code || sym->printer.code)
- {
- if (str->printer.code)
- symbol_printer_set (sym, &str->printer);
- else
- symbol_printer_set (str, &sym->printer);
- }
+ for (int i = 0; i < CODE_PROPS_SIZE; ++i)
+ if (str->props[i].code)
+ symbol_code_props_set (sym, i, &str->props[i]);
+ else if (sym->props[i].code)
+ symbol_code_props_set (str, i, &sym->props[i]);
if (sym->prec || str->prec)
{
if (str->prec)
- symbol_precedence_set (sym, str->prec, str->assoc,
- str->prec_location);
+ symbol_precedence_set (sym, str->prec, str->assoc,
+ str->prec_location);
else
- symbol_precedence_set (str, sym->prec, sym->assoc,
- sym->prec_location);
+ symbol_precedence_set (str, sym->prec, sym->assoc,
+ sym->prec_location);
}
}
static bool
symbol_check_alias_consistency_processor (void *this,
- void *null ATTRIBUTE_UNUSED)
+ void *null ATTRIBUTE_UNUSED)
{
symbol_check_alias_consistency (this);
return true;
static void
user_token_number_redeclaration (int num, symbol *first, symbol *second)
{
+ unsigned i = 0;
/* User token numbers are not assigned during the parsing, but in a
second step, via a traversal of the symbol table sorted on tag.
first = second;
second = tmp;
}
- complain_at (second->location, complaint,
- _("user token number %d redeclaration for %s"),
- num, second->tag);
- complain_at (first->location, complaint, _("previous declaration for %s"),
- first->tag);
- complain_at_indent (second->location, &i,
++ complain_at_indent (second->location, complaint, &i,
+ _("user token number %d redeclaration for %s"),
+ num, second->tag);
- complain_at_indent (first->location, &i,
++ complain_at_indent (first->location, complaint, &i,
+ _("previous declaration for %s"),
+ first->tag);
}
/*--------------------------------------------------.
{
/* A token which translation has already been set? */
if (token_translations[this->user_token_number] != undeftoken->number)
- user_token_number_redeclaration
+ user_token_number_redeclaration
(this->user_token_number,
symbols[token_translations[this->user_token_number]],
this);
symbols_new (void)
{
symbol_table = hash_initialize (HT_INITIAL_CAPACITY,
- NULL,
- hash_symbol_hasher,
- hash_symbol_comparator,
- free);
+ NULL,
+ hash_symbol_hasher,
+ hash_symbol_comparator,
+ free);
semantic_type_table = hash_initialize (HT_INITIAL_CAPACITY,
- NULL,
- hash_semantic_type_hasher,
- hash_semantic_type_comparator,
- free);
+ NULL,
+ hash_semantic_type_hasher,
+ hash_semantic_type_comparator,
+ free);
}
`-----------------------------------------------------------------------*/
semantic_type *
-semantic_type_from_uniqstr (const uniqstr key)
+semantic_type_from_uniqstr (const uniqstr key, const location *loc)
{
semantic_type probe;
semantic_type *entry;
if (!entry)
{
/* First insertion in the hash. */
- entry = semantic_type_new (key);
+ entry = semantic_type_new (key, loc);
if (!hash_insert (semantic_type_table, entry))
xalloc_die ();
}
`-----------------------------------------------------------------------*/
semantic_type *
-semantic_type_get (const char *key)
+semantic_type_get (const char *key, const location *loc)
{
- return semantic_type_from_uniqstr (uniqstr_new (key));
+ return semantic_type_from_uniqstr (uniqstr_new (key), loc);
}
}
static void
-symbols_do (Hash_processor processor, void *processor_data)
+symbols_do (Hash_processor processor, void *processor_data,
+ struct hash_table *table, symbol **sorted)
{
- size_t count = hash_get_n_entries (symbol_table);
- if (!symbols_sorted)
+ size_t count = hash_get_n_entries (table);
+ if (!sorted)
{
- symbols_sorted = xnmalloc (count, sizeof *symbols_sorted);
- hash_get_entries (symbol_table, (void**)symbols_sorted, count);
- qsort (symbols_sorted, count, sizeof *symbols_sorted,
- symbols_cmp_qsort);
+ sorted = xnmalloc (count, sizeof *sorted);
+ hash_get_entries (table, (void**)sorted, count);
+ qsort (sorted, count, sizeof *sorted, symbols_cmp_qsort);
}
{
size_t i;
for (i = 0; i < count; ++i)
- processor (symbols_sorted[i], processor_data);
+ processor (sorted[i], processor_data);
}
}
void
symbols_check_defined (void)
{
- symbols_do (symbol_check_defined_processor, NULL);
+ symbols_do (symbol_check_defined_processor, NULL,
+ symbol_table, symbols_sorted);
+ symbols_do (semantic_type_check_defined_processor, NULL,
+ semantic_type_table, semantic_types_sorted);
}
/*------------------------------------------------------------------.
{
symbol *this = symbols[i];
if (this->user_token_number != USER_NUMBER_UNDEFINED)
- {
- if (this->user_token_number > max_user_token_number)
- max_user_token_number = this->user_token_number;
- if (this->user_token_number == 256)
- num_256_available_p = false;
- }
+ {
+ if (this->user_token_number > max_user_token_number)
+ max_user_token_number = this->user_token_number;
+ if (this->user_token_number == 256)
+ num_256_available_p = false;
+ }
}
/* If 256 is not used, assign it to error, to follow POSIX. */
{
symbol *this = symbols[i];
if (this->user_token_number == USER_NUMBER_UNDEFINED)
- this->user_token_number = ++max_user_token_number;
+ this->user_token_number = ++max_user_token_number;
if (this->user_token_number > max_user_token_number)
- max_user_token_number = this->user_token_number;
+ max_user_token_number = this->user_token_number;
}
token_translations = xnmalloc (max_user_token_number + 1,
- sizeof *token_translations);
+ sizeof *token_translations);
- /* Initialize all entries for literal tokens to 2, the internal
- token number for $undefined, which represents all invalid inputs.
- */
+ /* Initialize all entries for literal tokens to the internal token
+ number for $undefined, which represents all invalid inputs. */
for (i = 0; i < max_user_token_number + 1; i++)
token_translations[i] = undeftoken->number;
- symbols_do (symbol_translation_processor, NULL);
+ symbols_do (symbol_translation_processor, NULL,
+ symbol_table, symbols_sorted);
}
void
symbols_pack (void)
{
- symbols_do (symbol_check_alias_consistency_processor, NULL);
+ symbols_do (symbol_check_alias_consistency_processor, NULL,
+ symbol_table, symbols_sorted);
symbols = xcalloc (nsyms, sizeof *symbols);
- symbols_do (symbol_pack_processor, NULL);
+ symbols_do (symbol_pack_processor, NULL, symbol_table, symbols_sorted);
/* Aliases leave empty slots in symbols, so remove them. */
{
symbols_token_translations_init ();
if (startsymbol->class == unknown_sym)
- fatal_at (startsymbol_location,
- _("the start symbol %s is undefined"),
- startsymbol->tag);
+ complain_at (startsymbol_location, fatal,
+ _("the start symbol %s is undefined"),
+ startsymbol->tag);
else if (startsymbol->class == token_sym)
- fatal_at (startsymbol_location,
- _("the start symbol %s is a token"),
- startsymbol->tag);
-}
-
-
-/*--------------------------------------------------.
-| Set default tagged/tagless %destructor/%printer. |
-`--------------------------------------------------*/
-
-void
-default_tagged_destructor_set (code_props const *destructor)
-{
- if (default_tagged_destructor.code)
- {
- unsigned i = 0;
- complain_at_indent (destructor->location, &i,
- _("redeclaration for default tagged %%destructor"));
- i += SUB_INDENT;
- complain_at_indent (default_tagged_destructor.location, &i,
- _("previous declaration"));
- }
- default_tagged_destructor = *destructor;
-}
-
-void
-default_tagless_destructor_set (code_props const *destructor)
-{
- if (default_tagless_destructor.code)
- {
- unsigned i = 0;
- complain_at_indent (destructor->location, &i,
- _("redeclaration for default tagless %%destructor"));
- i += SUB_INDENT;
- complain_at_indent (default_tagless_destructor.location, &i,
- _("previous declaration"));
- }
- default_tagless_destructor = *destructor;
-}
-
-void
-default_tagged_printer_set (code_props const *printer)
-{
- if (default_tagged_printer.code)
- {
- unsigned i = 0;
- complain_at_indent (printer->location, &i,
- _("redeclaration for default tagged %%printer"));
- i += SUB_INDENT;
- complain_at_indent (default_tagged_printer.location, &i,
- _("previous declaration"));
- }
- default_tagged_printer = *printer;
-}
-
-void
-default_tagless_printer_set (code_props const *printer)
-{
- if (default_tagless_printer.code)
- {
- unsigned i = 0;
- complain_at_indent (printer->location, &i,
- _("redeclaration for default tagless %%printer"));
- i += SUB_INDENT;
- complain_at_indent (default_tagless_printer.location, &i,
- _("previous declaration"));
- }
- default_tagless_printer = *printer;
+ complain_at (startsymbol_location, fatal,
+ _("the start symbol %s is a token"),
+ startsymbol->tag);
}
# Exercising Bison on conflicts. -*- Autotest -*-
-# Copyright (C) 2002-2005, 2007, 2009-2012 Free Software Foundation,
-# Inc.
+# Copyright (C) 2002-2005, 2007-2012 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
]])
AT_BISON_CHECK([-o input.c input.y], 0, [],
-[[input.y:4.9: warning: rule useless in parser due to conflicts: e: /* empty */
+[[input.y:4.9: warning: rule useless in parser due to conflicts: e: /* empty */ [-Wother]
]])
AT_CLEANUP
-## -------------------------------------- ##
-## %error-verbose and consistent errors. ##
-## -------------------------------------- ##
+## ------------------------------------------- ##
+## parse.error=verbose and consistent errors. ##
+## ------------------------------------------- ##
-AT_SETUP([[%error-verbose and consistent errors]])
+AT_SETUP([[parse.error=verbose and consistent errors]])
m4_pushdef([AT_CONSISTENT_ERRORS_CHECK], [
}]], [[
%code {]AT_SKEL_CC_IF([[
- #include <cassert>
#include <string>]], [[
#include <assert.h>
#include <stdio.h>
]$1[
-%error-verbose
+%define parse.error verbose
%%
;
consistent-reduction: /*empty*/ {
- assert (yychar == ]AT_SKEL_CC_IF([[yyempty_]], [[YYEMPTY]])[);
+ assert (yychar == YYEMPTY);
yylval = 0;
yychar = 'b';
} ;
[AT_USER_ACTION_GRAMMAR],
[AT_USER_ACTION_INPUT],
[['b']], [[none]])
-AT_CONSISTENT_ERRORS_CHECK([[%language "c++"]],
- [AT_USER_ACTION_GRAMMAR],
- [AT_USER_ACTION_INPUT],
- [['b']], [[none]])
-# No Java test because yychar cannot be manipulated by users.
+# No C++ or Java test because yychar cannot be manipulated by users.
AT_CONSISTENT_ERRORS_CHECK([[%define lr.default-reductions consistent]],
[AT_USER_ACTION_GRAMMAR],
# Show canonical LR's failure.
AT_BISON_CHECK([[-Dlr.type=canonical-lr -o input.c input.y]],
[[0]], [[]],
-[[input.y: conflicts: 2 shift/reduce
+[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
]])
AT_COMPILE([[input]])
AT_PARSER_CHECK([[./input]], [[1]], [[]],
# It's corrected by LAC.
AT_BISON_CHECK([[-Dlr.type=canonical-lr -Dparse.lac=full \
-o input.c input.y]], [[0]], [[]],
-[[input.y: conflicts: 2 shift/reduce
+[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
]])
AT_COMPILE([[input]])
AT_PARSER_CHECK([[./input]], [[1]], [[]],
# IELR is sufficient when LAC is used.
AT_BISON_CHECK([[-Dlr.type=ielr -Dparse.lac=full -o input.c input.y]],
[[0]], [[]],
-[[input.y: conflicts: 2 shift/reduce
+[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
]])
AT_COMPILE([[input]])
AT_PARSER_CHECK([[./input]], [[1]], [[]],
]])
AT_BISON_CHECK([-o input.c --report=all input.y], 0, [],
-[input.y: conflicts: 1 shift/reduce
-])
+[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
+]])
# Check the contents of the report.
AT_CHECK([cat input.output], [],
AT_CLEANUP
+## ---------------------- ##
+## %precedence suffices. ##
+## ---------------------- ##
+
+AT_SETUP([%precedence suffices])
+
+AT_DATA([input.y],
+[[%precedence "then"
+%precedence "else"
+%%
+stmt:
+ "if" cond "then" stmt
+| "if" cond "then" stmt "else" stmt
+| "stmt"
+;
+
+cond:
+ "exp"
+;
+]])
+
+AT_BISON_CHECK([-o input.c input.y])
+
+AT_CLEANUP
+
+
+## ------------------------------ ##
+## %precedence does not suffice. ##
+## ------------------------------ ##
+
+AT_SETUP([%precedence does not suffice])
+
+AT_DATA([input.y],
+[[%precedence "then"
+%precedence "else"
+%%
+stmt:
+ "if" cond "then" stmt
+| "if" cond "then" stmt "else" stmt
+| "stmt"
+;
+
+cond:
+ "exp"
+| cond "then" cond
+;
+]])
+
+AT_BISON_CHECK([-o input.c input.y], 0, [],
+[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
+input.y:12.3-18: warning: rule useless in parser due to conflicts: cond: cond "then" cond [-Wother]
+]])
+
+AT_CLEANUP
+
+
## -------------------------------- ##
## Defaulted Conflicted Reduction. ##
## -------------------------------- ##
]])
AT_BISON_CHECK([-o input.c --report=all input.y], 0, [],
-[[input.y: conflicts: 1 reduce/reduce
-input.y:4.6-8: warning: rule useless in parser due to conflicts: id: '0'
+[[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+input.y:4.6-8: warning: rule useless in parser due to conflicts: id: '0' [-Wother]
]])
# Check the contents of the report.
]])
AT_BISON_CHECK([-o input.c input.y], 1, [],
- [[input.y: shift/reduce conflicts: 1 found, 0 expected
-[input.y: conflicts: 1 shift/reduce
-input.y: error: expected 0 shift/reduce conflicts
-])
++[[input.y: error: shift/reduce conflicts: 1 found, 0 expected
+]])
AT_CLEANUP
]])
AT_BISON_CHECK([-o input.c input.y], 1, [],
- [[input.y: shift/reduce conflicts: 1 found, 2 expected
-[input.y: conflicts: 1 shift/reduce
-input.y: error: expected 2 shift/reduce conflicts
-])
++[[input.y: error: shift/reduce conflicts: 1 found, 2 expected
+]])
AT_CLEANUP
]])
AT_BISON_CHECK([-o input.c input.y], 1, [],
- [[input.y: reduce/reduce conflicts: 1 found, 0 expected
-[input.y: conflicts: 1 reduce/reduce
-input.y: error: expected 0 reduce/reduce conflicts
-])
++[[input.y: error: reduce/reduce conflicts: 1 found, 0 expected
+]])
AT_CLEANUP
]])
AT_BISON_CHECK([-o input.c input.y], 0, [],
-[[input.y: conflicts: 4 shift/reduce
+[[input.y: warning: 4 shift/reduce conflicts [-Wconflicts-sr]
]])
AT_CLEANUP
]])
AT_BISON_CHECK([[--report=all input.y]], 0, [],
-[[input.y: conflicts: 1 shift/reduce, 1 reduce/reduce
-input.y:12.5-20: warning: rule useless in parser due to conflicts: resolved_conflict: 'a' unreachable1
-input.y:20.5-20: warning: rule useless in parser due to conflicts: unreachable1: 'a' unreachable2
-input.y:21.4: warning: rule useless in parser due to conflicts: unreachable1: /* empty */
-input.y:25.13: warning: rule useless in parser due to conflicts: unreachable2: /* empty */
-input.y:25.16: warning: rule useless in parser due to conflicts: unreachable2: /* empty */
-input.y:31.5-7: warning: rule useless in parser due to conflicts: reported_conflicts: 'a'
-input.y:32.4: warning: rule useless in parser due to conflicts: reported_conflicts: /* empty */
+[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
+input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+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: unreachable1: 'a' unreachable2 [-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: unreachable2: /* empty */ [-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: reported_conflicts: 'a' [-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.y >> input-keep.y]])
AT_BISON_CHECK([[input-keep.y]], 0, [],
-[[input-keep.y: conflicts: 2 shift/reduce, 2 reduce/reduce
-input-keep.y:22.4: warning: rule useless in parser due to conflicts: unreachable1: /* empty */
-input-keep.y:26.16: warning: rule useless in parser due to conflicts: unreachable2: /* empty */
-input-keep.y:32.5-7: warning: rule useless in parser due to conflicts: reported_conflicts: 'a'
-input-keep.y:33.4: warning: rule useless in parser due to conflicts: reported_conflicts: /* empty */
+[[input-keep.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
+input-keep.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
+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: unreachable2: /* empty */ [-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: reported_conflicts: /* empty */ [-Wother]
]])
AT_CLEANUP
AT_CLEANUP
-## --------------------------------- ##
-## -W versus %expect and %expect-rr ##
-## --------------------------------- ##
+## -------------------- ##
+## %expect-rr non GLR. ##
+## -------------------- ##
+
+AT_SETUP([[%expect-rr non GLR]])
+
+AT_DATA([[1.y]],
+[[%expect-rr 0
+%%
+exp: 'a'
+]])
+
+AT_BISON_CHECK([[1.y]], [[0]], [],
+[[1.y: warning: %expect-rr applies only to GLR parsers [-Wother]
+]])
+
+AT_DATA([[2.y]],
+[[%expect-rr 1
+%%
+exp: 'a' | 'a';
+]])
+
+AT_BISON_CHECK([[2.y]], [[0]], [],
+[[2.y: warning: %expect-rr applies only to GLR parsers [-Wother]
+2.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+2.y:3.12-14: warning: rule useless in parser due to conflicts: exp: 'a' [-Wother]
+]])
+
+AT_CLEANUP
+
+
+## ---------------------------------- ##
+## -W versus %expect and %expect-rr. ##
+## ---------------------------------- ##
AT_SETUP([[-W versus %expect and %expect-rr]])
]])
AT_BISON_CHECK([[sr-rr.y]], [[0]], [[]],
-[[sr-rr.y: conflicts: 1 shift/reduce, 1 reduce/reduce
+[[sr-rr.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
+sr-rr.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
]])
AT_BISON_CHECK([[-Wno-conflicts-sr sr-rr.y]], [[0]], [[]],
-[[sr-rr.y: conflicts: 1 reduce/reduce
+[[sr-rr.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
]])
AT_BISON_CHECK([[-Wno-conflicts-rr sr-rr.y]], [[0]], [[]],
-[[sr-rr.y: conflicts: 1 shift/reduce
+[[sr-rr.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
]])
-[for gram in sr-rr sr rr; do
+[
+# This is piece of code is rather complex for a simple task: try every
+# combinaison of (0 or 1 real SR) x (0 or 1 real RR) x (don't %expect
+# or %expect 0, 1, or 2 SR) x (don't %expect-rr or %expect-rr 0, 1, or 2
+# RR).
+
+# Number and types of genuine conflicts in the grammar.
+for gram in sr-rr sr rr; do
+ # Number of expected s/r conflicts.
for sr_exp_i in '' 0 1 2; do
+ # Number of expected r/r conflicts.
for rr_exp_i in '' 0 1 2; do
test -z "$sr_exp_i" && test -z "$rr_exp_i" && continue
echo "$directives" > $file
cat $gram.y >> $file
- # Count actual conflicts.
- conflicts=
- sr_count=0
- rr_count=0
- if test $gram = sr || test $gram = sr-rr; then
- conflicts="1 shift/reduce"
- sr_count=1
- fi
- if test $gram = rr || test $gram = sr-rr; then
- if test -n "$conflicts"; then
- conflicts="$conflicts, "
- fi
- conflicts="${conflicts}1 reduce/reduce"
- rr_count=1
- fi
+ # Number of found conflicts.
+ case $gram in
+ (sr) sr_count=1; rr_count=0;;
+ (rr) sr_count=0; rr_count=1;;
+ (sr-rr) sr_count=1; rr_count=1;;
+ esac
+
+ # Update number of expected conflicts: if %expect is given then
+ # %expect-rr defaults to 0, and vice-versa. Leave empty if
+ # nothing expected.
+ case $sr_exp_i:$rr_exp_i in
+ ?:) rr_exp_i=0;;
+ :?) sr_exp_i=0;;
+ esac
# Run tests.
if test $sr_count -eq $sr_exp && test $rr_count -eq $rr_exp; then
]AT_BISON_CHECK([[-Wnone $file]])[
]AT_BISON_CHECK([[-Werror $file]])[
else
- echo "$file: conflicts: $conflicts" > experr
- if test $sr_count -ne $sr_exp; then
- if test $sr_exp -ne 1; then s=s; else s= ; fi
- echo "$file: error: expected $sr_exp shift/reduce conflict$s" >> experr
- fi
- if test $rr_count -ne $rr_exp; then
- if test $rr_exp -ne 1; then s=s; else s= ; fi
- echo "$file: error: expected $rr_exp reduce/reduce conflict$s" >> experr
- fi
+ {
+ if test -z "$sr_exp_i" && test "$sr_count" -ne 0; then
+ echo "warning: $sr_count shift/reduce conflicts"
+ elif test "$sr_exp_i" -ne "$sr_count"; then
- echo "shift/reduce conflicts: $sr_count found, $sr_exp_i expected"
++ echo "error: shift/reduce conflicts: $sr_count found, $sr_exp_i expected"
+ fi
+ if test -z "$rr_exp_i" && test "$rr_count" -ne 0; then
+ echo "warning: $rr_count reduce/reduce conflicts"
+ elif test "$rr_exp_i" -ne "$rr_count"; then
- echo "reduce/reduce conflicts: $rr_count found, $rr_exp_i expected"
++ echo "error: reduce/reduce conflicts: $rr_count found, $rr_exp_i expected"
+ fi
+ } | sed -e "s/^/$file: /" > experr
]AT_BISON_CHECK([[-Wnone $file]], [[1]], [[]], [[experr]])[
]AT_BISON_CHECK([[-Werror $file]], [[1]], [[]], [[experr]])[
fi
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr1.c glr-regr1.y]], 0, [],
-[glr-regr1.y: conflicts: 1 shift/reduce
-])
+[[glr-regr1.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
+]])
AT_COMPILE([glr-regr1])
AT_PARSER_CHECK([[echo BPBPB | ./glr-regr1]], 0,
[[E -> 'B'
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr2a.c glr-regr2a.y]], 0, [],
-[glr-regr2a.y: conflicts: 2 shift/reduce
-])
+[[glr-regr2a.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
+]])
AT_COMPILE([glr-regr2a])
AT_PARSER_CHECK([[echo s VARIABLE_1 t v x q | ./glr-regr2a]], 0,
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr3.c glr-regr3.y]], 0, [],
-[glr-regr3.y: conflicts: 1 shift/reduce, 1 reduce/reduce
-])
+[[glr-regr3.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
+glr-regr3.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
AT_COMPILE([glr-regr3])
AT_PARSER_CHECK([[echo p1 t4 o2 p1 p1 t1 o1 t2 p2 o1 t3 p2 p2 | ./glr-regr3]],
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr4.c glr-regr4.y]], 0, [],
-[glr-regr4.y: conflicts: 1 reduce/reduce
-])
+[[glr-regr4.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
AT_COMPILE([glr-regr4])
AT_PARSER_CHECK([[./glr-regr4]], 0,
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr5.c glr-regr5.y]], 0, [],
-[glr-regr5.y: conflicts: 1 reduce/reduce
-])
+[[glr-regr5.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
AT_COMPILE([glr-regr5])
AT_PARSER_CHECK([[./glr-regr5]], 0, [],
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr6.c glr-regr6.y]], 0, [],
-[glr-regr6.y: conflicts: 1 reduce/reduce
-])
+[[glr-regr6.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
AT_COMPILE([glr-regr6])
AT_PARSER_CHECK([[./glr-regr6]], 0,
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr7.c glr-regr7.y]], 0, [],
-[glr-regr7.y: conflicts: 2 reduce/reduce
-])
+[[glr-regr7.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
+]])
AT_COMPILE([glr-regr7])
AT_PARSER_CHECK([[./glr-regr7]], 2, [],
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr8.c glr-regr8.y]], 0, [],
-[glr-regr8.y: conflicts: 1 reduce/reduce
-])
+[[glr-regr8.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
AT_COMPILE([glr-regr8])
AT_PARSER_CHECK([[./glr-regr8]], 0,
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr9.c glr-regr9.y]], 0, [],
-[glr-regr9.y: conflicts: 1 reduce/reduce
-])
+[[glr-regr9.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
AT_COMPILE([glr-regr9])
AT_PARSER_CHECK([[./glr-regr9]], 0, [],
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr10.c glr-regr10.y]], 0, [],
-[glr-regr10.y: conflicts: 1 reduce/reduce
-])
+[[glr-regr10.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
AT_COMPILE([glr-regr10])
AT_PARSER_CHECK([[./glr-regr10]], 0, [], [])
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr11.c glr-regr11.y]], 0, [],
-[glr-regr11.y: conflicts: 1 reduce/reduce
-])
+[[glr-regr11.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
AT_COMPILE([glr-regr11])
AT_PARSER_CHECK([[./glr-regr11]], 0, [], [])
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr12.c glr-regr12.y]], 0, [],
-[glr-regr12.y: conflicts: 1 shift/reduce, 1 reduce/reduce
-])
+[[glr-regr12.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
+glr-regr12.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
AT_COMPILE([glr-regr12])
AT_PARSER_CHECK([[./glr-regr12]], 0, [], [])
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr14.c glr-regr14.y]], 0, [],
-[glr-regr14.y: conflicts: 3 reduce/reduce
-])
+[[glr-regr14.y: warning: 3 reduce/reduce conflicts [-Wconflicts-rr]
+]])
AT_COMPILE([glr-regr14])
AT_PARSER_CHECK([[./glr-regr14]], 0,
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr15.c glr-regr15.y]], 0, [],
-[glr-regr15.y: conflicts: 2 reduce/reduce
-])
+[[glr-regr15.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
+]])
AT_COMPILE([glr-regr15])
AT_PARSER_CHECK([[./glr-regr15]], 0, [],
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr16.c glr-regr16.y]], 0, [],
-[glr-regr16.y: conflicts: 1 reduce/reduce
-])
+[[glr-regr16.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
AT_COMPILE([glr-regr16])
AT_PARSER_CHECK([[./glr-regr16]], 0, [],
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr17.c glr-regr17.y]], 0, [],
-[glr-regr17.y: conflicts: 3 reduce/reduce
-])
+[[glr-regr17.y: warning: 3 reduce/reduce conflicts [-Wconflicts-rr]
+]])
AT_COMPILE([glr-regr17])
AT_PARSER_CHECK([[./glr-regr17]], 0, [],
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr18.c glr-regr18.y]], 1, [],
- [glr-regr18.y:26.18-24: result type clash on merge function 'merge': <type2> != <type1>
- glr-regr18.y:25.18-24: previous declaration
- glr-regr18.y:27.13-19: result type clash on merge function 'merge': <type3> != <type2>
- glr-regr18.y:26.18-24: previous declaration
- ])
-[glr-regr18.y:26.18-24: error: result type clash on merge function 'merge': <type2> != <type1>
++[[glr-regr18.y:26.18-24: error: result type clash on merge function 'merge': <type2> != <type1>
+ glr-regr18.y:25.18-24: previous declaration
+ glr-regr18.y:27.13-19: error: result type clash on merge function 'merge': <type3> != <type2>
+ glr-regr18.y:26.18-24: previous declaration
-])
++]])
AT_CLEANUP
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o input.c input.y]], 0, [],
-[input.y: conflicts: 1 reduce/reduce
-])
+[[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
AT_COMPILE([input])
AT_PARSER_CHECK([[./input]], 1, [],
]])
AT_BISON_CHECK([input.y], [1], [],
- [[input.y:2.13-14: integer out of range: '$1'
- input.y:3.13-14: integer out of range: '@1'
+ [[input.y:2.13-14: error: integer out of range: '$1'
+ input.y:3.13-14: error: integer out of range: '@1'
]])
AT_CLEANUP
]])
AT_BISON_CHECK([input.y], [1], [],
- [[input.y:5.12-13: $$ for the midrule at $2 of 'exp' has no declared type
- input.y:5.24-25: $2 of 'exp' has no declared type
+ [[input.y:5.12-13: error: $$ for the midrule at $2 of 'exp' has no declared type
+ input.y:5.24-25: error: $2 of 'exp' has no declared type
-input.y:5.6-32: warning: type clash on default action: <bar> != <>
-input.y:6.6-8: warning: type clash on default action: <bar> != <>
-input.y:7.5: warning: empty rule for typed nonterminal, and no action
+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:7.5: warning: empty rule for typed nonterminal, and no action [-Wother]
]])
AT_CLEANUP
# --------------------------------
# Generate the token, type, and destructor
# declarations for the unused values tests.
-
m4_define([_AT_UNUSED_VALUES_DECLARATIONS],
[[[%token <integer> INT;
%type <integer> a b c d e f g h i j k l;
# AT_CHECK_UNUSED_VALUES(DECLARATIONS_AFTER, CHECK_MIDRULE_VALUES)
-# ------------------------------------------------------------------
-# Generate a grammar to test unused values,
-# compile it, run it. If DECLARATIONS_AFTER
-# is set, then the token, type, and destructor
-# declarations are generated after the rules
-# rather than before. If CHECK_MIDRULE_VALUES
-# is set, then --warnings=midrule-values is
-# set.
-
+# ----------------------------------------------------------------
+# Generate a grammar to test unused values, compile it, run it. If
+# DECLARATIONS_AFTER is set, then the token, type, and destructor
+# declarations are generated after the rules rather than before. If
+# CHECK_MIDRULE_VALUES is set, then --warnings=midrule-values is set.
m4_define([AT_CHECK_UNUSED_VALUES],
[AT_DATA([input.y],
m4_ifval($1, [
)
AT_BISON_CHECK(m4_ifval($2, [ --warnings=midrule-values ])[ input.y], [0], [],
-[[input.y:11.10-32: warning: unset value: $]$[
-input.y:11.10-32: warning: unused value: $]1[
-input.y:11.10-32: warning: unused value: $]3[
-input.y:11.10-32: warning: unused value: $]5[
-input.y:12.9: warning: empty rule for typed nonterminal, and no action
-]]m4_ifval($2, [[[input.y:13.14-20: warning: unset value: $$
-input.y:13.26-41: warning: unset value: $$
-]]])[[input.y:13.10-62: warning: unset value: $]$[
-input.y:13.10-62: warning: unused value: $]3[
-input.y:13.10-62: warning: unused value: $]5[
-]]m4_ifval($2, [[[input.y:14.14-16: warning: unset value: $$
-]]])[[input.y:14.10-49: warning: unset value: $]$[
-input.y:14.10-49: warning: unused value: $]3[
-input.y:14.10-49: warning: unused value: $]5[
-input.y:15.10-37: warning: unset value: $]$[
-input.y:15.10-37: warning: unused value: $]3[
-input.y:15.10-37: warning: unused value: $]5[
-input.y:17.10-58: warning: unset value: $]$[
-input.y:17.10-58: warning: unused value: $]1[
-]]m4_ifval($2, [[[input.y:17.10-58: warning: unused value: $]2[
-]]])[[input.y:17.10-58: warning: unused value: $]3[
-]]m4_ifval($2, [[[input.y:17.10-58: warning: unused value: $]4[
-]]])[[input.y:17.10-58: warning: unused value: $]5[
-input.y:18.10-72: warning: unset value: $]$[
-input.y:18.10-72: warning: unused value: $]1[
-input.y:18.10-72: warning: unused value: $]3[
-]]m4_ifval($2, [[[input.y:18.10-72: warning: unused value: $]4[
-]]])[[input.y:18.10-72: warning: unused value: $]5[
-]]m4_ifval($2, [[[input.y:20.10-55: warning: unused value: $]3[
-]]])[[input.y:21.10-68: warning: unset value: $]$[
-input.y:21.10-68: warning: unused value: $]1[
-input.y:21.10-68: warning: unused value: $]2[
-]]m4_ifval($2, [[[input.y:21.10-68: warning: unused value: $]4[
+[[input.y:11.10-32: warning: unset value: $]$[ [-Wother]
+input.y:11.10-32: warning: unused value: $]1[ [-Wother]
+input.y:11.10-32: warning: unused value: $]3[ [-Wother]
+input.y:11.10-32: warning: unused value: $]5[ [-Wother]
+input.y:12.9: warning: empty rule for typed nonterminal, and no action [-Wother]
+]]m4_ifval($2, [[[input.y:13.14-20: warning: unset value: $$ [-Wmidrule-values]
+input.y:13.26-41: warning: unset value: $$ [-Wmidrule-values]
+]]])[[input.y:13.10-62: warning: unset value: $]$[ [-Wother]
+input.y:13.10-62: warning: unused value: $]3[ [-Wother]
+input.y:13.10-62: warning: unused value: $]5[ [-Wother]
+]]m4_ifval($2, [[[input.y:14.14-16: warning: unset value: $$ [-Wmidrule-values]
+]]])[[input.y:14.10-49: warning: unset value: $]$[ [-Wother]
+input.y:14.10-49: warning: unused value: $]3[ [-Wother]
+input.y:14.10-49: warning: unused value: $]5[ [-Wother]
+input.y:15.10-37: warning: unset value: $]$[ [-Wother]
+input.y:15.10-37: warning: unused value: $]3[ [-Wother]
+input.y:15.10-37: warning: unused value: $]5[ [-Wother]
+input.y:17.10-58: warning: unset value: $]$[ [-Wother]
+input.y:17.10-58: warning: unused value: $]1[ [-Wother]
+]]m4_ifval($2, [[[input.y:17.10-58: warning: unused value: $]2[ [-Wmidrule-values]
+]]])[[input.y:17.10-58: warning: unused value: $]3[ [-Wother]
+]]m4_ifval($2, [[[input.y:17.10-58: warning: unused value: $]4[ [-Wmidrule-values]
+]]])[[input.y:17.10-58: warning: unused value: $]5[ [-Wother]
+input.y:18.10-72: warning: unset value: $]$[ [-Wother]
+input.y:18.10-72: warning: unused value: $]1[ [-Wother]
+input.y:18.10-72: warning: unused value: $]3[ [-Wother]
+]]m4_ifval($2, [[[input.y:18.10-72: warning: unused value: $]4[ [-Wmidrule-values]
+]]])[[input.y:18.10-72: warning: unused value: $]5[ [-Wother]
+]]m4_ifval($2, [[[input.y:20.10-55: warning: unused value: $]3[ [-Wmidrule-values]
+]]])[[input.y:21.10-68: warning: unset value: $]$[ [-Wother]
+input.y:21.10-68: warning: unused value: $]1[ [-Wother]
+input.y:21.10-68: warning: unused value: $]2[ [-Wother]
+]]m4_ifval($2, [[[input.y:21.10-68: warning: unused value: $]4[ [-Wmidrule-values]
]]]))])
]])
AT_BISON_CHECK([input.y], [1], [],
- [[input.y:1.13-29: %destructor redeclaration for <*>
- input.y:1.13-29: previous declaration
- input.y:2.10-24: %printer redeclaration for <*>
- input.y:2.10-24: previous declaration
- input.y:4.13-29: %destructor redeclaration for <*>
- input.y:1.13-29: previous declaration
- input.y:5.10-24: %printer redeclaration for <*>
- input.y:2.10-24: previous declaration
- input.y:7.13-29: %destructor redeclaration for <>
- input.y:7.13-29: previous declaration
- input.y:8.10-24: %printer redeclaration for <>
- input.y:8.10-24: previous declaration
- input.y:10.13-29: %destructor redeclaration for <>
- input.y:7.13-29: previous declaration
- input.y:11.10-24: %printer redeclaration for <>
- input.y:8.10-24: previous declaration
- input.y:17.13-29: %destructor redeclaration for <*>
- input.y:4.13-29: previous declaration
- input.y:18.10-24: %printer redeclaration for <*>
- input.y:5.10-24: previous declaration
- input.y:20.13-29: %destructor redeclaration for <>
- input.y:10.13-29: previous declaration
- input.y:21.10-24: %printer redeclaration for <>
- input.y:11.10-24: previous declaration
-[[input.y:1.13-29: error: redeclaration for default tagged %destructor
++[[input.y:1.13-29: error: %destructor redeclaration for <*>
+ input.y:1.13-29: previous declaration
-input.y:2.10-24: error: redeclaration for default tagged %printer
++input.y:2.10-24: error: %printer redeclaration for <*>
+ input.y:2.10-24: previous declaration
-input.y:4.13-29: error: redeclaration for default tagged %destructor
++input.y:4.13-29: error: %destructor redeclaration for <*>
+ input.y:1.13-29: previous declaration
-input.y:5.10-24: error: redeclaration for default tagged %printer
++input.y:5.10-24: error: %printer redeclaration for <*>
+ input.y:2.10-24: previous declaration
-input.y:7.13-29: error: redeclaration for default tagless %destructor
++input.y:7.13-29: error: %destructor redeclaration for <>
+ input.y:7.13-29: previous declaration
-input.y:8.10-24: error: redeclaration for default tagless %printer
++input.y:8.10-24: error: %printer redeclaration for <>
+ input.y:8.10-24: previous declaration
-input.y:10.13-29: error: redeclaration for default tagless %destructor
++input.y:10.13-29: error: %destructor redeclaration for <>
+ input.y:7.13-29: previous declaration
-input.y:11.10-24: error: redeclaration for default tagless %printer
++input.y:11.10-24: error: %printer redeclaration for <>
+ input.y:8.10-24: previous declaration
-input.y:17.13-29: error: redeclaration for default tagged %destructor
++input.y:17.13-29: error: %destructor redeclaration for <*>
+ input.y:4.13-29: previous declaration
-input.y:18.10-24: error: redeclaration for default tagged %printer
++input.y:18.10-24: error: %printer redeclaration for <*>
+ input.y:5.10-24: previous declaration
-input.y:20.13-29: error: redeclaration for default tagless %destructor
++input.y:20.13-29: error: %destructor redeclaration for <>
+ input.y:10.13-29: previous declaration
-input.y:21.10-24: error: redeclaration for default tagless %printer
++input.y:21.10-24: error: %printer redeclaration for <>
+ input.y:11.10-24: previous declaration
]])
AT_CLEANUP
]])
AT_BISON_CHECK([input.y], [1], [],
- [[input.y:4.13-29: %destructor redeclaration for <field1>
- input.y:1.13-29: previous declaration
- input.y:4.13-29: %destructor redeclaration for <field1>
- input.y:4.13-29: previous declaration
- input.y:5.10-24: %printer redeclaration for <field2>
- input.y:2.10-24: previous declaration
- input.y:5.10-24: %printer redeclaration for <field2>
- input.y:5.10-24: previous declaration
- input.y:11.13-29: %destructor redeclaration for <field1>
- input.y:4.13-29: previous declaration
- input.y:11.13-29: %destructor redeclaration for <field2>
- input.y:1.13-29: previous declaration
- input.y:12.10-24: %printer redeclaration for <field1>
- input.y:2.10-24: previous declaration
- input.y:12.10-24: %printer redeclaration for <field2>
- input.y:5.10-24: previous declaration
+ [[input.y:4.13-29: error: %destructor redeclaration for <field1>
+ input.y:1.13-29: previous declaration
+ input.y:4.13-29: error: %destructor redeclaration for <field1>
+ input.y:4.13-29: previous declaration
+ input.y:5.10-24: error: %printer redeclaration for <field2>
+ input.y:2.10-24: previous declaration
+ input.y:5.10-24: error: %printer redeclaration for <field2>
+ input.y:5.10-24: previous declaration
+ input.y:11.13-29: error: %destructor redeclaration for <field1>
+ input.y:4.13-29: previous declaration
+ input.y:11.13-29: error: %destructor redeclaration for <field2>
+ input.y:1.13-29: previous declaration
+ input.y:12.10-24: error: %printer redeclaration for <field1>
+ input.y:2.10-24: previous declaration
+ input.y:12.10-24: error: %printer redeclaration for <field2>
+ input.y:5.10-24: previous declaration
]])
AT_CLEANUP
- [[input.y:2.16-18: symbol bar is used, but is not defined as a token and has no rules
+## ------------------- ##
+## Undefined symbols. ##
+## ------------------- ##
+
+AT_SETUP([Undefined symbols])
+
+AT_DATA([[input.y]],
+[[%printer {} foo baz
+%destructor {} bar
+%type <foo> qux
+%%
+exp: bar;
+]])
+
+AT_BISON_CHECK([input.y], [1], [],
++[[input.y:2.16-18: error: symbol bar is used, but is not defined as a token and has no rules
+input.y:1.17-19: warning: symbol baz is used, but is not defined as a token and has no rules [-Wother]
+input.y:1.13-15: warning: symbol foo is used, but is not defined as a token and has no rules [-Wother]
+input.y:3.13-15: warning: symbol qux is used, but is not defined as a token and has no rules [-Wother]
+]])
+
+AT_CLEANUP
+
+
+## ----------------------------------------------------- ##
+## Unassociated types used for a printer or destructor. ##
+## ----------------------------------------------------- ##
+
+AT_SETUP([Unassociated types used for a printer or destructor])
+
+AT_DATA([[input.y]],
+[[%token <type1> tag1
+%type <type2> tag2
+
+%printer { } <type1> <type3>
+%destructor { } <type2> <type4>
+
+%%
+
+exp: tag1 { $1; }
+ | tag2 { $1; }
+
+tag2: "a" { $$; }
+]])
+
+AT_BISON_CHECK([input.y], [0], [],
+[[input.y:4.22-28: warning: type <type3> is used, but is not associated to any symbol [-Wother]
+input.y:5.25-31: warning: type <type4> is used, but is not associated to any symbol [-Wother]
+]])
+
+AT_CLEANUP
+
+
+## --------------------------------- ##
+## Useless printers or destructors. ##
+## --------------------------------- ##
+
+AT_SETUP([Useless printers or destructors])
+
+# AT_TEST([INPUT], [STDERR])
+# --------------------------
+m4_pushdef([AT_TEST],
+[AT_DATA([[input.y]],
+[$1
+])
+AT_BISON_CHECK([input.y], [0], [], [$2
+])])
+
+AT_TEST([[%token <type1> token1
+%token <type2> token2
+%token <type3> token3
+%token <type4> token4
+%token <type5> token51 token52
+%token <type6> token61 token62
+%token <type7> token7
+
+%printer {} token1
+%destructor {} token2
+%printer {} token51
+%destructor {} token61
+
+%printer {} token7
+
+%printer {} <type1>
+%destructor {} <type2>
+%printer {} <type3>
+%destructor {} <type4>
+
+%printer {} <type5>
+%destructor {} <type6>
+
+%destructor {} <type7>
+
+%%
+exp: "a";]],
+[[input.y:16.13-19: warning: useless %printer for type <type1> [-Wother]
+input.y:17.16-22: warning: useless %destructor for type <type2> [-Wother]]])
+
+# If everybody is typed, <> is useless.
+AT_TEST([[%type <type> exp
+%token <type> a
+%printer {} <> <*>
+%%
+exp: a;]],
+[[input.y:3.13-14: warning: useless %printer for type <> [-Wother]]])
+
+# If nobody is typed, <*> is useless.
+AT_TEST([[%token a
+%printer {} <> <*>
+%%
+exp: a;]],
+[[input.y:2.16-18: warning: useless %printer for type <*> [-Wother]]])
+
+m4_popdef([AT_TEST])
+
+AT_CLEANUP
+
## ---------------------------------------- ##
## Unused values with default %destructor. ##
]])
AT_BISON_CHECK([input.y], [0], [],
-[[input.y:6.8-45: warning: unset value: $$
-input.y:6.8-45: warning: unused value: $2
-input.y:7.6-8: warning: unset value: $$
+[[input.y:6.8-45: warning: unset value: $$ [-Wother]
+input.y:6.8-45: warning: unused value: $2 [-Wother]
+input.y:7.6-8: warning: unset value: $$ [-Wother]
]])
AT_DATA([[input.y]],
]])
AT_BISON_CHECK([input.y], [0], [],
-[[input.y:6.8-45: warning: unused value: $4
-input.y:8.9-11: warning: unset value: $$
+[[input.y:6.8-45: warning: unused value: $4 [-Wother]
+input.y:8.9-11: warning: unset value: $$ [-Wother]
]])
AT_CLEANUP
]])
AT_BISON_CHECK([input.y], [0], [],
-[[input.y:6.8-22: warning: unset value: $$
-input.y:6.8-22: warning: unused value: $2
-input.y:7.6-8: warning: unset value: $$
+[[input.y:6.8-22: warning: unset value: $$ [-Wother]
+input.y:6.8-22: warning: unused value: $2 [-Wother]
+input.y:7.6-8: warning: unset value: $$ [-Wother]
]])
AT_CLEANUP
]])
AT_BISON_CHECK([input.y], [1], [],
- [[input.y:8.7-11: %type redeclaration for foo
- input.y:3.7-11: previous declaration
- input.y:10.13-17: %destructor redeclaration for foo
- input.y:5.13-17: previous declaration
- input.y:9.10-14: %printer redeclaration for foo
- input.y:4.10-14: previous declaration
- input.y:11.1-5: %left redeclaration for foo
- input.y:6.1-5: previous declaration
+ [[input.y:8.7-11: error: %type redeclaration for foo
+ input.y:3.7-11: previous declaration
+ input.y:10.13-17: error: %destructor redeclaration for foo
+ input.y:5.13-17: previous declaration
+ input.y:9.10-14: error: %printer redeclaration for foo
+ input.y:4.10-14: previous declaration
+ input.y:11.1-5: error: %left redeclaration for foo
+ input.y:6.1-5: previous declaration
]])
AT_CLEANUP
AT_BISON_OPTION_PUSHDEFS
AT_DATA([input.y], [])
AT_BISON_CHECK([input.y], [1], [],
- [[input.y:1.1: syntax error, unexpected end of file
+ [[input.y:1.1: error: syntax error, unexpected end of file
]])
[{}
])
AT_BISON_CHECK([input.y], [1], [],
- [[input.y:1.1-2: syntax error, unexpected {...}
+ [[input.y:1.1-2: error: syntax error, unexpected {...}
]])
}
]])
-# Pacify Emacs' font-lock-mode: "
+# Pacify Emacs'font-lock-mode: "
AT_DATA([main.c],
[[typedef int value;
AT_SETUP([String aliases for character tokens])
-# Bison once thought a character token and its alias were different symbols
-# with the same user token number.
+# Bison once thought a character token and its alias were different
+# symbols with the same user token number.
AT_DATA_GRAMMAR([input.y],
[[%token 'a' "a"
# POSIX Yacc accept periods, but not dashes.
AT_BISON_CHECK([--yacc input.y], [1], [],
-[[input.y:9.8-16: POSIX Yacc forbids dashes in symbol names: WITH-DASH
-input.y:18.8-16: POSIX Yacc forbids dashes in symbol names: with-dash
+[[input.y:9.8-16: POSIX Yacc forbids dashes in symbol names: WITH-DASH [-Wyacc]
+input.y:18.8-16: POSIX Yacc forbids dashes in symbol names: with-dash [-Wyacc]
]])
# So warn about them.
AT_BISON_CHECK([-Wyacc input.y], [], [],
-[[input.y:9.8-16: warning: POSIX Yacc forbids dashes in symbol names: WITH-DASH
-input.y:18.8-16: warning: POSIX Yacc forbids dashes in symbol names: with-dash
+[[input.y:9.8-16: warning: POSIX Yacc forbids dashes in symbol names: WITH-DASH [-Wyacc]
+input.y:18.8-16: warning: POSIX Yacc forbids dashes in symbol names: with-dash [-Wyacc]
]])
# Dashes are fine for GNU Bison.
start: .GOOD GOOD
]])
AT_BISON_CHECK([-o input.c input.y], [1], [],
- [[input.y:10.10: invalid character: '-'
- input.y:11.10-16: invalid identifier: '1NV4L1D'
- input.y:12.10: invalid character: '-'
+ [[input.y:10.10: error: invalid character: '-'
+ input.y:11.10-16: error: invalid identifier: '1NV4L1D'
+ input.y:12.10: error: invalid character: '-'
]])
AT_CLEANUP
]])
AT_BISON_CHECK([redecl.y], [1], [],
- [[redecl.y:10.10-22: user token number 11259375 redeclaration for HEXADECIMAL_1
- redecl.y:9.8-16: previous declaration for DECIMAL_1
- redecl.y:12.10-18: user token number 16702650 redeclaration for DECIMAL_2
+ [[redecl.y:10.10-22: error: user token number 11259375 redeclaration for HEXADECIMAL_1
+ redecl.y:9.8-16: previous declaration for DECIMAL_1
+ redecl.y:12.10-18: error: user token number 16702650 redeclaration for DECIMAL_2
redecl.y:11.10-22: previous declaration for HEXADECIMAL_2
]])
]])
AT_BISON_CHECK([too-large.y], [1], [],
- [[too-large.y:9.22-42: integer out of range: '999999999999999999999'
- too-large.y:10.24-44: integer out of range: '0xFFFFFFFFFFFFFFFFFFF'
+ [[too-large.y:9.22-42: error: integer out of range: '999999999999999999999'
+ too-large.y:10.24-44: error: integer out of range: '0xFFFFFFFFFFFFFFFFFFF'
]])
AT_CLEANUP
AT_SETUP([Unclosed constructs])
-# Bison's scan-gram.l once forgot to STRING_FINISH some unclosed constructs, so
-# they were prepended to whatever it STRING_GROW'ed next. It also threw them
-# away rather than returning them to the parser. The effect was confusing
-# subsequent error messages.
+# Bison's scan-gram.l once forgot to STRING_FINISH some unclosed
+# constructs, so they were prepended to whatever it STRING_GROW'ed
+# next. It also threw them away rather than returning them to the
+# parser. The effect was confusing subsequent error messages.
AT_DATA([input.y],
[[%token A "a
]])
AT_BISON_CHECK([-o input.c input.y], 1, [],
- [[input.y:1.10-2.0: missing '"' at end of line
- input.y:4.10-5.0: missing "'" at end of line
- input.y:14.11-15.0: missing "'" at end of line
- input.y:16.11-17.0: missing '"' at end of line
- input.y:19.13-20.0: missing '}' at end of file
- input.y:20.1: syntax error, unexpected end of file
+ [[input.y:1.10-2.0: error: missing '"' at end of line
+ input.y:4.10-5.0: error: missing "'" at end of line
+ input.y:14.11-15.0: error: missing "'" at end of line
+ input.y:16.11-17.0: error: missing '"' at end of line
+ input.y:19.13-20.0: error: missing '}' at end of file
+ input.y:20.1: error: syntax error, unexpected end of file
]])
AT_CLEANUP
AT_SETUP([%start after first rule])
-# Bison once complained that a %start after the first rule was a redeclaration
-# of the start symbol.
+# Bison once complained that a %start after the first rule was a
+# redeclaration of the start symbol.
AT_DATA([input.y],
[[%%
]])
AT_BISON_CHECK([input.y], [1], [],
- [[input.y:3.1-4: rule given for PREC, which is a token
+ [[input.y:3.1-4: error: rule given for PREC, which is a token
]])
AT_CLEANUP
]])
AT_BISON_CHECK([[input.y]], [[0]], [],
-[[input.y:2.8-17: warning: token for %prec is not defined: PREC
+[[input.y:2.8-17: warning: token for %prec is not defined: PREC [-Wother]
]])
AT_CLEANUP
start: ;
]])
AT_BISON_CHECK([[input-c.y]], [[1]], [],
- [[input-c.y:1.7: %code qualifier 'q' is not used
- input-c.y:2.7-9: %code qualifier 'bad' is not used
- input-c.y:3.7-9: %code qualifier 'bad' is not used
- input-c.y:4.7-12: %code qualifier 'format' is not used
+ [[input-c.y:1.7: error: %code qualifier 'q' is not used
+ input-c.y:2.7-9: error: %code qualifier 'bad' is not used
+ input-c.y:3.7-9: error: %code qualifier 'bad' is not used
+ input-c.y:4.7-12: error: %code qualifier 'format' is not used
]])
AT_DATA([input-c-glr.y],
start: ;
]])
AT_BISON_CHECK([[input-c-glr.y]], [[1]], [],
- [[input-c-glr.y:1.7: %code qualifier 'q' is not used
- input-c-glr.y:2.7-9: %code qualifier 'bad' is not used
- input-c-glr.y:3.8-10: %code qualifier 'bad' is not used
+ [[input-c-glr.y:1.7: error: %code qualifier 'q' is not used
+ input-c-glr.y:2.7-9: error: %code qualifier 'bad' is not used
+ input-c-glr.y:3.8-10: error: %code qualifier 'bad' is not used
]])
AT_DATA([input-c++.y],
start: ;
]])
AT_BISON_CHECK([[input-c++.y]], [[1]], [],
- [[input-c++.y:1.7: %code qualifier 'q' is not used
- input-c++.y:2.7-9: %code qualifier 'bad' is not used
- input-c++.y:3.8: %code qualifier 'q' is not used
+ [[input-c++.y:1.7: error: %code qualifier 'q' is not used
+ input-c++.y:2.7-9: error: %code qualifier 'bad' is not used
+ input-c++.y:3.8: error: %code qualifier 'q' is not used
]])
AT_DATA([input-c++-glr.y],
start: ;
]])
AT_BISON_CHECK([[input-c++-glr.y]], [[1]], [],
- [[input-c++-glr.y:1.7-9: %code qualifier 'bad' is not used
- input-c++-glr.y:2.7: %code qualifier 'q' is not used
- input-c++-glr.y:3.7: %code qualifier 'q' is not used
+ [[input-c++-glr.y:1.7-9: error: %code qualifier 'bad' is not used
+ input-c++-glr.y:2.7: error: %code qualifier 'q' is not used
+ input-c++-glr.y:3.7: error: %code qualifier 'q' is not used
]])
AT_DATA([special-char-@@.y],
start: ;
]])
AT_BISON_CHECK([[special-char-@@.y]], [[1]], [],
- [[special-char-@@.y:1.7-9: %code qualifier 'bad' is not used
- special-char-@@.y:2.7: %code qualifier 'q' is not used
- special-char-@@.y:3.7: %code qualifier 'q' is not used
+ [[special-char-@@.y:1.7-9: error: %code qualifier 'bad' is not used
+ special-char-@@.y:2.7: error: %code qualifier 'q' is not used
+ special-char-@@.y:3.7: error: %code qualifier 'q' is not used
]])
AT_DATA([special-char-@:>@.y],
start: ;
]])
AT_BISON_CHECK([[special-char-@:>@.y]], [[1]], [],
- [[special-char-@:>@.y:1.7-9: %code qualifier 'bad' is not used
- special-char-@:>@.y:2.7: %code qualifier 'q' is not used
- special-char-@:>@.y:3.7: %code qualifier 'q' is not used
+ [[special-char-@:>@.y:1.7-9: error: %code qualifier 'bad' is not used
+ special-char-@:>@.y:2.7: error: %code qualifier 'q' is not used
+ special-char-@:>@.y:3.7: error: %code qualifier 'q' is not used
]])
AT_CLEANUP
]])
AT_BISON_CHECK([[input-redefined.y]], [[1]], [],
- [[input-redefined.y:2.9-11: %define variable 'var' redefined
- input-redefined.y:1.9-11: previous definition
- input-redefined.y:3.10-12: %define variable 'var' redefined
- input-redefined.y:2.9-11: previous definition
+ [[input-redefined.y:2.9-11: error: %define variable 'var' redefined
+ input-redefined.y:1.9-11: previous definition
+ input-redefined.y:3.10-12: error: %define variable 'var' redefined
+ input-redefined.y:2.9-11: previous definition
]])
AT_DATA([input-unused.y],
]])
AT_BISON_CHECK([[input-unused.y]], [[1]], [],
- [[input-unused.y:1.9-11: %define variable 'var' is not used
+ [[input-unused.y:1.9-11: error: %define variable 'var' is not used
]])
AT_CLEANUP
start: ;
]])
AT_BISON_CHECK([[-Dvar=cmd-d input-dg.y]], [[1]], [],
- [[input-dg.y:1.9-11: %define variable 'var' redefined
- <command line>:2: previous definition
+ [[input-dg.y:1.9-11: error: %define variable 'var' redefined
+ <command line>:2: previous definition
]])
AT_DATA([[input-unused.y]],
start: ;
]])
AT_BISON_CHECK([[-Dunused-d -Funused-f input-unused.y]], [[1]], [],
- [[<command line>:2: %define variable 'unused-d' is not used
- <command line>:3: %define variable 'unused-f' is not used
+ [[<command line>:2: error: %define variable 'unused-d' is not used
+ <command line>:3: error: %define variable 'unused-f' is not used
]])
AT_CLEANUP
]])
AT_BISON_CHECK([[Input.y]], [1], [],
- [[Input.y:2.9-14: invalid value for %define Boolean variable 'public'
+ [[Input.y:2.9-14: error: invalid value for %define Boolean variable 'public'
]])
AT_CLEANUP
start: ;
]])
AT_BISON_CHECK([[input.y]], [[1]], [[]],
- [[input.y:1.9-29: invalid value for %define variable 'lr.default-reductions': 'bogus'
- input.y:1.9-29: accepted value: 'most'
- input.y:1.9-29: accepted value: 'consistent'
- input.y:1.9-29: accepted value: 'accepting'
+ [[input.y:1.9-29: error: invalid value for %define variable 'lr.default-reductions': 'bogus'
+ input.y:1.9-29: accepted value: 'most'
+ input.y:1.9-29: accepted value: 'consistent'
+ input.y:1.9-29: accepted value: 'accepting'
]])
# Back-end.
+ # FIXME: these should be indented, but we shouldn't mess with the m4 yet
AT_DATA([[input.y]],
[[%define api.push-pull neither
%%
start: ;
]])
AT_BISON_CHECK([[input.y]], [1], [],
- [[input.y:1.9-21: invalid value for %define variable 'api.push-pull': 'neither'
- input.y:1.9-21: accepted value: 'pull'
- input.y:1.9-21: accepted value: 'push'
- input.y:1.9-21: accepted value: 'both'
+ [[input.y:1.9-21: error: invalid value for %define variable 'api.push-pull': 'neither'
+ input.y:1.9-21: error: accepted value: 'pull'
+ input.y:1.9-21: error: accepted value: 'push'
+ input.y:1.9-21: error: accepted value: 'both'
]])
AT_CLEANUP
start: ;
]])
AT_BISON_CHECK([[input.y]], [1], [],
-[[input.y:1.9-21: error: invalid value for %define variable 'api.push-pull': 'neither'
+[[input.y:1.9-21: warning: deprecated %define variable name: 'api.push_pull', use 'api.push-pull' [-Wdeprecated]
- input.y:1.9-21: invalid value for %define variable 'api.push-pull': 'neither'
- input.y:1.9-21: accepted value: 'pull'
- input.y:1.9-21: accepted value: 'push'
- input.y:1.9-21: accepted value: 'both'
++input.y:1.9-21: error: invalid value for %define variable 'api.push-pull': 'neither'
+ input.y:1.9-21: error: accepted value: 'pull'
+ input.y:1.9-21: error: accepted value: 'push'
+ input.y:1.9-21: error: accepted value: 'both'
]])
AT_DATA([[input.y]],
start: ;
]])
AT_BISON_CHECK([[input.y]], [1], [],
-[[input.y:1.9-34: error: invalid value for %define Boolean variable 'lr.keep-unreachable-states'
+[[input.y:1.9-34: warning: deprecated %define variable name: 'lr.keep_unreachable_states', use 'lr.keep-unreachable-states' [-Wdeprecated]
- input.y:1.9-34: invalid value for %define Boolean variable 'lr.keep-unreachable-states'
++input.y:1.9-34: error: invalid value for %define Boolean variable 'lr.keep-unreachable-states'
+]])
+
+AT_DATA([[input.y]],
+[[%define namespace "foo"
+%define api.namespace "foo"
+%%
+start: ;
+]])
+AT_BISON_CHECK([[input.y]], [1], [],
+[[input.y:1.9-17: warning: deprecated %define variable name: 'namespace', use 'api.namespace' [-Wdeprecated]
- input.y:2.9-21: %define variable 'api.namespace' redefined
- input.y:1.9-17: previous definition
++input.y:2.9-21: error: %define variable 'api.namespace' redefined
++input.y:1.9-17: previous definition
]])
AT_DATA([[input.y]],
start: ;
]])
AT_BISON_CHECK([[input.y]], [[1]], [],
- [[input.y:1.9-15: %define variable 'foo_bar' is not used
+ [[input.y:1.9-15: error: %define variable 'foo_bar' is not used
]])
AT_CLEANUP
]])
AT_BISON_CHECK([[input.y]], [[1]], [],
- [[input.y:1.9-16: %define variable 'api.pure' is not used
+ [[input.y:1.9-16: error: %define variable 'api.pure' is not used
]])
])
AT_DATA([[input.y]],
[[%language "C++"
%defines
-%define namespace "]$1["
+%define api.namespace "]$1["
%%
start: ;
]])
AT_BISON_CHECK([[input.y]], [1], [],
[m4_foreach([b4_arg], m4_dquote(m4_shift($@)),
- [[input.y:3.9-21: ]b4_arg[
-[[input.y:3.9-17: error: ]b4_arg[
++[[input.y:3.9-21: error: ]b4_arg[
]])])
])
AT_CHECK([[perl -e "print 'start: \'';" >> empty.y || exit 77]])
AT_BISON_CHECK([empty.y], [1], [],
-[[empty.y:2.8-9: warning: empty character literal
-empty.y:3.8-4.0: warning: empty character literal
+[[empty.y:2.8-9: warning: empty character literal [-Wother]
+empty.y:3.8-4.0: warning: empty character literal [-Wother]
- empty.y:3.8-4.0: missing "'" at end of line
+ empty.y:3.8-4.0: error: missing "'" at end of line
-empty.y:4.8: warning: empty character literal
+empty.y:4.8: warning: empty character literal [-Wother]
- empty.y:4.8: missing "'" at end of file
+ empty.y:4.8: error: missing "'" at end of file
]])
AT_DATA([two.y],
AT_CHECK([[perl -e "print 'start: \'ab';" >> two.y || exit 77]])
AT_BISON_CHECK([two.y], [1], [],
-[[two.y:2.8-11: warning: extra characters in character literal
-two.y:3.8-4.0: warning: extra characters in character literal
+[[two.y:2.8-11: warning: extra characters in character literal [-Wother]
+two.y:3.8-4.0: warning: extra characters in character literal [-Wother]
- two.y:3.8-4.0: missing "'" at end of line
+ two.y:3.8-4.0: error: missing "'" at end of line
-two.y:4.8-10: warning: extra characters in character literal
+two.y:4.8-10: warning: extra characters in character literal [-Wother]
- two.y:4.8-10: missing "'" at end of file
+ two.y:4.8-10: error: missing "'" at end of file
]])
AT_DATA([three.y],
AT_CHECK([[perl -e "print 'start: \'abc';" >> three.y || exit 77]])
AT_BISON_CHECK([three.y], [1], [],
-[[three.y:2.8-12: warning: extra characters in character literal
-three.y:3.8-4.0: warning: extra characters in character literal
+[[three.y:2.8-12: warning: extra characters in character literal [-Wother]
+three.y:3.8-4.0: warning: extra characters in character literal [-Wother]
- three.y:3.8-4.0: missing "'" at end of line
+ three.y:3.8-4.0: error: missing "'" at end of line
-three.y:4.8-11: warning: extra characters in character literal
+three.y:4.8-11: warning: extra characters in character literal [-Wother]
- three.y:4.8-11: missing "'" at end of file
+ three.y:4.8-11: error: missing "'" at end of file
]])
AT_CLEANUP
|| exit 77]])
AT_BISON_CHECK([input.y], [1], [],
- [[input.y:2.9-12: invalid number after \-escape: 777
+ [[input.y:2.9-12: error: invalid number after \-escape: 777
-input.y:2.8-13: warning: empty character literal
+input.y:2.8-13: warning: empty character literal [-Wother]
- input.y:2.16-17: invalid number after \-escape: 0
+ input.y:2.16-17: error: invalid number after \-escape: 0
-input.y:2.15-18: warning: empty character literal
+input.y:2.15-18: warning: empty character literal [-Wother]
- input.y:2.21-25: invalid number after \-escape: xfff
+ input.y:2.21-25: error: invalid number after \-escape: xfff
-input.y:2.20-26: warning: empty character literal
+input.y:2.20-26: warning: empty character literal [-Wother]
- input.y:2.29-31: invalid number after \-escape: x0
+ input.y:2.29-31: error: invalid number after \-escape: x0
-input.y:2.28-32: warning: empty character literal
+input.y:2.28-32: warning: empty character literal [-Wother]
- input.y:3.9-14: invalid number after \-escape: uffff
+ input.y:3.9-14: error: invalid number after \-escape: uffff
-input.y:3.8-15: warning: empty character literal
+input.y:3.8-15: warning: empty character literal [-Wother]
- input.y:3.18-23: invalid number after \-escape: u0000
+ input.y:3.18-23: error: invalid number after \-escape: u0000
-input.y:3.17-24: warning: empty character literal
+input.y:3.17-24: warning: empty character literal [-Wother]
- input.y:3.27-36: invalid number after \-escape: Uffffffff
+ input.y:3.27-36: error: invalid number after \-escape: Uffffffff
-input.y:3.26-37: warning: empty character literal
+input.y:3.26-37: warning: empty character literal [-Wother]
- input.y:3.40-49: invalid number after \-escape: U00000000
+ input.y:3.40-49: error: invalid number after \-escape: U00000000
-input.y:3.39-50: warning: empty character literal
+input.y:3.39-50: warning: empty character literal [-Wother]
- input.y:4.9-10: invalid character after \-escape: ' '
+ input.y:4.9-10: error: invalid character after \-escape: ' '
-input.y:4.8-11: warning: empty character literal
+input.y:4.8-11: warning: empty character literal [-Wother]
- input.y:4.14-15: invalid character after \-escape: A
+ input.y:4.14-15: error: invalid character after \-escape: A
-input.y:4.13-16: warning: empty character literal
+input.y:4.13-16: warning: empty character literal [-Wother]
- input.y:5.9-16: invalid character after \-escape: \t
- input.y:5.17: invalid character after \-escape: \f
- input.y:5.18: invalid character after \-escape: \0
- input.y:5.19: invalid character after \-escape: \001
+ input.y:5.9-16: error: invalid character after \-escape: \t
+ input.y:5.17: error: invalid character after \-escape: \f
+ input.y:5.18: error: invalid character after \-escape: \0
+ input.y:5.19: error: invalid character after \-escape: \001
]])
AT_CLEANUP
# parse.lac.* options are useless if LAC isn't actually activated.
AT_BISON_CHECK([[-Dparse.lac.es-capacity-initial=1 input.y]],
[[1]], [],
- [[<command line>:2: %define variable 'parse.lac.es-capacity-initial' is not used
+ [[<command line>:2: error: %define variable 'parse.lac.es-capacity-initial' is not used
]])
AT_BISON_CHECK([[-Dparse.lac.memory-trace=full input.y]],
[[1]], [],
- [[<command line>:2: %define variable 'parse.lac.memory-trace' is not used
+ [[<command line>:2: error: %define variable 'parse.lac.memory-trace' is not used
]])
AT_CLEANUP
# -Werror is not enabled by -Wall or equivalent.
AT_BISON_CHECK([[-Wall input.y]], [[0]], [[]],
-[[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar
+[[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar [-Wyacc]
]])
AT_BISON_CHECK([[-W input.y]], [[0]], [[]],
-[[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar
+[[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar [-Wyacc]
]])
AT_BISON_CHECK([[-Wno-none input.y]], [[0]], [[]],
-[[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar
+[[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar [-Wyacc]
]])
# -Werror is not disabled by -Wnone or equivalent.
AT_BISON_CHECK([[-Werror,none,yacc input.y]], [[1]], [[]], [[stderr]])
AT_CHECK([[sed 's/^.*bison:/bison:/' stderr]], [[0]],
[[bison: warnings being treated as errors
-input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar
+input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar [-Wyacc]
]])
[mv stderr experr]
AT_BISON_CHECK([[-Werror,no-all,yacc input.y]], [[1]], [[]], [[experr]])
exp:;
]])
AT_BISON_CHECK([[$2 input.y]], [[1]], [[]],
- [[$3: '%name-prefix' and '%define api.prefix' cannot be used together
+ [[$3: error: '%name-prefix' and '%define api.prefix' cannot be used together
]])
])
# check that the warnings are reported once, not three times.
AT_DATA_GRAMMAR([[input.y]],
-[[%token TOK
+[[%type <TYPE> exp
+%token <TYPE> TOK TOK2
%destructor { $%; @%; } <*> exp TOK;
%initial-action { $%; @%; };
%printer { $%; @%; } <*> exp TOK;
]])
AT_BISON_CHECK([[input.y]], 0, [],
-[[input.y:10.19: warning: stray '$'
-input.y:10.23: warning: stray '@'
-input.y:11.19: warning: stray '$'
-input.y:11.23: warning: stray '@'
-input.y:12.19: warning: stray '$'
-input.y:12.23: warning: stray '@'
-input.y:14.19: warning: stray '$'
-input.y:14.23: warning: stray '@'
+[[input.y:11.19: warning: stray '$' [-Wother]
+input.y:11.23: warning: stray '@' [-Wother]
+input.y:12.19: warning: stray '$' [-Wother]
+input.y:12.23: warning: stray '@' [-Wother]
+input.y:13.19: warning: stray '$' [-Wother]
+input.y:13.23: warning: stray '@' [-Wother]
+input.y:15.19: warning: stray '$' [-Wother]
+input.y:15.23: warning: stray '@' [-Wother]
]])
AT_CLEANUP
[AT_DATA([[input.y]],
[[%type <$1(DEAD %type)> exp
%token <$1(DEAD %token)> a
+%token b
%initial-action
{
$$;
};
%%
exp:
- a a[last]
+ a a[name] b
{
$$;
$][1;
$<$1(DEAD action 1)>$
$<$1(DEAD action 2)>1
- $<$1(DEAD action 3)>last
+ $<$1(DEAD action 3)>name
$<$1(DEAD action 4)>0
;
};
%token <ival> NUM "number"
%type <ival> exp
-%nonassoc '=' /* comparison */
+%nonassoc '=' /* comparison */
%left '-' '+'
%left '*' '/'
-%left NEG /* negation--unary minus */
+%precedence NEG /* negation--unary minus */
%right '^' /* exponentiation */
%%
%token <ival> NUM "number"
%type <ival> exp
-%nonassoc '=' /* comparison */
+%nonassoc '=' /* comparison */
%left '-' '+'
%left '*' '/'
-%left NEG /* negation--unary minus */
+%precedence NEG /* negation--unary minus */
%right '^' /* exponentiation */
%%
]])
AT_BISON_CHECK([-o test.c test.y], 1, [],
- [[test.y:50.51-60: invalid reference: '$<ival>lo9'
+ [[test.y:50.51-60: error: invalid reference: '$<ival>lo9'
test.y:50.3-68: symbol not found in production: lo9
-test.y:51.51-60: warning: misleading reference: '$<ival>exp'
-test.y:42.1-3: refers to: $exp at $$
-test.y:51.7: possibly meant: $x, hiding $exp at $1
-test.y:51.41: possibly meant: $r, hiding $exp at $4
+test.y:51.51-60: warning: misleading reference: '$<ival>exp' [-Wother]
- test.y:42.1-3: warning: refers to: $exp at $$ [-Wother]
- test.y:51.7: warning: possibly meant: $x, hiding $exp at $1 [-Wother]
- test.y:51.41: warning: possibly meant: $r, hiding $exp at $4 [-Wother]
- test.y:52.51-52: $l of 'exp' has no declared type
- test.y:55.46-49: invalid reference: '$r12'
++test.y:42.1-3: refers to: $exp at $$ [-Wother]
++test.y:51.7: possibly meant: $x, hiding $exp at $1 [-Wother]
++test.y:51.41: possibly meant: $r, hiding $exp at $4 [-Wother]
+ test.y:52.51-52: error: $l of 'exp' has no declared type
+ test.y:55.46-49: error: invalid reference: '$r12'
test.y:55.3-53: symbol not found in production: r12
- test.y:56.29-33: invalid reference: '$expo'
+ test.y:56.29-33: error: invalid reference: '$expo'
test.y:56.3-46: symbol not found in production: expo
]])
AT_BISON_OPTION_POPDEFS
foo.bar: '2'
]])
AT_BISON_CHECK([-o test.c test.y], 0, [],
-[[test.y:11.22-29: warning: misleading reference: '$foo.bar'
-test.y:11.8-10: refers to: $foo at $1
-test.y:11.12-18: possibly meant: $[foo.bar] at $2
+[[test.y:11.22-29: warning: misleading reference: '$foo.bar' [-Wother]
- test.y:11.8-10: warning: refers to: $foo at $1 [-Wother]
- test.y:11.12-18: warning: possibly meant: $[foo.bar] at $2 [-Wother]
++test.y:11.8-10: refers to: $foo at $1 [-Wother]
++test.y:11.12-18: possibly meant: $[foo.bar] at $2 [-Wother]
]])
AT_CLEANUP
;
]])
AT_BISON_CHECK([-o test.c test.y], 1, [],
- [[test.y:24.36-41: invalid reference: '$cond1'
+ [[test.y:24.36-41: error: invalid reference: '$cond1'
test.y:23.11-24.62: symbol not found in production: cond1
- test.y:26.43-53: invalid reference: '$stmt.field'
+ test.y:26.43-53: error: invalid reference: '$stmt.field'
test.y:25.11-26.60: symbol not found in production: stmt
test.y:25.35-38: possibly meant: $then.field, hiding $stmt.field at $4
- test.y:28.43-52: invalid reference: '$stmt.list'
+ test.y:28.43-52: error: invalid reference: '$stmt.list'
test.y:27.11-28.59: symbol not found in production: stmt
test.y:27.30-38: possibly meant: $[stmt.list] at $4
- test.y:30.43-46: ambiguous reference: '$xyz'
+ test.y:30.43-46: error: ambiguous reference: '$xyz'
test.y:29.35-37: refers to: $xyz at $4
test.y:29.50-52: refers to: $xyz at $6
- test.y:32.43-52: invalid reference: '$stmt.list'
+ test.y:32.43-52: error: invalid reference: '$stmt.list'
test.y:31.11-32.63: symbol not found in production: stmt
test.y:31.40-43: possibly meant: $then, hiding $[stmt.list] at $4
test.y:31.61-64: possibly meant: $else, hiding $[stmt.list] at $6
- test.y:34.43-58: invalid reference: '$stmt.list.field'
+ test.y:34.43-58: error: invalid reference: '$stmt.list.field'
test.y:33.11-34.69: symbol not found in production: stmt
test.y:33.40-43: possibly meant: $then.field, hiding $[stmt.list].field at $4
test.y:33.61-64: possibly meant: $else.field, hiding $[stmt.list].field at $6
- test.y:36.43-54: invalid reference: '$[stmt.list]'
+ test.y:36.43-54: error: invalid reference: '$[stmt.list]'
test.y:35.11-36.71: symbol not found in production: stmt.list
test.y:35.40-43: possibly meant: $then, hiding $[stmt.list] at $4
test.y:35.61-64: possibly meant: $else, hiding $[stmt.list] at $6
- test.y:38.43-49: invalid reference: '$then.1'
+ test.y:38.43-49: error: invalid reference: '$then.1'
test.y:37.11-38.60: symbol not found in production: then
test.y:37.40-45: possibly meant: $[then.1] at $4
- test.y:40.43-55: invalid reference: '$then.1.field'
+ test.y:40.43-55: error: invalid reference: '$then.1.field'
test.y:39.11-40.66: symbol not found in production: then
test.y:39.40-45: possibly meant: $[then.1].field at $4
- test.y:42.44-50: invalid reference: '$stmt.x'
+ test.y:42.44-50: error: invalid reference: '$stmt.x'
test.y:41.12-42.57: symbol not found in production: stmt
test.y:41.36-41: possibly meant: $[stmt.x].x, hiding $stmt.x at $4
test.y:41.36-41: possibly meant: $[stmt.x] at $4
- test.y:44.13-22: invalid reference: '$if-stmt-a'
+ test.y:44.13-22: error: invalid reference: '$if-stmt-a'
test.y:43.12-44.59: symbol not found in production: if
test.y:43.1-9: possibly meant: $[if-stmt-a] at $$
- test.y:46.46-54: invalid reference: '$then-a.f'
+ test.y:46.46-54: error: invalid reference: '$then-a.f'
test.y:45.12-46.65: symbol not found in production: then
test.y:45.41-46: possibly meant: $[then-a].f at $4
]])
{ s = $foo; }
]])
AT_BISON_CHECK([-o test.c test.y], 1, [],
- [[test.y:11.12: an identifier expected
+ [[test.y:11.12: error: an identifier expected
]])
AT_CLEANUP
{ s = $foo; }
]])
AT_BISON_CHECK([-o test.c test.y], 1, [],
- [[test.y:11.15: unexpected identifier in bracketed name: 'd'
+ [[test.y:11.15: error: unexpected identifier in bracketed name: 'd'
]])
AT_CLEANUP
{ s = $foo; }
]])
AT_BISON_CHECK([-o test.c test.y], 1, [],
- [[test.y:11.25: an identifier expected
+ [[test.y:11.25: error: an identifier expected
]])
AT_CLEANUP
{ s = $foo; }
]])
AT_BISON_CHECK([-o test.c test.y], 1, [],
- [[test.y:11.23: invalid character in bracketed name: '*'
- test.y:11.24: invalid character in bracketed name: '&'
- test.y:11.25: invalid character in bracketed name: '-'
- test.y:11.27: invalid character in bracketed name: '+'
+ [[test.y:11.23: error: invalid character in bracketed name: '*'
+ test.y:11.24: error: invalid character in bracketed name: '&'
+ test.y:11.25: error: invalid character in bracketed name: '-'
+ test.y:11.27: error: invalid character in bracketed name: '+'
]])
AT_CLEANUP
start[a s]: foo;
]])
AT_BISON_CHECK([-o test.c test.y], 1, [],
- [[test.y:11.9: unexpected identifier in bracketed name: 's'
+ [[test.y:11.9: error: unexpected identifier in bracketed name: 's'
]])
AT_CLEANUP
sym_b: 'b';
]])
AT_BISON_CHECK([-o test.c test.y], 1, [],
- [[test.y:12.22-31: invalid reference: '$sym.field'
+ [[test.y:12.22-31: error: invalid reference: '$sym.field'
test.y:12.3-35: symbol not found in production: sym
- test.y:13.22-35: invalid reference: '$<aa>sym.field'
+ test.y:13.22-35: error: invalid reference: '$<aa>sym.field'
test.y:13.3-39: symbol not found in production: sym
- test.y:14.22-33: invalid reference: '$[sym.field]'
+ test.y:14.22-33: error: invalid reference: '$[sym.field]'
test.y:14.3-37: symbol not found in production: sym.field
- test.y:15.22-37: invalid reference: '$<aa>[sym.field]'
+ test.y:15.22-37: error: invalid reference: '$<aa>[sym.field]'
test.y:15.3-41: symbol not found in production: sym.field
- test.y:16.22-25: invalid reference: '$sym'
+ test.y:16.22-25: error: invalid reference: '$sym'
test.y:16.3-29: symbol not found in production: sym
- test.y:17.22-29: invalid reference: '$<aa>sym'
+ test.y:17.22-29: error: invalid reference: '$<aa>sym'
test.y:17.3-33: symbol not found in production: sym
- test.y:18.22-27: invalid reference: '$[sym]'
+ test.y:18.22-27: error: invalid reference: '$[sym]'
test.y:18.3-65: symbol not found in production before $3: sym
- test.y:18.52-61: invalid reference: '$<aa>[sym]'
+ test.y:18.52-61: error: invalid reference: '$<aa>[sym]'
test.y:18.3-65: symbol not found in production: sym
- test.y:22.22-31: invalid reference: '$sym-field'
+ test.y:22.22-31: error: invalid reference: '$sym-field'
test.y:22.3-35: symbol not found in production: sym
- test.y:23.22-35: invalid reference: '$<aa>sym-field'
+ test.y:23.22-35: error: invalid reference: '$<aa>sym-field'
test.y:23.3-39: symbol not found in production: sym
- test.y:24.22-33: invalid reference: '$[sym-field]'
+ test.y:24.22-33: error: invalid reference: '$[sym-field]'
test.y:24.3-37: symbol not found in production: sym-field
- test.y:25.22-37: invalid reference: '$<aa>[sym-field]'
+ test.y:25.22-37: error: invalid reference: '$<aa>[sym-field]'
test.y:25.3-41: symbol not found in production: sym-field
- test.y:26.22-25: invalid reference: '$sym'
+ test.y:26.22-25: error: invalid reference: '$sym'
test.y:26.3-29: symbol not found in production: sym
- test.y:27.22-29: invalid reference: '$<aa>sym'
+ test.y:27.22-29: error: invalid reference: '$<aa>sym'
test.y:27.3-33: symbol not found in production: sym
- test.y:28.22-27: invalid reference: '$[sym]'
+ test.y:28.22-27: error: invalid reference: '$[sym]'
test.y:28.3-65: symbol not found in production before $3: sym
- test.y:28.52-61: invalid reference: '$<aa>[sym]'
+ test.y:28.52-61: error: invalid reference: '$<aa>[sym]'
test.y:28.3-65: symbol not found in production: sym
]])
AT_CLEANUP
.field: ;
]])
AT_BISON_CHECK([[test.y]], [[1]], [],
- [[test.y:4.12-18: invalid reference: '$.field'
+ [[test.y:4.12-18: error: invalid reference: '$.field'
test.y:4.13: syntax error after '$', expecting integer, letter, '_', '@<:@', or '$'
test.y:4.3-8: possibly meant: $[.field] at $1
- test.y:5.12-18: invalid reference: '@.field'
+ test.y:5.12-18: error: invalid reference: '@.field'
test.y:5.13: syntax error after '@', expecting integer, letter, '_', '@<:@', or '$'
]])
AT_DATA([[test.y]],
;
]])
AT_BISON_CHECK([[test.y]], [[0]], [],
-[[test.y:4.9: warning: stray '$'
-test.y:5.9: warning: stray '@'
+[[test.y:4.9: warning: stray '$' [-Wother]
+test.y:5.9: warning: stray '@' [-Wother]
]])
AT_CLEANUP
# [ADDITIONAL-TESTS], [PRE-TESTS])
# -----------------------------------------------------------------------------
m4_define([AT_CHECK_OUTPUT],
-[AT_SETUP([[Output files: $2 $3 $5]])
-$7
-for file in $1 $4; do
- case "$file" in
- */*) mkdir -p `echo "$file" | sed 's,/.*,,'`;;
+[AT_SETUP([[Output files: ]$2 $3 $5])[
+]$7[
+for file in ]$1 $4[; do
+ case $file in
+ */*) mkdir -p `echo "$file" | sed 's,/[^/]*,,'`;;
esac
done
-AT_DATA([$1],
-[[$2
+]AT_DATA([$1],
+[$2[
%%
foo: {};
+]])[
+
+]AT_BISON_CHECK([$3 $1 $5], 0)[
+# Ignore the files non-generated files
+]AT_CHECK([find . -type f -and -not -path './$1' -and -not -path './testsuite.log' |
+ sed 's,\./,,' |
+ sort |
+ xargs echo],
+ [], [$4
+])[
+]$6[
+]AT_CLEANUP[
]])
-AT_BISON_CHECK([$3 $1 $5], 0)
-AT_CHECK([ls $4], [], [ignore])
-$6
-AT_CLEANUP
-])
-
AT_CHECK_OUTPUT([foo.y], [], [-dv],
- [foo.output foo.tab.c foo.tab.h])
+ [foo.output foo.tab.c foo.tab.h])
# Some versions of Valgrind (at least valgrind-3.6.0.SVN-Debian) report
# "fgrep: write error: Bad file descriptor" when stdout is closed, so we
# skip this test group during maintainer-check-valgrind.
AT_CHECK_OUTPUT([foo.y], [], [-dv],
- [foo.output foo.tab.c foo.tab.h],
- [>&-], [],
- [AT_CHECK([[case "$PREBISON" in *valgrind*) exit 77;; esac]])])
+ [foo.output foo.tab.c foo.tab.h],
+ [>&-], [],
+ [AT_CHECK([[case "$PREBISON" in *valgrind*) exit 77;; esac]])])
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],
- [foo.output foo.tab.c foo.tab.h])
+ [foo.output foo.tab.c foo.tab.h])
AT_CHECK_OUTPUT([foo.y], [], [-dv -y],
- [y.output y.tab.c y.tab.h])
+ [y.output y.tab.c y.tab.h])
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],
- [foo.c foo.dot foo.h foo.output])
+ [foo.c foo.dot foo.h foo.output])
AT_CHECK_OUTPUT([foo.y], [%defines %verbose], [],
- [foo.output foo.tab.c foo.tab.h])
+ [foo.output foo.tab.c foo.tab.h])
AT_CHECK_OUTPUT([foo.y], [%defines %verbose %yacc],[],
- [y.output y.tab.c y.tab.h])
+ [y.output y.tab.c y.tab.h])
AT_CHECK_OUTPUT([foo.yy], [%defines %verbose %yacc],[],
- [y.output y.tab.c y.tab.h])
+ [y.output y.tab.c y.tab.h])
# Exercise %output and %file-prefix including deprecated '='
AT_CHECK_OUTPUT([foo.y], [%file-prefix "bar" %defines %verbose], [],
- [bar.output bar.tab.c bar.tab.h])
+ [bar.output bar.tab.c bar.tab.h])
AT_CHECK_OUTPUT([foo.y], [%output="bar.c" %defines %verbose %yacc],[],
- [bar.output bar.c bar.h])
+ [bar.c bar.h bar.output])
AT_CHECK_OUTPUT([foo.y],
- [%file-prefix="baz" %output "bar.c" %defines %verbose %yacc],
- [],
- [bar.output bar.c bar.h])
+ [%file-prefix="baz" %output "bar.c" %defines %verbose %yacc],
+ [],
+ [bar.c bar.h bar.output])
# Check priorities of extension control.
AT_CHECK_OUTPUT([foo.yy], [%defines %verbose], [],
- [foo.output foo.tab.cc foo.tab.hh])
+ [foo.output foo.tab.cc foo.tab.hh])
AT_CHECK_OUTPUT([foo.yy], [%defines %verbose ], [-o foo.c],
- [foo.c foo.h foo.output])
+ [foo.c foo.h foo.output])
AT_CHECK_OUTPUT([foo.yy], [],
- [--defines=foo.hpp -o foo.c++],
- [foo.c++ foo.hpp])
+ [--defines=foo.hpp -o foo.c++],
+ [foo.c++ foo.hpp])
AT_CHECK_OUTPUT([foo.yy], [%defines "foo.hpp"],
- [-o foo.c++],
- [foo.c++ foo.hpp])
+ [-o foo.c++],
+ [foo.c++ foo.hpp])
AT_CHECK_OUTPUT([foo.yy], [],
- [-o foo.c++ --graph=foo.gph],
- [foo.c++ foo.gph])
+ [-o foo.c++ --graph=foo.gph],
+ [foo.c++ foo.gph])
## ------------ ##
AT_CHECK([grep 'include .subdir/' $1.hh], 1, [])
])
+AT_CHECK_OUTPUT([foo.yy], [%skeleton "lalr1.cc" %verbose], [],
+ [foo.output foo.tab.cc])
+
AT_CHECK_OUTPUT([foo.yy], [%skeleton "lalr1.cc" %defines %verbose], [],
- [foo.tab.cc foo.tab.hh foo.output location.hh stack.hh position.hh])
+ [foo.output foo.tab.cc foo.tab.hh stack.hh])
+
+AT_CHECK_OUTPUT([foo.yy], [%skeleton "lalr1.cc" %verbose %locations], [],
+ [foo.output foo.tab.cc])
+
+AT_CHECK_OUTPUT([foo.yy], [%skeleton "lalr1.cc" %defines %verbose %locations], [],
+ [foo.output foo.tab.cc foo.tab.hh location.hh position.hh stack.hh])
AT_CHECK_OUTPUT([subdir/foo.yy], [%skeleton "lalr1.cc" %defines %verbose], [],
- [foo.tab.cc foo.tab.hh foo.output location.hh stack.hh position.hh],
- [], [AT_CHECK_NO_SUBDIR_PART([foo.tab])])
+ [foo.output foo.tab.cc foo.tab.hh stack.hh],
+ [], [AT_CHECK_NO_SUBDIR_PART([foo.tab])])
-AT_CHECK_OUTPUT([subdir/foo.yy], [%skeleton "lalr1.cc" %defines %verbose],
- [-o subdir/foo.cc],
- [subdir/foo.cc subdir/foo.hh subdir/foo.output subdir/location.hh subdir/stack.hh subdir/position.hh],
- [], [AT_CHECK_NO_SUBDIR_PART([subdir/foo])])
+AT_CHECK_OUTPUT([subdir/foo.yy], [%skeleton "lalr1.cc" %defines %verbose %locations],
+ [-o subdir/foo.cc],
+ [subdir/foo.cc subdir/foo.hh subdir/foo.output subdir/location.hh subdir/position.hh subdir/stack.hh],
+ [], [AT_CHECK_NO_SUBDIR_PART([subdir/foo])])
AT_CHECK_OUTPUT([gram_dir/foo.yy],
[%skeleton "lalr1.cc" %defines %verbose %file-prefix "output_dir/foo"],
[],
- [output_dir/foo.tab.cc output_dir/foo.tab.hh output_dir/foo.output output_dir/location.hh output_dir/stack.hh output_dir/position.hh])
+ [output_dir/foo.output output_dir/foo.tab.cc output_dir/foo.tab.hh output_dir/stack.hh])
+
+AT_CHECK_OUTPUT([gram_dir/foo.yy],
+ [%skeleton "lalr1.cc" %defines %locations %verbose %file-prefix "output_dir/foo"],
+ [],
+ [output_dir/foo.output output_dir/foo.tab.cc output_dir/foo.tab.hh output_dir/location.hh output_dir/position.hh output_dir/stack.hh])
# AT_CHECK_CONFLICTING_OUTPUT(INPUT-FILE, DIRECTIVES, FLAGS, STDERR,
AT_CHECK_CONFLICTING_OUTPUT([foo.y],
[], [--graph="foo.tab.c"],
-[foo.y: warning: conflicting outputs to file 'foo.tab.c'
-])
+[[foo.y: warning: conflicting outputs to file 'foo.tab.c' [-Wother]
+]])
AT_CHECK_CONFLICTING_OUTPUT([foo.y],
[%defines "foo.output"], [-v],
-[foo.y: warning: conflicting outputs to file 'foo.output'
-])
+[[foo.y: warning: conflicting outputs to file 'foo.output' [-Wother]
+]])
AT_CHECK_CONFLICTING_OUTPUT([foo.y],
-[%skeleton "lalr1.cc" %defines], [--graph="location.hh"],
-[foo.y: warning: conflicting outputs to file 'location.hh'
-])
+[%skeleton "lalr1.cc" %defines %locations], [--graph="location.hh"],
+[[foo.y: warning: conflicting outputs to file 'location.hh' [-Wother]
+]])
AT_CHECK_CONFLICTING_OUTPUT([foo.y], [], [-o foo.y],
- [[foo.y: refusing to overwrite the input file 'foo.y'
-[foo.y: error: refusing to overwrite the input file 'foo.y'
-], 1)
++[[foo.y: error: refusing to overwrite the input file 'foo.y'
+]], 1)
# AT_CHECK_OUTPUT_FILE_NAME(FILE-NAME-PREFIX, [ADDITIONAL-TESTS])
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([-v -o input.c input.y], 0, [],
-[[input.y:6.8-14: warning: symbol "<=" used more than once as a literal string
+[[input.y:6.8-14: warning: symbol "<=" used more than once as a literal string [-Wother]
]])
AT_CLEANUP
]])
AT_BISON_CHECK([input.y], [1], [],
- [[input.y:2.1: invalid character: '?'
- input.y:3.14: invalid character: '}'
- input.y:4.1: invalid character: '%'
- input.y:4.2: invalid character: '&'
- input.y:5.1-17: invalid directive: '%a-does-not-exist'
- input.y:6.1: invalid character: '%'
- input.y:6.2: invalid character: '-'
- input.y:7.1-8.0: missing '%}' at end of file
- input.y:7.1-8.0: syntax error, unexpected %{...%}
+ [[input.y:2.1: error: invalid character: '?'
+ input.y:3.14: error: invalid character: '}'
+ input.y:4.1: error: invalid character: '%'
+ input.y:4.2: error: invalid character: '&'
+ input.y:5.1-17: error: invalid directive: '%a-does-not-exist'
+ input.y:6.1: 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: syntax error, unexpected %{...%}
]])
AT_CLEANUP
]])
AT_BISON_CHECK([input.y], [1], [],
- [[input.y:3.1-15: syntax error, unexpected %initial-action, expecting {...}
+ [[input.y:3.1-15: error: syntax error, unexpected %initial-action, expecting {...}
]])
AT_CLEANUP
# C-string literal. Also notice that unnecessary escaping, such as "\?", from
# the user specification is eliminated.
AT_BISON_CHECK([-o input.c input.y], [[0]], [[]],
-[[input.y:22.8-14: warning: symbol SPECIAL redeclared
-input.y:22.8-63: warning: symbol "\\'?\"\a\b\f\n\r\t\v\001\201\001\201??!" used more than once as a literal string
+[[input.y:22.8-14: warning: symbol SPECIAL redeclared [-Wother]
+input.y:22.8-63: warning: symbol "\\'?\"\a\b\f\n\r\t\v\001\201\001\201??!" used more than once as a literal string [-Wother]
]])
AT_COMPILE([input])
AT_KEYWORDS([report])
AT_DATA([input.y],
-[[%token undef_id_tok const_id_tok
+[[%token undef_id_tok const_id_tok
%start CONST_DEC_PART
\f
;
CONST_DEC_LIST:
- CONST_DEC
+ CONST_DEC
| CONST_DEC_LIST CONST_DEC
;
CONST_DEC:
- { } undef_id_tok '=' const_id_tok ';'
+ { } undef_id_tok '=' const_id_tok ';'
;
%%
]])
2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
5, 6
};
-static const yytype_uint8 yyprhs[] =
-{
- 0, 0, 3, 5, 6, 9, 14
-};
-static const yytype_int8 yyrhs[] =
-{
- 8, 0, -1, 9, -1, -1, 10, 11, -1, 3,
- 4, 5, 8, -1, 6, 8, -1
-};
static const yytype_uint8 yyrline[] =
{
0, 2, 2, 3, 3, 4, 5
{
0, 256, 257, 258, 259, 260, 261
};
-static const yytype_uint8 yyr1[] =
-{
- 0, 7, 8, 9, 9, 10, 11
-};
-static const yytype_uint8 yyr2[] =
+static const yytype_int8 yypact[] =
{
- 0, 2, 1, 0, 2, 4, 2
+ -2, -1, 4, -8, 0, 2, -8, -2, -8, -2,
+ -8, -8
};
static const yytype_uint8 yydefact[] =
{
3, 0, 0, 2, 0, 0, 1, 3, 4, 3,
6, 5
};
-static const yytype_int8 yydefgoto[] =
-{
- -1, 2, 3, 4, 8
-};
-static const yytype_int8 yypact[] =
-{
- -2, -1, 4, -8, 0, 2, -8, -2, -8, -2,
- -8, -8
-};
static const yytype_int8 yypgoto[] =
{
-8, -7, -8, -8, -8
};
+static const yytype_int8 yydefgoto[] =
+{
+ -1, 2, 3, 4, 8
+};
static const yytype_uint8 yytable[] =
{
10, 1, 11, 5, 6, 0, 7, 9
0, 3, 8, 9, 10, 4, 0, 6, 11, 5,
8, 8
};
+static const yytype_uint8 yyr1[] =
+{
+ 0, 7, 8, 9, 9, 10, 11
+};
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 1, 0, 2, 4, 2
+};
]])
AT_CLEANUP
# --------------------------------
m4_define([_AT_DATA_EXPECT2_Y],
[AT_DATA_GRAMMAR([expect2.y],
-[[%{
-static int yylex (]AT_LALR1_CC_IF([int *], [void]));
-AT_LALR1_CC_IF([],
-[[#include <stdio.h>
-#include <stdlib.h>
+[%{
+static int yylex (AT_LALR1_CC_IF([int *], [void]));
+AT_LALR1_CC_IF([[#include <cstdlib>]],
+[[#include <stdlib.h>
+#include <stdio.h>
]AT_YYERROR_DECLARE])[
%}
$1
start:
{
printf ("Bison would once convert this action to a midrule because of the"
- " subsequent braced code.\n");
+ " subsequent braced code.\n");
}
;
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o input.c input.y]], [[0]],,
-[[input.y:23.5-19: warning: rule useless in parser due to conflicts: start: start
-input.y:27.5-19: warning: rule useless in parser due to conflicts: sr_conflict: TK2 "tok alias"
+[[input.y:23.5-19: warning: rule useless in parser due to conflicts: start: start [-Wother]
+input.y:27.5-19: warning: rule useless in parser due to conflicts: sr_conflict: TK2 "tok alias" [-Wother]
]])
AT_COMPILE([[input]])
AT_PARSER_CHECK([[./input]])
AT_SETUP([[parse-gram.y: LALR = IELR]])
-# Avoid differences in synclines by telling bison that the output files
-# have the same name.
+# Avoid tests/bison's dark magic by processing a local copy of the
+# grammar. Avoid differences in synclines by telling bison that the
+# output files have the same name.
[cp $abs_top_srcdir/src/parse-gram.y input.y]
AT_BISON_CHECK([[-o input.c -Dlr.type=lalr input.y]])
[mv input.c lalr.c]
-## --------------------------------------- ##
-## %error-verbose and YYSTACK_USE_ALLOCA. ##
-## --------------------------------------- ##
+## -------------------------------------------- ##
+## parse.error=verbose and YYSTACK_USE_ALLOCA. ##
+## -------------------------------------------- ##
-AT_SETUP([[%error-verbose and YYSTACK_USE_ALLOCA]])
+AT_SETUP([[parse.error=verbose and YYSTACK_USE_ALLOCA]])
AT_BISON_OPTION_PUSHDEFS
AT_DATA_GRAMMAR([input.y],
#define YYSTACK_USE_ALLOCA 1
}
-%error-verbose
+%define parse.error verbose
%%
%%
]AT_YYERROR_DEFINE[
-/* Induce two syntax error messages (which requires full error
- recovery by shifting 3 tokens) in order to detect any loss of the
- reallocated buffer. */
+ /* Induce two syntax error messages (which requires full error
+ recovery by shifting 3 tokens) in order to detect any loss of the
+ reallocated buffer. */
]AT_YYLEX_DEFINE(["abc"])[
int
main (void)
-## ------------------------- ##
-## %error-verbose overflow. ##
-## ------------------------- ##
+## ------------------------------ ##
+## parse.error=verbose overflow. ##
+## ------------------------------ ##
# Imagine the case where YYSTACK_ALLOC_MAXIMUM = YYSIZE_MAXIMUM and an
# invocation of yysyntax_error has caused yymsg_alloc to grow to exactly
# size calculation would return YYSIZE_MAXIMUM to yyparse. Then,
# yyparse would invoke yyerror using the old contents of yymsg.
-AT_SETUP([[%error-verbose overflow]])
+AT_SETUP([[parse.error=verbose overflow]])
+
AT_BISON_OPTION_PUSHDEFS
AT_DATA_GRAMMAR([input.y],
[[%code {
#define YYMAXDEPTH 100
}
-%error-verbose
+%define parse.error verbose
%%
%%
]AT_YYERROR_DEFINE[
-/* Induce two syntax error messages (which requires full error
- recovery by shifting 3 tokens). */
+ /* Induce two syntax error messages (which requires full error
+ recovery by shifting 3 tokens). */
]AT_YYLEX_DEFINE(["abc"])[
int
main (void)
}
]$1[
-%error-verbose
+%define parse.error verbose
%token 'c'
%%
AT_BISON_CHECK([[-Dparse.lac=full -Dparse.lac.es-capacity-initial=1 \
-Dparse.lac.memory-trace=full \
-t -o input.c input.y]], [[0]], [],
-[[input.y: conflicts: 21 shift/reduce
+[[input.y: warning: 21 shift/reduce conflicts [-Wconflicts-sr]
]])
AT_COMPILE([[input]])
AT_PARSER_CHECK([[./input > stdout.txt 2> stderr.txt]], [[1]])
AT_BISON_CHECK([[-Dparse.lac=full -Dparse.lac.es-capacity-initial=1 \
-t -o input.c input.y]], [[0]], [],
-[[input.y: conflicts: 8 shift/reduce
+[[input.y: warning: 8 shift/reduce conflicts [-Wconflicts-sr]
]])
AT_COMPILE([[input]])
AT_BISON_OPTION_POPDEFS
]])
AT_BISON_CHECK([[input.y]], [[1]], [[]],
- [[<skeleton default value>: invalid value for %define Boolean variable 'foo'
+ [[<skeleton default value>: error: invalid value for %define Boolean variable 'foo'
]])
AT_CLEANUP
]])
AT_BISON_CHECK([[input1.y]], [[1]], [[]],
-[[input1.y: warning: foow fubar
-foow.y:2.3-5.3: warning: foowat fubar
+[[input1.y: warning: foow fubar [-Wother]
+foow.y:2.3-5.3: warning: foowat fubar [-Wother]
- input1.y: fooc fubar
- fooc.y:1.1-10.5: foocat fubar
+ input1.y: error: fooc fubar
+ fooc.y:1.1-10.5: error: foocat fubar
input1.y: fatal error: foof fubar
]])
]])
AT_BISON_CHECK([[input1.y]], [[1]], [[]],
- [[input1.y: non-fatal error
+ [[input1.y: error: non-fatal error
input1.y: fatal error: M4 should exit immediately here
]])
]])
AT_BISON_CHECK([[input2.y]], [[1]], [[]],
-[[input2.y: warning: morning
+[[input2.y: warning: morning [-Wother]
foo.y:1.5-6: fatal error: M4 should exit immediately here
]])