diff options
author | Akim Demaille <akim.demaille@gmail.com> | 2021-08-05 08:39:24 +0200 |
---|---|---|
committer | Akim Demaille <akim.demaille@gmail.com> | 2021-08-09 07:17:19 +0200 |
commit | 3c5f73fe51a6d61e6a2f6219a9320bf4fd32ae66 (patch) | |
tree | d6f625d49abe74ba2ba2036f756dbf8e3bc8d21b | |
parent | dabde7c560f249f30e47a1fce7cf29891023f3fc (diff) | |
download | bison-3c5f73fe51a6d61e6a2f6219a9320bf4fd32ae66.tar.gz |
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.
-rw-r--r-- | NEWS | 8 | ||||
-rw-r--r-- | TODO | 4 | ||||
-rw-r--r-- | data/skeletons/c.m4 | 12 | ||||
-rw-r--r-- | data/skeletons/yacc.c | 29 | ||||
-rw-r--r-- | doc/bison.texi | 59 | ||||
-rw-r--r-- | tests/README.md | 1 | ||||
-rw-r--r-- | tests/local.at | 8 | ||||
-rw-r--r-- | tests/regression.at | 4 |
8 files changed, 95 insertions, 30 deletions
@@ -9,6 +9,14 @@ GNU Bison NEWS now generates a *.gv file by default, instead of *.dot. A transition 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 Support for the YYPRINT macro is removed. It worked only with yacc.c and @@ -1,8 +1,4 @@ * Soon -** POSIX updates -See the recent changes about function prototypes in POSIX Yacc. Implement -them. - ** scan-code The default case is scanning char-per-char. diff --git a/data/skeletons/c.m4 b/data/skeletons/c.m4 index a0e35ae0..2a992f51 100644 --- a/data/skeletons/c.m4 +++ b/data/skeletons/c.m4 @@ -112,8 +112,8 @@ b4_percent_define_default([[api.symbol.prefix]], [[YYSYMBOL_]]) # All the yylex formal arguments. # b4_lex_param arrives quoted twice, but we want to keep only one level. m4_define([b4_lex_formals], -[b4_pure_if([[[[YYSTYPE *yylvalp]], [[&yylval]]][]dnl -b4_locations_if([, [[YYLTYPE *yyllocp], [&yylloc]]])])dnl +[b4_pure_if([[[b4_api_PREFIX[STYPE *yylvalp]], [[&yylval]]][]dnl +b4_locations_if([, [b4_api_PREFIX[LTYPE *yyllocp], [&yylloc]]])])dnl m4_ifdef([b4_lex_param], [, ]b4_lex_param)]) @@ -662,6 +662,14 @@ m4_define([b4_formal], [$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. ## diff --git a/data/skeletons/yacc.c b/data/skeletons/yacc.c index 98671322..3fa8b14f 100644 --- a/data/skeletons/yacc.c +++ b/data/skeletons/yacc.c @@ -102,6 +102,16 @@ m4_define([b4_yyerror_arg_loc_if], [1], [m4_ifset([b4_parse_param], [$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 # --------------- # 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 # ---------------------- -# Declaration that might either go into the header (if --header) -# or open coded in the parser body. +# Declarations that might either go into the header (if --header) +# or into the implementation file. m4_define([b4_shared_declarations], [b4_cpp_guard_open([b4_spec_mapped_header_file])[ ]b4_declare_yydebug[ ]b4_percent_code_get([[requires]])[ ]b4_token_enums_defines[ ]b4_declare_yylstype[ +]b4_declare_yyerror_and_yylex[ ]b4_declare_yyparse[ ]b4_percent_code_get([[provides]])[ ]b4_cpp_guard_close([b4_spec_mapped_header_file])[]dnl diff --git a/doc/bison.texi b/doc/bison.texi index b3b69843..93c2b437 100644 --- a/doc/bison.texi +++ b/doc/bison.texi @@ -6117,11 +6117,13 @@ states and what is done for each type of lookahead token in that state. @end deffn @deffn {Directive} %yacc -Pretend the option @option{--yacc} was given, i.e., imitate Yacc, including -its naming conventions. Only makes sense with the @file{yacc.c} +Pretend the option @option{--yacc} was given +(@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. -Of course @code{%yacc} is a Bison extension@dots{} +Of course, being a Bison extension, @code{%yacc} is somewhat +self-contradictory@dots{} @end deffn @@ -11832,8 +11834,9 @@ Pretend that @code{%locations} was specified. @xref{Decl Summary}. @item -p @var{prefix} @itemx --name-prefix=@var{prefix} Pretend that @code{%name-prefix "@var{prefix}"} was specified (@pxref{Decl -Summary}). Obsoleted by @option{-Dapi.prefix=@var{prefix}}. @xref{Multiple -Parsers}. +Summary}). The option @option{-p} is specified by POSIX. When POSIX +compatibility is not a requirement, @option{-Dapi.prefix=@var{prefix}} is a +better option (@pxref{Multiple Parsers}). @item -l @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}. @item -y -@itemx --yacc -Act more like the traditional @command{yacc} command. This can cause -different diagnostics to be generated (it implies @option{-Wyacc}), and may -change behavior in other minor ways. Most importantly, 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}. Also, generate @code{#define} statements in addition to an -@code{enum} to associate token codes with token kind names. Thus, the -following shell script can substitute for Yacc, and the Bison distribution -contains such a script for compatibility with POSIX: - +@itemx @anchor{option-yacc} --yacc +Act more like the traditional @command{yacc} command: +@itemize +@item +Generate different diagnostics (it implies @option{-Wyacc}). +@item +Generate @code{#define} statements in addition to an @code{enum} to +associate token codes with token kind names. +@item +Generate prototypes for @code{yyerror} and @code{yylex} (since Bison 3.8): @example -#! /bin/sh -bison -y "$@@" +int yylex (void); +void yyerror (const char *); @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 Yacc grammars. This option only makes sense for the default C skeleton, @file{yacc.c}. If your grammar uses Bison extensions Bison cannot be 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 @node Output Files diff --git a/tests/README.md b/tests/README.md index aa409a54..a23f6b8b 100644 --- a/tests/README.md +++ b/tests/README.md @@ -27,6 +27,7 @@ synonyms. - report: for automaton dumps - %union - variant +- yacc: POSIX yacc (%yacc) # Calculator The grammar features several special directives: diff --git a/tests/local.at b/tests/local.at index 01cf5845..3cf4a49e 100644 --- a/tests/local.at +++ b/tests/local.at @@ -275,6 +275,8 @@ m4_pushdef([AT_MULTISTART_IF], [m4_bmatch([$3], [%start [_a-zA-Z]+ [_a-zA-Z]+], [$1], [$2])]) m4_pushdef([AT_PARAM_IF], [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. # 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_MULTISTART_IF([AT_KEYWORDS([multistart])]) AT_PUSH_IF([AT_KEYWORDS([push])]) +AT_YACC_IF([AT_KEYWORDS([yacc])]) ])# _AT_BISON_OPTION_PUSHDEFS @@ -466,6 +469,7 @@ m4_popdef([AT_VALUE_UNION_IF]) m4_popdef([AT_PUSH_IF]) m4_popdef([AT_PURE_IF]) m4_popdef([AT_PARSER_CLASS]) +m4_popdef([AT_YACC_IF]) m4_popdef([AT_PARAM_IF]) m4_popdef([AT_MULTISTART_IF]) m4_popdef([AT_LEXPARAM_IF]) @@ -683,7 +687,7 @@ m4_define([AT_YYERROR_DECLARE_EXTERN(c)], m4_define([AT_YYERROR_DECLARE(c)], [[#include <stdio.h> ]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. @@ -729,7 +733,7 @@ yyreport_syntax_error (const yypcontext_t *ctx]AT_PARAM_IF([, AT_PARSE_PARAMS])[ ]])[ /* A C error reporting function. */ -static +]AT_YACC_IF([], [static])[ ]AT_YYERROR_PROTOTYPE[ {]m4_bpatsubst(m4_defn([AT_PARSE_PARAMS]), [[^,]+[^A-Za-z_0-9]\([A-Za-z_][A-Za-z_0-9]*\),* *], [ diff --git a/tests/regression.at b/tests/regression.at index 73d9268a..a64da9ab 100644 --- a/tests/regression.at +++ b/tests/regression.at @@ -87,7 +87,7 @@ AT_SETUP([Early token definitions with --yacc]) # Found in GCJ: they expect the tokens to be defined before the user # 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. AT_DATA([input.y], @@ -112,7 +112,7 @@ exp: MY_TOKEN; ]]) 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_CLEANUP |