mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
yacc: comply with recent POSIX updates: declare yyerror and yylex
In POSIX Yacc mode, declare yyerror and yylex unless already #defined, or if YYERROR_IS_DECLARED/YYLEX_IS_DECLARED are defined (for consistency with Bison's YYSTYPE_IS_DECLARED/YYLTYPE_IS_DECLARED). See <https://austingroupbugs.net/view.php?id=1388#c5220>. * data/skeletons/c.m4 (b4_function_declare): Resurect. (b4_lex_formals): Since we will possibly expose this prototype in the header, take the prefix into account. * data/skeletons/yacc.c (b4_declare_yyerror_and_yylex): New. (b4_shared_declarations): Use it. * tests/local.at (AT_YACC_IF): New. When in Yacc mode, set the `yacc` Autotest keyword. (AT_YYERROR_DECLARE(c)): Don't declare in Yacc mode, to avoid clashes (since this signature is static). (AT_YYERROR_DEFINE(c)): Don't define as static in Yacc mode. * tests/regression.at (Early token definitions with --yacc): Specify that we are in Yacc mode.
This commit is contained in:
8
NEWS
8
NEWS
@@ -9,6 +9,14 @@ GNU Bison NEWS
|
|||||||
now generates a *.gv file by default, instead of *.dot. A transition
|
now generates a *.gv file by default, instead of *.dot. A transition
|
||||||
started in Bison 3.4.
|
started in Bison 3.4.
|
||||||
|
|
||||||
|
To comply with the latest POSIX standard, in Yacc compatibility mode
|
||||||
|
(options `-y`/`--yacc`) Bison now generates prototypes for yyerror and
|
||||||
|
yylex. In some situations, this is breaking compatibility: if the user
|
||||||
|
has already declared these functions but with some differences (e.g., to
|
||||||
|
declare them as static, or to use specific attributes), the generated
|
||||||
|
parser will fail to compile. To disable these prototypes, #define yyerror
|
||||||
|
(to `yyerror`), and likewise for yylex.
|
||||||
|
|
||||||
** Deprecated features
|
** Deprecated features
|
||||||
|
|
||||||
Support for the YYPRINT macro is removed. It worked only with yacc.c and
|
Support for the YYPRINT macro is removed. It worked only with yacc.c and
|
||||||
|
|||||||
4
TODO
4
TODO
@@ -1,8 +1,4 @@
|
|||||||
* Soon
|
* Soon
|
||||||
** POSIX updates
|
|
||||||
See the recent changes about function prototypes in POSIX Yacc. Implement
|
|
||||||
them.
|
|
||||||
|
|
||||||
** scan-code
|
** scan-code
|
||||||
The default case is scanning char-per-char.
|
The default case is scanning char-per-char.
|
||||||
|
|
||||||
|
|||||||
@@ -112,8 +112,8 @@ b4_percent_define_default([[api.symbol.prefix]], [[YYSYMBOL_]])
|
|||||||
# All the yylex formal arguments.
|
# All the yylex formal arguments.
|
||||||
# b4_lex_param arrives quoted twice, but we want to keep only one level.
|
# b4_lex_param arrives quoted twice, but we want to keep only one level.
|
||||||
m4_define([b4_lex_formals],
|
m4_define([b4_lex_formals],
|
||||||
[b4_pure_if([[[[YYSTYPE *yylvalp]], [[&yylval]]][]dnl
|
[b4_pure_if([[[b4_api_PREFIX[STYPE *yylvalp]], [[&yylval]]][]dnl
|
||||||
b4_locations_if([, [[YYLTYPE *yyllocp], [&yylloc]]])])dnl
|
b4_locations_if([, [b4_api_PREFIX[LTYPE *yyllocp], [&yylloc]]])])dnl
|
||||||
m4_ifdef([b4_lex_param], [, ]b4_lex_param)])
|
m4_ifdef([b4_lex_param], [, ]b4_lex_param)])
|
||||||
|
|
||||||
|
|
||||||
@@ -662,6 +662,14 @@ m4_define([b4_formal],
|
|||||||
[$1])
|
[$1])
|
||||||
|
|
||||||
|
|
||||||
|
# b4_function_declare(NAME, RETURN-VALUE, [DECL1, NAME1], ...)
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# Declare the function NAME.
|
||||||
|
m4_define([b4_function_declare],
|
||||||
|
[$2 $1 (b4_formals(m4_shift2($@)));[]dnl
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## --------------------- ##
|
## --------------------- ##
|
||||||
## Calling C functions. ##
|
## Calling C functions. ##
|
||||||
|
|||||||
@@ -102,6 +102,16 @@ m4_define([b4_yyerror_arg_loc_if],
|
|||||||
[1], [m4_ifset([b4_parse_param], [$1])],
|
[1], [m4_ifset([b4_parse_param], [$1])],
|
||||||
[2], [$1])])])
|
[2], [$1])])])
|
||||||
|
|
||||||
|
# b4_yyerror_formals
|
||||||
|
# ------------------
|
||||||
|
m4_define([b4_yyerror_formals],
|
||||||
|
[b4_pure_if([b4_locations_if([, [[const ]b4_api_PREFIX[LTYPE *yyllocp], [&yylloc]]])[]dnl
|
||||||
|
m4_ifdef([b4_parse_param], [, b4_parse_param])[]dnl
|
||||||
|
,])dnl
|
||||||
|
[[const char *msg], [msg]]])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# b4_yyerror_args
|
# b4_yyerror_args
|
||||||
# ---------------
|
# ---------------
|
||||||
# Arguments passed to yyerror: user args plus yylloc.
|
# Arguments passed to yyerror: user args plus yylloc.
|
||||||
@@ -352,17 +362,32 @@ m4_define([b4_declare_yyparse],
|
|||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
# b4_declare_yyerror_and_yylex
|
||||||
|
# ----------------------------
|
||||||
|
# Comply with POSIX Yacc.
|
||||||
|
# <https://austingroupbugs.net/view.php?id=1388#c5220>
|
||||||
|
m4_define([b4_declare_yyerror_and_yylex],
|
||||||
|
[b4_yacc_if([[#if !defined ]b4_prefix[error && !defined ]b4_api_PREFIX[ERROR_IS_DECLARED
|
||||||
|
]b4_function_declare([b4_prefix[error]], void, b4_yyerror_formals)[
|
||||||
|
#endif
|
||||||
|
#if !defined ]b4_prefix[lex && !defined ]b4_api_PREFIX[LEX_IS_DECLARED
|
||||||
|
]b4_function_declare([b4_prefix[lex]], int, b4_lex_formals)[
|
||||||
|
#endif
|
||||||
|
]])dnl
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
# b4_shared_declarations
|
# b4_shared_declarations
|
||||||
# ----------------------
|
# ----------------------
|
||||||
# Declaration that might either go into the header (if --header)
|
# Declarations that might either go into the header (if --header)
|
||||||
# or open coded in the parser body.
|
# or into the implementation file.
|
||||||
m4_define([b4_shared_declarations],
|
m4_define([b4_shared_declarations],
|
||||||
[b4_cpp_guard_open([b4_spec_mapped_header_file])[
|
[b4_cpp_guard_open([b4_spec_mapped_header_file])[
|
||||||
]b4_declare_yydebug[
|
]b4_declare_yydebug[
|
||||||
]b4_percent_code_get([[requires]])[
|
]b4_percent_code_get([[requires]])[
|
||||||
]b4_token_enums_defines[
|
]b4_token_enums_defines[
|
||||||
]b4_declare_yylstype[
|
]b4_declare_yylstype[
|
||||||
|
]b4_declare_yyerror_and_yylex[
|
||||||
]b4_declare_yyparse[
|
]b4_declare_yyparse[
|
||||||
]b4_percent_code_get([[provides]])[
|
]b4_percent_code_get([[provides]])[
|
||||||
]b4_cpp_guard_close([b4_spec_mapped_header_file])[]dnl
|
]b4_cpp_guard_close([b4_spec_mapped_header_file])[]dnl
|
||||||
|
|||||||
@@ -6117,11 +6117,13 @@ states and what is done for each type of lookahead token in that state.
|
|||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Directive} %yacc
|
@deffn {Directive} %yacc
|
||||||
Pretend the option @option{--yacc} was given, i.e., imitate Yacc, including
|
Pretend the option @option{--yacc} was given
|
||||||
its naming conventions. Only makes sense with the @file{yacc.c}
|
(@pxref{option-yacc,,@option{--yacc}}), i.e., imitate Yacc, including its
|
||||||
|
naming conventions. Only makes sense with the @file{yacc.c}
|
||||||
skeleton. @xref{Tuning the Parser}, for more.
|
skeleton. @xref{Tuning the Parser}, for more.
|
||||||
|
|
||||||
Of course @code{%yacc} is a Bison extension@dots{}
|
Of course, being a Bison extension, @code{%yacc} is somewhat
|
||||||
|
self-contradictory@dots{}
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
@@ -11832,8 +11834,9 @@ Pretend that @code{%locations} was specified. @xref{Decl Summary}.
|
|||||||
@item -p @var{prefix}
|
@item -p @var{prefix}
|
||||||
@itemx --name-prefix=@var{prefix}
|
@itemx --name-prefix=@var{prefix}
|
||||||
Pretend that @code{%name-prefix "@var{prefix}"} was specified (@pxref{Decl
|
Pretend that @code{%name-prefix "@var{prefix}"} was specified (@pxref{Decl
|
||||||
Summary}). Obsoleted by @option{-Dapi.prefix=@var{prefix}}. @xref{Multiple
|
Summary}). The option @option{-p} is specified by POSIX. When POSIX
|
||||||
Parsers}.
|
compatibility is not a requirement, @option{-Dapi.prefix=@var{prefix}} is a
|
||||||
|
better option (@pxref{Multiple Parsers}).
|
||||||
|
|
||||||
@item -l
|
@item -l
|
||||||
@itemx --no-lines
|
@itemx --no-lines
|
||||||
@@ -11865,26 +11868,46 @@ This is similar to how most shells resolve commands.
|
|||||||
Pretend that @code{%token-table} was specified. @xref{Decl Summary}.
|
Pretend that @code{%token-table} was specified. @xref{Decl Summary}.
|
||||||
|
|
||||||
@item -y
|
@item -y
|
||||||
@itemx --yacc
|
@itemx @anchor{option-yacc} --yacc
|
||||||
Act more like the traditional @command{yacc} command. This can cause
|
Act more like the traditional @command{yacc} command:
|
||||||
different diagnostics to be generated (it implies @option{-Wyacc}), and may
|
@itemize
|
||||||
change behavior in other minor ways. Most importantly, imitate Yacc's
|
@item
|
||||||
output file name conventions, so that the parser implementation file is
|
Generate different diagnostics (it implies @option{-Wyacc}).
|
||||||
called @file{y.tab.c}, and the other outputs are called @file{y.output} and
|
@item
|
||||||
@file{y.tab.h}. Also, generate @code{#define} statements in addition to an
|
Generate @code{#define} statements in addition to an @code{enum} to
|
||||||
@code{enum} to associate token codes with token kind names. Thus, the
|
associate token codes with token kind names.
|
||||||
following shell script can substitute for Yacc, and the Bison distribution
|
@item
|
||||||
contains such a script for compatibility with POSIX:
|
Generate prototypes for @code{yyerror} and @code{yylex} (since Bison 3.8):
|
||||||
|
|
||||||
@example
|
@example
|
||||||
#! /bin/sh
|
int yylex (void);
|
||||||
bison -y "$@@"
|
void yyerror (const char *);
|
||||||
@end example
|
@end example
|
||||||
|
As a Bison extension, additional arguments required by @code{%pure-parser},
|
||||||
|
@code{%locations}, @code{%lex-param} and @code{%parse-param} are taken into
|
||||||
|
account. You may disable @code{yyerror}'s prototype with @samp{#define
|
||||||
|
yyerror yyerror} (as specified by POSIX), or with @samp{#define
|
||||||
|
YYERROR_IS_DECLARED} (a Bison extension). Likewise for @code{yylex}.
|
||||||
|
@item
|
||||||
|
Imitate Yacc's output file name conventions, so that the parser
|
||||||
|
implementation file is called @file{y.tab.c}, and the other outputs are
|
||||||
|
called @file{y.output} and @file{y.tab.h}. Do not use @option{--yacc} just
|
||||||
|
to change the output file names since it also triggers all the
|
||||||
|
aforementioned behavior changes; rather use @samp{-o y.tab.c}.
|
||||||
|
@end itemize
|
||||||
|
|
||||||
The @option{-y}/@option{--yacc} option is intended for use with traditional
|
The @option{-y}/@option{--yacc} option is intended for use with traditional
|
||||||
Yacc grammars. This option only makes sense for the default C skeleton,
|
Yacc grammars. This option only makes sense for the default C skeleton,
|
||||||
@file{yacc.c}. If your grammar uses Bison extensions Bison cannot be
|
@file{yacc.c}. If your grammar uses Bison extensions Bison cannot be
|
||||||
Yacc-compatible, even if this option is specified.
|
Yacc-compatible, even if this option is specified.
|
||||||
|
|
||||||
|
Thus, the following shell script can substitute for Yacc, and the Bison
|
||||||
|
distribution contains such a @command{yacc} script for compatibility with
|
||||||
|
POSIX:
|
||||||
|
|
||||||
|
@example
|
||||||
|
#! /bin/sh
|
||||||
|
bison -y "$@@"
|
||||||
|
@end example
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@node Output Files
|
@node Output Files
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ synonyms.
|
|||||||
- report: for automaton dumps
|
- report: for automaton dumps
|
||||||
- %union
|
- %union
|
||||||
- variant
|
- variant
|
||||||
|
- yacc: POSIX yacc (%yacc)
|
||||||
|
|
||||||
# Calculator
|
# Calculator
|
||||||
The grammar features several special directives:
|
The grammar features several special directives:
|
||||||
|
|||||||
@@ -275,6 +275,8 @@ m4_pushdef([AT_MULTISTART_IF],
|
|||||||
[m4_bmatch([$3], [%start [_a-zA-Z]+ [_a-zA-Z]+], [$1], [$2])])
|
[m4_bmatch([$3], [%start [_a-zA-Z]+ [_a-zA-Z]+], [$1], [$2])])
|
||||||
m4_pushdef([AT_PARAM_IF],
|
m4_pushdef([AT_PARAM_IF],
|
||||||
[m4_bmatch([$3], [%parse-param], [$1], [$2])])
|
[m4_bmatch([$3], [%parse-param], [$1], [$2])])
|
||||||
|
m4_pushdef([AT_YACC_IF],
|
||||||
|
[m4_bmatch([$3], [%yacc], [$1], [$2])])
|
||||||
|
|
||||||
# Comma-terminated list of formals parse-parameters.
|
# Comma-terminated list of formals parse-parameters.
|
||||||
# E.g., %parse-param { int x } %parse-param {int y} -> "int x, int y, ".
|
# E.g., %parse-param { int x } %parse-param {int y} -> "int x, int y, ".
|
||||||
@@ -427,6 +429,7 @@ AT_LOCATION_TYPE_SPAN_IF(
|
|||||||
AT_GLR_IF([AT_KEYWORDS([glr])])
|
AT_GLR_IF([AT_KEYWORDS([glr])])
|
||||||
AT_MULTISTART_IF([AT_KEYWORDS([multistart])])
|
AT_MULTISTART_IF([AT_KEYWORDS([multistart])])
|
||||||
AT_PUSH_IF([AT_KEYWORDS([push])])
|
AT_PUSH_IF([AT_KEYWORDS([push])])
|
||||||
|
AT_YACC_IF([AT_KEYWORDS([yacc])])
|
||||||
])# _AT_BISON_OPTION_PUSHDEFS
|
])# _AT_BISON_OPTION_PUSHDEFS
|
||||||
|
|
||||||
|
|
||||||
@@ -466,6 +469,7 @@ m4_popdef([AT_VALUE_UNION_IF])
|
|||||||
m4_popdef([AT_PUSH_IF])
|
m4_popdef([AT_PUSH_IF])
|
||||||
m4_popdef([AT_PURE_IF])
|
m4_popdef([AT_PURE_IF])
|
||||||
m4_popdef([AT_PARSER_CLASS])
|
m4_popdef([AT_PARSER_CLASS])
|
||||||
|
m4_popdef([AT_YACC_IF])
|
||||||
m4_popdef([AT_PARAM_IF])
|
m4_popdef([AT_PARAM_IF])
|
||||||
m4_popdef([AT_MULTISTART_IF])
|
m4_popdef([AT_MULTISTART_IF])
|
||||||
m4_popdef([AT_LEXPARAM_IF])
|
m4_popdef([AT_LEXPARAM_IF])
|
||||||
@@ -683,7 +687,7 @@ m4_define([AT_YYERROR_DECLARE_EXTERN(c)],
|
|||||||
m4_define([AT_YYERROR_DECLARE(c)],
|
m4_define([AT_YYERROR_DECLARE(c)],
|
||||||
[[#include <stdio.h>
|
[[#include <stdio.h>
|
||||||
]AT_LOCATION_PRINT_DECLARE[
|
]AT_LOCATION_PRINT_DECLARE[
|
||||||
static ]AT_YYERROR_DECLARE_EXTERN])
|
]AT_YACC_IF([], [[static ]AT_YYERROR_DECLARE_EXTERN])])
|
||||||
|
|
||||||
|
|
||||||
# "%define parse.error custom" uses a different format, easy to check.
|
# "%define parse.error custom" uses a different format, easy to check.
|
||||||
@@ -729,7 +733,7 @@ yyreport_syntax_error (const yypcontext_t *ctx]AT_PARAM_IF([, AT_PARSE_PARAMS])[
|
|||||||
]])[
|
]])[
|
||||||
|
|
||||||
/* A C error reporting function. */
|
/* A C error reporting function. */
|
||||||
static
|
]AT_YACC_IF([], [static])[
|
||||||
]AT_YYERROR_PROTOTYPE[
|
]AT_YYERROR_PROTOTYPE[
|
||||||
{]m4_bpatsubst(m4_defn([AT_PARSE_PARAMS]),
|
{]m4_bpatsubst(m4_defn([AT_PARSE_PARAMS]),
|
||||||
[[^,]+[^A-Za-z_0-9]\([A-Za-z_][A-Za-z_0-9]*\),* *], [
|
[[^,]+[^A-Za-z_0-9]\([A-Za-z_][A-Za-z_0-9]*\),* *], [
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ AT_SETUP([Early token definitions with --yacc])
|
|||||||
# Found in GCJ: they expect the tokens to be defined before the user
|
# Found in GCJ: they expect the tokens to be defined before the user
|
||||||
# prologue, so that they can use the token definitions in it.
|
# prologue, so that they can use the token definitions in it.
|
||||||
|
|
||||||
AT_BISON_OPTION_PUSHDEFS
|
AT_BISON_OPTION_PUSHDEFS([%yacc])
|
||||||
|
|
||||||
# Not AT_DATA_GRAMMAR, which uses %code, which is not supported by Yacc.
|
# Not AT_DATA_GRAMMAR, which uses %code, which is not supported by Yacc.
|
||||||
AT_DATA([input.y],
|
AT_DATA([input.y],
|
||||||
@@ -112,7 +112,7 @@ exp: MY_TOKEN;
|
|||||||
]])
|
]])
|
||||||
AT_BISON_OPTION_POPDEFS
|
AT_BISON_OPTION_POPDEFS
|
||||||
|
|
||||||
AT_BISON_CHECK([-y -o input.c input.y])
|
AT_BISON_CHECK([--yacc -o input.c input.y])
|
||||||
AT_COMPILE([input.o])
|
AT_COMPILE([input.o])
|
||||||
|
|
||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|||||||
Reference in New Issue
Block a user