From: Akim Demaille Date: Tue, 26 Jun 2012 08:09:10 +0000 (+0200) Subject: api.prefix. X-Git-Tag: v2.6~40 X-Git-Url: https://git.saurik.com/bison.git/commitdiff_plain/4b3847c3c0e161b85267d077adb256a880c0f3e3 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. --- diff --git a/NEWS b/NEWS index 33fac145..371b9333 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 FOO %token 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 1f266a47..0b2699a1 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], [, ], - [$@]) + [$@])[ }; #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 699d7304..ce611600 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 8e46be3d..d1eb6bd2 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 e82e654f..337af10a 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 7cf088b2..8c595f9a 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 b1631665..fbe780cd 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 -@deffn {Directive} %name-prefix "@var{prefix}" -Rename the external symbols used in the parser so that they start with -@var{prefix} instead of @samp{yy}. The precise list of symbols renamed -in C parsers -is @code{yyparse}, @code{yylex}, @code{yyerror}, @code{yynerrs}, -@code{yylval}, @code{yychar}, @code{yydebug}, and -(if locations are used) @code{yylloc}. If you use a push parser, -@code{yypush_parse}, @code{yypull_parse}, @code{yypstate}, -@code{yypstate_new} 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. -@xref{Multiple Parsers, ,Multiple Parsers in the Same Program}. -@end 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 +@c ================================================== api.prefix +@item @code{api.prefix} +@findex %define api.prefix + +@itemize @bullet +@item Language(s): All + +@item Purpose: Rename exported symbols +@xref{Multiple Parsers, ,Multiple Parsers in the Same Program}. + +@item Accepted Values: String + +@item Default Value: @code{yy} +@end itemize + @c ================================================== api.pure -@item api.pure +@item @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 -@item api.push-pull +@c ================================================== api.push-pull + +@item @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 -@item lr.default-reductions +@item @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 -@item lr.keep-unreachable-states +@item @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 -@item lr.type +@item @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 -@item namespace +@c ================================================== namespace + +@item @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 -@item parse.lac +@item @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}, -@code{yyerror}, @code{yynerrs}, @code{yylval}, @code{yylloc}, -@code{yychar} and @code{yydebug}. If you use a push parser, -@code{yypush_parse}, @code{yypull_parse}, @code{yypstate}, -@code{yypstate_new} and @code{yypstate_delete} will also be renamed. -For example, if you use @samp{-p c}, the names become @code{cparse}, -@code{clex}, and so on. - -@strong{All 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 @code{@var{prefix}parse}, 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}, +@code{yylval}. 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 +@code{api.prefix} (possibly using the option +@samp{-Dapi.prefix=@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 +@var{PREFIX} (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}, +@code{yynerrs}, @code{yylval}, @code{yylloc}, @code{yychar} and +@code{yydebug}. If you use a push parser, @code{yypush_parse}, +@code{yypull_parse}, @code{yypstate}, @code{yypstate_new} and +@code{yypstate_delete} will also be renamed. The renamed macros include +@code{YYSTYPE}, @code{YYSTYPE_IS_TRIVIAL}, @code{YYSTYPE_IS_DECLARED}, +@code{YYLTYPE}, @code{YYLTYPE_IS_TRIVIAL}, and @code{YYLTYPE_IS_DECLARED}. + +For example, if you use @samp{%define api.prefix c}, the names become +@code{cparse}, @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 +@code{@var{prefix}parse}, and so on: + +@example +#define YYSTYPE CTYPE +#define yyparse cparse +#define yylval clval +... +YYSTYPE yylval; +int yyparse (void); +@end example + +This effectively substitutes one name for the other in the entire parser +implementation file, thus the ``original'' names (@code{yylex}, +@code{YYSTYPE}, @dots{}) are also usable in the parser implementation file. + +However, in the parser header file, the symbols are defined renamed, for +instance: + +@example +extern CSTYPE clval; +int cparse (void); +@end example + +Previously, a similar feature was provided by the obsoleted directive +@code{%name-prefix} (@pxref{Table of Symbols, ,Bison Symbols}) and option +@code{--name-prefix} (@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 --name-prefix=@var{prefix} -Pretend that @code{%name-prefix "@var{prefix}"} was specified. -@xref{Decl Summary}. +Pretend that @code{%name-prefix "@var{prefix}"} was specified (@pxref{Decl +Summary}). Obsoleted by @code{-Dapi.prefix=@var{prefix}}. @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 +@code{api.prefix}, do no rename types and macros. + +The precise list of symbols renamed in C parsers is @code{yyparse}, +@code{yylex}, @code{yyerror}, @code{yynerrs}, @code{yylval}, @code{yychar}, +@code{yydebug}, and (if locations are used) @code{yylloc}. If you use a +push parser, @code{yypush_parse}, @code{yypull_parse}, @code{yypstate}, +@code{yypstate_new} 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. @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 3fa2a7af..599cbbad 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 549d62dc..970d3f1b 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 + ]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 1baf6616..7a981c6d 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])