[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: yacc.c does not prototype yyparse in the header
From: |
Akim Demaille |
Subject: |
Re: yacc.c does not prototype yyparse in the header |
Date: |
Mon, 2 Jul 2012 10:02:07 +0200 |
Le 29 juin 2012 à 17:42, Akim Demaille a écrit :
> This is a more mature patch, with the documentation.
> It's in the api.prefix branch.
I installed it.
From 4b3847c3c0e161b85267d077adb256a880c0f3e3 Mon Sep 17 00:00:00 2001
From: Akim Demaille <address@hidden>
Date: Tue, 26 Jun 2012 10:09:10 +0200
Subject: [PATCH] api.prefix.
* data/c.m4 (b4_api_prefix, b4_api_PREFIX): New.
(b4_prefix, b4_union_name, b4_token_enums, b4_declare_yylstype): Use them.
* data/glr.c, data/yacc.c, data/glr.cc, data/lalr1.cc: Use them to change
the prefix of exported preprocessor symbols.
* src/getargs.c (usage): Ditto.
* tests/headers.at (Several parsers): New.
* tests/local.at (AT_API_PREFIX): New.
AT_YYSTYPE, AT_YYLTYPE): Adjust.
* doc/bison.texi (Multiple Parsers): Move documentation of %name-prefix to...
(Table of Symbols): here.
(Multiple Parsers): Document api.prefix.
(%define Summary): Point to it.
Use @code for variable names.
(Bison Options): -p/--name-prefix are obsoleted.
* NEWS: Announce api.prefix.
---
NEWS | 54 +++++++++++++++++++
data/c.m4 | 65 +++++++++++++----------
data/glr.c | 8 +++
data/glr.cc | 14 ++---
data/lalr1.cc | 12 ++---
data/yacc.c | 10 +++-
doc/bison.texi | 155 ++++++++++++++++++++++++++++++++++++-------------------
src/getargs.c | 7 +--
tests/headers.at | 90 ++++++++++++++++++++++++++++++++
tests/local.at | 7 ++-
10 files changed, 323 insertions(+), 99 deletions(-)
diff --git a/NEWS b/NEWS
index 33fac14..371b933 100644
--- a/NEWS
+++ b/NEWS
@@ -70,6 +70,60 @@ GNU Bison NEWS
For the same reasons, the undocumented and unused macro YYLSP_NEEDED is no
longer defined.
+** New %define variable: api.prefix
+
+ Now that the generated headers are more complete and properly protected
+ against multiple inclusions, constant names, such as YYSTYPE are a
+ problem. While yyparse and others are properly renamed by %name-prefix,
+ YYSTYPE, YYDEBUG and others have never been affected by it. Because it
+ would introduce backward compatibility issues in projects not expecting
+ YYSTYPE to be renamed, instead of changing the behavior of %name-prefix,
+ it is deprecated in favor of a new %define variable: api.prefix.
+
+ The following examples compares both:
+
+ %name-prefix "bar_" | %define api.prefix "bar_"
+ %token <ival> FOO %token <ival> FOO
+ %union { int ival; } %union { int ival; }
+ %% %%
+ exp: 'a'; exp: 'a';
+
+ bison generates:
+
+ #ifndef BAR_FOO_H #ifndef BAR_FOO_H
+ # define BAR_FOO_H # define BAR_FOO_H
+
+ /* Enabling traces. */ /* Enabling traces. */
+ # ifndef YYDEBUG # ifndef YYDEBUG
+ # define YYDEBUG 0 # define YYDEBUG 0
+ # endif # endif
+ # if YYDEBUG # if YYDEBUG
+ extern int bar_debug; extern int bar_debug;
+ # endif # endif
+
+ /* Tokens. */ /* Tokens. */
+ # ifndef YYTOKENTYPE | # ifndef BAR_TOKENTYPE
+ # define YYTOKENTYPE | # define BAR_TOKENTYPE
+ enum yytokentype { | enum bar_tokentype {
+ FOO = 258 FOO = 258
+ }; };
+ # endif # endif
+
+ #if ! defined YYSTYPE \ | #if ! defined BAR_STYPE \
+ && ! defined YYSTYPE_IS_DECLARED | && ! defined BAR_STYPE_IS_DECLARED
+ typedef union YYSTYPE | typedef union BAR_STYPE
+ { {
+ int ival; int ival;
+ } YYSTYPE; | } BAR_STYPE;
+ # define YYSTYPE_IS_DECLARED 1 | # define BAR_STYPE_IS_DECLARED 1
+ #endif #endif
+
+ extern YYSTYPE bar_lval; | extern BAR_STYPE bar_lval;
+
+ int bar_parse (void); int bar_parse (void);
+
+ #endif /* !BAR_FOO_H */ #endif /* !BAR_FOO_H */
+
* Noteworthy changes in release 2.5.1 (2012-06-05) [stable]
** Future changes:
diff --git a/data/c.m4 b/data/c.m4
index 1f266a4..0b2699a 100644
--- a/data/c.m4
+++ b/data/c.m4
@@ -84,11 +84,24 @@ m4_define([b4_identification],
## Default values. ##
## ---------------- ##
+# b4_api_prefix, b4_api_PREFIX
+# ----------------------------
+# Corresponds to %define api.prefix
+b4_percent_define_default([[api.prefix]], [[yy]])
+m4_define([b4_api_prefix],
+[b4_percent_define_get([[api.prefix]])])
+m4_define([b4_api_PREFIX],
+[m4_toupper(b4_api_prefix)])
+
+
+# b4_prefix
+# ---------
+# If the %name-prefix is not given, it is api.prefix.
+m4_define_default([b4_prefix], [b4_api_prefix])
+
# If the %union is not named, its name is YYSTYPE.
-m4_define_default([b4_union_name], [YYSTYPE])
+m4_define_default([b4_union_name], [b4_api_PREFIX[]STYPE])
-# If the %name-prefix is not given, it is yy.
-m4_define_default([b4_prefix], [yy])
## ------------------------ ##
## Pure/impure interfaces. ##
@@ -232,18 +245,18 @@ m4_define([b4_token_enum],
# Output the definition of the tokens (if there are) as enums.
m4_define([b4_token_enums],
[m4_if([$#$1], [1], [],
-[/* Tokens. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
+[[/* Tokens. */
+#ifndef ]b4_api_PREFIX[TOKENTYPE
+# define ]b4_api_PREFIX[TOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
- enum yytokentype {
-m4_map_sep([ b4_token_enum], [,
+ enum ]b4_api_prefix[tokentype {
+]m4_map_sep([ b4_token_enum], [,
],
- address@hidden)
+ address@hidden)[
};
#endif
-])])
+]])])
# b4_token_enums_defines(LIST-OF-PAIRS-TOKEN-NAME-TOKEN-NUMBER)
@@ -533,39 +546,39 @@ b4_locations_if([, yylocationp])[]b4_user_args[);
## -------------- ##
# b4_declare_yylstype
-# ------------------
+# -------------------
# Declarations that might either go into the header (if --defines) or
# in the parser body. Declare YYSTYPE/YYLTYPE, and yylval/yylloc.
m4_define([b4_declare_yylstype],
-[[#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+[[#if ! defined ]b4_api_PREFIX[STYPE && ! defined
]b4_api_PREFIX[STYPE_IS_DECLARED
]m4_ifdef([b4_stype],
[[typedef union ]b4_union_name[
{
]b4_user_stype[
-} YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1]],
+} ]b4_api_PREFIX[STYPE;
+# define ]b4_api_PREFIX[STYPE_IS_TRIVIAL 1]],
[m4_if(b4_tag_seen_flag, 0,
-[[typedef int YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1]])])[
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
+[[typedef int ]b4_api_PREFIX[STYPE;
+# define ]b4_api_PREFIX[STYPE_IS_TRIVIAL 1]])])[
+# define ]b4_api_prefix[stype ]b4_api_PREFIX[STYPE /* obsolescent; will be
withdrawn */
+# define ]b4_api_PREFIX[STYPE_IS_DECLARED 1
#endif]b4_locations_if([[
-#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
-typedef struct YYLTYPE
+#if ! defined ]b4_api_PREFIX[LTYPE && ! defined
]b4_api_PREFIX[LTYPE_IS_DECLARED
+typedef struct ]b4_api_PREFIX[LTYPE
{
int first_line;
int first_column;
int last_line;
int last_column;
-} YYLTYPE;
-# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
-# define YYLTYPE_IS_DECLARED 1
-# define YYLTYPE_IS_TRIVIAL 1
+} ]b4_api_PREFIX[LTYPE;
+# define ]b4_api_prefix[ltype ]b4_api_PREFIX[LTYPE /* obsolescent; will be
withdrawn */
+# define ]b4_api_PREFIX[LTYPE_IS_DECLARED 1
+# define ]b4_api_PREFIX[LTYPE_IS_TRIVIAL 1
#endif]])
-b4_pure_if([], [[extern YYSTYPE ]b4_prefix[lval;
-]b4_locations_if([[extern YYLTYPE ]b4_prefix[lloc;]])])[]dnl
+b4_pure_if([], [[extern ]b4_api_PREFIX[STYPE ]b4_prefix[lval;
+]b4_locations_if([[extern ]b4_api_PREFIX[LTYPE ]b4_prefix[lloc;]])])[]dnl
])
# b4_declare_yydebug
diff --git a/data/glr.c b/data/glr.c
index 699d730..ce61160 100644
--- a/data/glr.c
+++ b/data/glr.c
@@ -188,6 +188,14 @@ b4_copyright([Skeleton implementation for Bison GLR
parsers in C],
]b4_identification
b4_percent_code_get([[top]])[
+]m4_if(b4_api_prefix, [yy], [],
+[[/* Substitute the type names. */
+#define YYSTYPE ]b4_api_PREFIX[STYPE
+#define YYSTYPE_IS_TRIVIAL ]b4_api_PREFIX[STYPE_IS_TRIVIAL
+#define YYSTYPE_IS_DECLARED
]b4_api_PREFIX[STYPE_IS_DECLARED]b4_locations_if([[
+#define YYLTYPE ]b4_api_PREFIX[LTYPE
+#define YYLTYPE_IS_TRIVIAL ]b4_api_PREFIX[LTYPE_IS_TRIVIAL
+#define YYLTYPE_IS_DECLARED ]b4_api_PREFIX[LTYPE_IS_DECLARED]])])[
]m4_if(b4_prefix, [yy], [],
[[/* Substitute the variable and function names. */
#define yyparse ]b4_prefix[parse
diff --git a/data/glr.cc b/data/glr.cc
index 8e46be3..d1eb6bd 100644
--- a/data/glr.cc
+++ b/data/glr.cc
@@ -269,7 +269,7 @@ b4_copyright([Skeleton interface for Bison GLR parsers in
C++],
{
public:
/// Symbol semantic values.
-#ifndef YYSTYPE
+#ifndef ]b4_api_PREFIX[STYPE
]m4_ifdef([b4_stype],
[ union semantic_type
{
@@ -277,9 +277,9 @@ b4_user_stype
};],
[m4_if(b4_tag_seen_flag, 0,
[[ typedef int semantic_type;]],
-[[ typedef YYSTYPE semantic_type;]])])[
+[[ typedef ]b4_api_PREFIX[STYPE semantic_type;]])])[
#else
- typedef YYSTYPE semantic_type;
+ typedef ]b4_api_PREFIX[STYPE semantic_type;
#endif
/// Symbol locations.
typedef ]b4_percent_define_get([[location_type]],
@@ -350,11 +350,11 @@ b4_user_stype
b4_percent_define_flag_if([[global_tokens_and_yystype]],
[b4_token_defines(b4_tokens)])
[
-#ifndef YYSTYPE
-# define YYSTYPE ]b4_namespace_ref[::]b4_parser_class_name[::semantic_type
+#ifndef ]b4_api_PREFIX[STYPE
+# define ]b4_api_PREFIX[STYPE
]b4_namespace_ref[::]b4_parser_class_name[::semantic_type
#endif
-#ifndef YYLTYPE
-# define YYLTYPE ]b4_namespace_ref[::]b4_parser_class_name[::location_type
+#ifndef ]b4_api_PREFIX[LTYPE
+# define ]b4_api_PREFIX[LTYPE
]b4_namespace_ref[::]b4_parser_class_name[::location_type
#endif
]b4_namespace_close[
diff --git a/data/lalr1.cc b/data/lalr1.cc
index e82e654..337af10 100644
--- a/data/lalr1.cc
+++ b/data/lalr1.cc
@@ -69,7 +69,7 @@ b4_copyright([Skeleton interface for Bison LALR(1) parsers in
C++],
{
public:
/// Symbol semantic values.
-#ifndef YYSTYPE
+#ifndef ]b4_api_PREFIX[STYPE
]m4_ifdef([b4_stype],
[ union semantic_type
{
@@ -77,9 +77,9 @@ b4_user_stype
};],
[m4_if(b4_tag_seen_flag, 0,
[[ typedef int semantic_type;]],
-[[ typedef YYSTYPE semantic_type;]])])[
+[[ typedef ]b4_api_PREFIX[STYPE semantic_type;]])])[
#else
- typedef YYSTYPE semantic_type;
+ typedef ]b4_api_PREFIX[STYPE semantic_type;
#endif
/// Symbol locations.
typedef ]b4_percent_define_get([[location_type]],
@@ -262,9 +262,9 @@ b4_user_stype
]b4_percent_define_flag_if([[global_tokens_and_yystype]],
[b4_token_defines(b4_tokens)
-#ifndef YYSTYPE
+#ifndef ]b4_api_PREFIX[STYPE
/* Redirection for backward compatibility. */
-# define YYSTYPE b4_namespace_ref::b4_parser_class_name::semantic_type
+# define ]b4_api_PREFIX[STYPE
b4_namespace_ref::b4_parser_class_name::semantic_type
#endif
])[
]b4_percent_code_get([[provides]])[
@@ -597,7 +597,7 @@ m4_popdef([b4_at_dollar])])dnl
{
YYCDEBUG << "Reading a token: ";
yychar = ]b4_c_function_call([yylex], [int],
- [[YYSTYPE*], [&yylval]][]dnl
+ [b4_api_PREFIX[STYPE*], [&yylval]][]dnl
b4_locations_if([, [[location*], [&yylloc]]])dnl
m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
}
diff --git a/data/yacc.c b/data/yacc.c
index 7cf088b..8c595f9 100644
--- a/data/yacc.c
+++ b/data/yacc.c
@@ -307,7 +307,15 @@ b4_copyright([Bison implementation for Yacc-like parsers
in C],
]b4_identification
b4_percent_code_get([[top]])[]dnl
-m4_if(b4_prefix, [yy], [],
+m4_if(b4_api_prefix, [yy], [],
+[[/* Substitute the type names. */
+#define YYSTYPE ]b4_api_PREFIX[STYPE
+#define YYSTYPE_IS_TRIVIAL ]b4_api_PREFIX[STYPE_IS_TRIVIAL
+#define YYSTYPE_IS_DECLARED
]b4_api_PREFIX[STYPE_IS_DECLARED]b4_locations_if([[
+#define YYLTYPE ]b4_api_PREFIX[LTYPE
+#define YYLTYPE_IS_TRIVIAL ]b4_api_PREFIX[LTYPE_IS_TRIVIAL
+#define YYLTYPE_IS_DECLARED ]b4_api_PREFIX[LTYPE_IS_DECLARED]])])[
+]m4_if(b4_prefix, [yy], [],
[[/* Substitute the variable and function names. */]b4_pull_if([[
#define yyparse ]b4_prefix[parse]])b4_push_if([[
#define yypush_parse ]b4_prefix[push_parse]b4_pull_if([[
diff --git a/doc/bison.texi b/doc/bison.texi
index b163166..fbe780c 100644
--- a/doc/bison.texi
+++ b/doc/bison.texi
@@ -5154,22 +5154,6 @@ grammar does not use it, using @samp{%locations} allows
for more
accurate syntax error messages.
@end deffn
address@hidden {Directive} %name-prefix "@var{prefix}"
-Rename the external symbols used in the parser so that they start with
address@hidden instead of @samp{yy}. The precise list of symbols renamed
-in C parsers
-is @code{yyparse}, @code{yylex}, @code{yyerror}, @code{yynerrs},
address@hidden, @code{yychar}, @code{yydebug}, and
-(if locations are used) @code{yylloc}. If you use a push parser,
address@hidden, @code{yypull_parse}, @code{yypstate},
address@hidden and @code{yypstate_delete} will
-also be renamed. For example, if you use @samp{%name-prefix "c_"}, the
-names become @code{c_parse}, @code{c_lex}, and so on.
-For C++ parsers, see the @code{%define namespace} documentation in this
-section.
address@hidden Parsers, ,Multiple Parsers in the Same Program}.
address@hidden deffn
-
@ifset defaultprec
@deffn {Directive} %no-default-prec
Do not assign a precedence to rules lacking an explicit @code{%prec}
@@ -5317,8 +5301,23 @@ Unaccepted @var{variable}s produce an error.
Some of the accepted @var{variable}s are:
@itemize @bullet
address@hidden ================================================== api.prefix
address@hidden @code{api.prefix}
address@hidden %define api.prefix
+
address@hidden @bullet
address@hidden Language(s): All
+
address@hidden Purpose: Rename exported symbols
address@hidden Parsers, ,Multiple Parsers in the Same Program}.
+
address@hidden Accepted Values: String
+
address@hidden Default Value: @code{yy}
address@hidden itemize
+
@c ================================================== api.pure
address@hidden api.pure
address@hidden @code{api.pure}
@findex %define api.pure
@itemize @bullet
@@ -5332,7 +5331,9 @@ Some of the accepted @var{variable}s are:
@item Default Value: @code{false}
@end itemize
address@hidden api.push-pull
address@hidden ================================================== api.push-pull
+
address@hidden @code{api.push-pull}
@findex %define api.push-pull
@itemize @bullet
@@ -5350,7 +5351,7 @@ More user feedback will help to stabilize it.)
@c ================================================== lr.default-reductions
address@hidden lr.default-reductions
address@hidden @code{lr.default-reductions}
@findex %define lr.default-reductions
@itemize @bullet
@@ -5371,7 +5372,7 @@ feedback will help to stabilize it.)
@c ============================================ lr.keep-unreachable-states
address@hidden lr.keep-unreachable-states
address@hidden @code{lr.keep-unreachable-states}
@findex %define lr.keep-unreachable-states
@itemize @bullet
@@ -5384,7 +5385,7 @@ remain in the parser tables. @xref{Unreachable States}.
@c ================================================== lr.type
address@hidden lr.type
address@hidden @code{lr.type}
@findex %define lr.type
@itemize @bullet
@@ -5399,7 +5400,9 @@ More user feedback will help to stabilize it.)
@item Default Value: @code{lalr}
@end itemize
address@hidden namespace
address@hidden ================================================== namespace
+
address@hidden @code{namespace}
@findex %define namespace
@itemize
@@ -5452,7 +5455,7 @@ The parser namespace is @code{foo} and @code{yylex} is
referenced as
@end itemize
@c ================================================== parse.lac
address@hidden parse.lac
address@hidden @code{parse.lac}
@findex %define parse.lac
@itemize
@@ -5585,34 +5588,62 @@ of the standard Bison skeletons.
@section Multiple Parsers in the Same Program
Most programs that use Bison parse only one language and therefore contain
-only one Bison parser. But what if you want to parse more than one
-language with the same program? Then you need to avoid a name conflict
-between different definitions of @code{yyparse}, @code{yylval}, and so on.
-
-The easy way to do this is to use the option @samp{-p @var{prefix}}
-(@pxref{Invocation, ,Invoking Bison}). This renames the interface
-functions and variables of the Bison parser to start with @var{prefix}
-instead of @samp{yy}. You can use this to give each parser distinct
-names that do not conflict.
-
-The precise list of symbols renamed is @code{yyparse}, @code{yylex},
address@hidden, @code{yynerrs}, @code{yylval}, @code{yylloc},
address@hidden and @code{yydebug}. If you use a push parser,
address@hidden, @code{yypull_parse}, @code{yypstate},
address@hidden and @code{yypstate_delete} will also be renamed.
-For example, if you use @samp{-p c}, the names become @code{cparse},
address@hidden, and so on.
-
address@hidden the other variables and macros associated with Bison are not
-renamed.} These others are not global; there is no conflict if the same
-name is used in different parsers. For example, @code{YYSTYPE} is not
-renamed, but defining this in different ways in different parsers causes
-no trouble (@pxref{Value Type, ,Data Types of Semantic Values}).
-
-The @samp{-p} option works by adding macro definitions to the
-beginning of the parser implementation file, defining @code{yyparse}
-as @address@hidden, and so on. This effectively substitutes
-one name for the other in the entire parser implementation file.
+only one Bison parser. But what if you want to parse more than one language
+with the same program? Then you need to avoid name conflicts between
+different definitions of functions and variables such as @code{yyparse},
address@hidden To use different parsers from the same compilation unit, you
+also need to avoid conflicts on types and macros (e.g., @code{YYSTYPE})
+exported in the generated header.
+
+The easy way to do this is to define the @code{%define} variable
address@hidden (possibly using the option
address@hidden@var{prefix}}, see @ref{Invocation, ,Invoking Bison}).
+This renames the interface functions and variables of the Bison parser to
+start with @var{prefix} instead of @samp{yy}, and all the macros to start by
address@hidden (i.e., @var{prefix} upper cased) instead of @samp{YY}. You can
+use this to give each parser distinct names that do not conflict.
+
+The renamed symbols include @code{yyparse}, @code{yylex}, @code{yyerror},
address@hidden, @code{yylval}, @code{yylloc}, @code{yychar} and
address@hidden If you use a push parser, @code{yypush_parse},
address@hidden, @code{yypstate}, @code{yypstate_new} and
address@hidden will also be renamed. The renamed macros include
address@hidden, @code{YYSTYPE_IS_TRIVIAL}, @code{YYSTYPE_IS_DECLARED},
address@hidden, @code{YYLTYPE_IS_TRIVIAL}, and @code{YYLTYPE_IS_DECLARED}.
+
+For example, if you use @samp{%define api.prefix c}, the names become
address@hidden, @code{clex}, @dots{}, @code{CSTYPE}, @code{CLTYPE}, and so
+on.
+
+The @code{%define} variable @code{api.prefix} works in two different ways.
+In the implementation file, it works by adding macro definitions to the
+beginning of the parser implementation file, defining @code{yyparse} as
address@hidden@var{prefix}parse}, and so on:
+
address@hidden
+#define YYSTYPE CTYPE
+#define yyparse cparse
+#define yylval clval
+...
+YYSTYPE yylval;
+int yyparse (void);
address@hidden example
+
+This effectively substitutes one name for the other in the entire parser
+implementation file, thus the ``original'' names (@code{yylex},
address@hidden, @dots{}) are also usable in the parser implementation file.
+
+However, in the parser header file, the symbols are defined renamed, for
+instance:
+
address@hidden
+extern CSTYPE clval;
+int cparse (void);
address@hidden example
+
+Previously, a similar feature was provided by the obsoleted directive
address@hidden (@pxref{Table of Symbols, ,Bison Symbols}) and option
address@hidden (@pxref{Bison Options}).
@node Interface
@chapter Parser C-Language Interface
@@ -8924,8 +8955,9 @@ Pretend that @code{%locations} was specified. @xref{Decl
Summary}.
@item -p @var{prefix}
@itemx address@hidden
-Pretend that @code{%name-prefix "@var{prefix}"} was specified.
address@hidden Summary}.
+Pretend that @code{%name-prefix "@var{prefix}"} was specified (@pxref{Decl
+Summary}). Obsoleted by @address@hidden @xref{Multiple
+Parsers, ,Multiple Parsers in the Same Program}.
@item -l
@itemx --no-lines
@@ -11054,9 +11086,24 @@ function is applied to the two semantic values to get
a single result.
@end deffn
@deffn {Directive} %name-prefix "@var{prefix}"
-Bison declaration to rename the external symbols. @xref{Decl Summary}.
+Obsoleted by the @code{%define} variable @code{api.prefix} (@pxref{Multiple
+Parsers, ,Multiple Parsers in the Same Program}).
+
+Rename the external symbols (variables and functions) used in the parser so
+that they start with @var{prefix} instead of @samp{yy}. Contrary to
address@hidden, do no rename types and macros.
+
+The precise list of symbols renamed in C parsers is @code{yyparse},
address@hidden, @code{yyerror}, @code{yynerrs}, @code{yylval}, @code{yychar},
address@hidden, and (if locations are used) @code{yylloc}. If you use a
+push parser, @code{yypush_parse}, @code{yypull_parse}, @code{yypstate},
address@hidden and @code{yypstate_delete} will also be renamed. For
+example, if you use @samp{%name-prefix "c_"}, the names become
address@hidden, @code{c_lex}, and so on. For C++ parsers, see the
address@hidden namespace} documentation in this section.
@end deffn
+
@ifset defaultprec
@deffn {Directive} %no-default-prec
Do not assign a precedence to rules that lack an explicit @samp{%prec}
diff --git a/src/getargs.c b/src/getargs.c
index 3fa2a7a..599cbba 100644
--- a/src/getargs.c
+++ b/src/getargs.c
@@ -311,10 +311,11 @@ Parser:\n\
-S, --skeleton=FILE specify the skeleton to use\n\
-t, --debug instrument the parser for debugging\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\
+ -D, --define=NAME[=VALUE] similar to '%define NAME \"VALUE\"'\n\
+ -F, --force-define=NAME[=VALUE] override '%define NAME \"VALUE\"'\n\
-p, --name-prefix=PREFIX prepend PREFIX to the external symbols\n\
- -l, --no-lines don't generate `#line' directives\n\
+ deprecated by '-Dapi.prefix=PREFIX'\n\
+ -l, --no-lines don't generate '#line' directives\n\
-k, --token-table include a table of token names\n\
\n\
"), stdout);
diff --git a/tests/headers.at b/tests/headers.at
index 549d62d..970d3f1 100644
--- a/tests/headers.at
+++ b/tests/headers.at
@@ -117,3 +117,93 @@ AT_COMPILE([caller], [caller.o input.o])
AT_PARSER_CHECK([./caller])
AT_CLEANUP
+
+## ----------------- ##
+## Several parsers. ##
+## ----------------- ##
+
+AT_SETUP([Several parsers])
+
+# AT_DATA_GRAMMAR_SEVERAL([PREFIX], [DIRECTIVES])
+# -----------------------------------------------
+# Generate and compile to *.o. Make sure there is no YY* nor yy* in
+# the header (but YYDEBUG and YYPARSE_PARAM).
+m4_define([AT_DATA_GRAMMAR_SEVERAL],
+[AT_BISON_OPTION_PUSHDEFS([%define api.prefix "$1_" $2])
+AT_DATA_GRAMMAR([AT_SKEL_CC_IF([$1.yy], [$1.y])],
+[[%define api.prefix "$1_"
+$2
+%union
+{
+ int integer;
+}
+%{
+#include <stdio.h>
+ ]AT_YYERROR_DECLARE[
+ ]AT_YYLEX_DECLARE[
+%}
+%%
+exp:
+ 'x' '1' { printf ("x1\n"); }
+| 'x' '2' { printf ("x2\n"); }
+| 'x' '3' { printf ("x3\n"); }
+| 'x' '4' { printf ("x4\n"); }
+| 'x' '5' { printf ("x5\n"); }
+| 'x' '6' { printf ("x6\n"); }
+;
+
+%%
+]AT_YYERROR_DEFINE[
+]AT_YYLEX_DEFINE(["$1"])[
+]])
+
+AT_BISON_CHECK([-d -o AT_SKEL_CC_IF([$1.cc $1.yy], [$1.c $1.y])])
+# C++ output relies on namespaces and still uses yy a lot.
+AT_SKEL_CC_IF([],
+ [AT_CHECK([$EGREP -i yy $1.h | $EGREP -v 'YY(DEBUG|PARSE_PARAM)'], [1])])
+AT_LANG_COMPILE([$1.o])
+AT_BISON_OPTION_POPDEFS
+])
+
+AT_DATA([main.cc],
+[[extern "C"
+{
+ #include "x1.h"
+ #include "x2.h"
+ #include "x3.h"
+ #include "x4.h"
+}
+#include "x5.hh"
+//#include "x6.hh"
+int
+main (void)
+{
+ int errs = 0;
+ errs += x1_parse();
+ errs += x2_parse();
+ errs += x3_parse();
+ errs += x4_parse();
+ x5_::parser p5;
+ errs += p5.parse();
+// errs += x6_parse();
+ return !!errs;
+}
+]])
+
+AT_DATA_GRAMMAR_SEVERAL([x1], [])
+AT_DATA_GRAMMAR_SEVERAL([x2], [%locations %debug])
+AT_DATA_GRAMMAR_SEVERAL([x3], [%glr-parser])
+AT_DATA_GRAMMAR_SEVERAL([x4], [%locations %debug %glr-parser])
+AT_DATA_GRAMMAR_SEVERAL([x5], [%locations %debug %language "c++"])
+#AT_DATA_GRAMMAR_SEVERAL([x6], [%locations %language "c++"])
+
+AT_COMPILE_CXX([parser], [x1.o x2.o x3.o x4.o x5.o main.cc])
+AT_CHECK([./parser], [0],
+[[x1
+x2
+x3
+x4
+x5
+]])
+
+AT_CLEANUP
diff --git a/tests/local.at b/tests/local.at
index 1baf661..7a981c6 100644
--- a/tests/local.at
+++ b/tests/local.at
@@ -145,6 +145,8 @@ m4_pushdef([AT_API_prefix],
[m4_bmatch([$3], [%define api\.prefix ".*"],
[m4_bregexp([$3], [%define api\.prefix "\([^""]*\)"], [\1])],
[yy])])
+m4_pushdef([AT_API_PREFIX],
+[m4_toupper(AT_API_prefix)])
# yyerror receives the location if %location & %pure & (%glr or %parse-param).
m4_pushdef([AT_YYERROR_ARG_LOC_IF],
[AT_GLR_OR_PARAM_IF([AT_PURE_AND_LOC_IF([$1], [$2])],
@@ -165,10 +167,10 @@ m4_pushdef([AT_PURE_LEX_IF],
m4_pushdef([AT_YYSTYPE],
[AT_SKEL_CC_IF([AT_NAME_PREFIX[::parser::semantic_type]],
- [[YYSTYPE]])])
+ [AT_API_PREFIX[STYPE]])])
m4_pushdef([AT_YYLTYPE],
[AT_SKEL_CC_IF([AT_NAME_PREFIX[::parser::location_type]],
- [[YYLTYPE]])])
+ [AT_API_PREFIX[LTYPE]])])
AT_PURE_LEX_IF(
@@ -221,6 +223,7 @@ m4_popdef([AT_LOC])
m4_popdef([AT_PURE_LEX_IF])
m4_popdef([AT_YYERROR_SEES_LOC_IF])
m4_popdef([AT_YYERROR_ARG_LOC_IF])
+m4_popdef([AT_API_PREFIX])
m4_popdef([AT_API_prefix])
m4_popdef([AT_NAME_PREFIX])
m4_popdef([AT_GLR_OR_PARAM_IF])
--
1.7.11.1
- Re: yacc.c does not prototype yyparse in the header,
Akim Demaille <=