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.
This commit is contained in:
Akim Demaille
2012-06-26 10:09:10 +02:00
parent 087dcd7868
commit 4b3847c3c0
10 changed files with 320 additions and 96 deletions

54
NEWS
View File

@@ -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:

View File

@@ -84,11 +84,24 @@ m4_define([b4_identification],
## Default values. ##
## ---------------- ##
# If the %union is not named, its name is YYSTYPE.
m4_define_default([b4_union_name], [YYSTYPE])
# 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], [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

View File

@@ -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

View File

@@ -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[

View File

@@ -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))[;
}

View File

@@ -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([[

View File

@@ -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.
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 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 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 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.
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}.
@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}).
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 @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.
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}

View File

@@ -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);

View File

@@ -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

View File

@@ -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])