summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkim Demaille <akim.demaille@gmail.com>2021-08-05 08:39:24 +0200
committerAkim Demaille <akim.demaille@gmail.com>2021-08-09 07:17:19 +0200
commit3c5f73fe51a6d61e6a2f6219a9320bf4fd32ae66 (patch)
treed6f625d49abe74ba2ba2036f756dbf8e3bc8d21b
parentdabde7c560f249f30e47a1fce7cf29891023f3fc (diff)
downloadbison-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--NEWS8
-rw-r--r--TODO4
-rw-r--r--data/skeletons/c.m412
-rw-r--r--data/skeletons/yacc.c29
-rw-r--r--doc/bison.texi59
-rw-r--r--tests/README.md1
-rw-r--r--tests/local.at8
-rw-r--r--tests/regression.at4
8 files changed, 95 insertions, 30 deletions
diff --git a/NEWS b/NEWS
index 8cecaf68..a908bdb0 100644
--- a/NEWS
+++ b/NEWS
@@ -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
diff --git a/TODO b/TODO
index 150d4072..b4557991 100644
--- a/TODO
+++ b/TODO
@@ -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