Improve C++ namespace support. Discussed starting at

<http://lists.gnu.org/archive/html/help-bison/2007-09/msg00016.html>.
* data/c++.m4: (b4_namespace_ref, b4_namespace_open,
b4_namespace_close): New macros that interpret the %define variable
"namespace" so its value can contain "::" to indicate nested
namespaces.
* data/glr.cc (b4_namespace): Don't define, and replace all uses with
the above macros.
* data/lalr1.cc (b4_namespace): Likewise.
* data/location.cc (b4_namespace): Likewise.
* doc/bison.texinfo (Decl Summary): Move `%define push_pull' entry
inside a new table in the general %define entry.  Document `%define
namespace' there as well.  Point the %name-prefix entry to it since it
explains it more completely in the case of C++.
(C++ Bison Interface): Mention `%define namespace' instead of
%name-prefix.
(Table of Symbols): Remove the `%define push_pull' entry.  The %define
entry suffices.
* tests/c++.at (Relative namespace references): New test case.
(Absolute namespace references): New test case.
(Syntactically invalid namespace references): New test case.
* tests/input.at (C++ namespace reference errors): New test case.
This commit is contained in:
Joel E. Denny
2007-10-08 10:09:07 +00:00
parent 35b8730d01
commit 793fbca50a
8 changed files with 309 additions and 63 deletions

View File

@@ -35,6 +35,51 @@ b4_percent_define_default([[define_location_comparison]],
[std::string], [[true]], [[false]])])
## ----------- ##
## Namespace. ##
## ----------- ##
m4_define([b4_namespace_ref], [b4_percent_define_get([[namespace]])])
# Don't permit an empty b4_namespace_ref. Any `::parser::foo' appended to it
# would compile as an absolute reference with `parser' in the global namespace.
# b4_namespace_open would open an anonymous namespace and thus establish
# internal linkage. This would compile. However, it's cryptic, and internal
# linkage for the parser would be specified in all translation units that
# include the header, which is always generated. If we ever need to permit
# internal linkage somehow, surely we can find a cleaner approach.
m4_if(m4_bregexp(b4_namespace_ref, [^[ ]*$]), [-1], [],
[b4_complain_at(b4_percent_define_get_loc([[namespace]]),
[[namespace reference is empty]])])
# Instead of assuming the C++ compiler will do it, Bison should reject any
# invalid b4_namepsace_ref that would be converted to a valid
# b4_namespace_open. The problem is that Bison doesn't always output
# b4_namespace_ref to uncommented code but should reserve the ability to do so
# in future releases without risking breaking any existing user grammars.
# Specifically, don't allow empty names as b4_namespace_open would just convert
# those into anonymous namespaces, and that might tempt some users.
m4_if(m4_bregexp(b4_namespace_ref, [::[ ]*::]), [-1], [],
[b4_complain_at(b4_percent_define_get_loc([[namespace]]),
[[namespace reference has consecutive "::"]])])
m4_if(m4_bregexp(b4_namespace_ref, [::[ ]*$]), [-1], [],
[b4_complain_at(b4_percent_define_get_loc([[namespace]]),
[[namespace reference has a trailing "::"]])])
m4_define([b4_namespace_open],
[b4_user_code([b4_percent_define_get_syncline([[namespace]])
[namespace ]m4_bpatsubst(m4_dquote(m4_bpatsubst(m4_dquote(b4_namespace_ref),
[^\(.\)[ ]*::], [\1])),
[::], [ { namespace ])[ {]])])
m4_define([b4_namespace_close],
[b4_user_code([b4_percent_define_get_syncline([[namespace]])
m4_bpatsubst(m4_dquote(m4_bpatsubst(m4_dquote(b4_namespace_ref),
[^\(.\)[ ]*\(::\)?\([^][:]\|:[^][:]\)*],
[\1])),
[::\([^][:]\|:[^][:]\)*], [} ])[} // ]b4_namespace_ref])])
# b4_token_enums(LIST-OF-PAIRS-TOKEN-NAME-TOKEN-NUMBER)
# -----------------------------------------------------
# Output the definition of the tokens as enums.

View File

@@ -58,8 +58,6 @@ m4_include(b4_pkgdatadir/[location.cc])
m4_define([b4_parser_class_name],
[b4_percent_define_get([[parser_class_name]])])
m4_define([b4_namespace],
[b4_percent_define_get([[namespace]])])
# Save the parse parameters.
m4_define([b4_parse_param_orig], m4_defn([b4_parse_param]))
@@ -79,9 +77,9 @@ m4_define([b4_yy_symbol_print_generate],
[static void],
[[FILE *], []],
[[int yytype], [yytype]],
[[const b4_namespace::b4_parser_class_name::semantic_type *yyvaluep],
[[const b4_namespace_ref::b4_parser_class_name::semantic_type *yyvaluep],
[yyvaluep]],
[[const b4_namespace::b4_parser_class_name::location_type *yylocationp],
[[const b4_namespace_ref::b4_parser_class_name::location_type *yylocationp],
[yylocationp]],
b4_parse_param)[
{
@@ -97,7 +95,7 @@ m4_append([b4_post_prologue],
b4_c_ansi_function_decl([yyerror],
[static void],
[[b4_namespace::b4_parser_class_name::location_type *yylocationp], [yylocationp]],
[[b4_namespace_ref::b4_parser_class_name::location_type *yylocationp], [yylocationp]],
b4_parse_param,
[[const char* msg], [msg]])])
@@ -111,7 +109,7 @@ m4_append([b4_epilogue],
]b4_c_ansi_function_def([yyerror],
[static void],
[[b4_namespace::b4_parser_class_name::location_type *yylocationp], [yylocationp]],
[[b4_namespace_ref::b4_parser_class_name::location_type *yylocationp], [yylocationp]],
b4_parse_param,
[[const char* msg], [msg]])[
{
@@ -120,8 +118,7 @@ m4_append([b4_epilogue],
}
namespace ]b4_namespace[
{
]b4_namespace_open[
]dnl In this section, the parse param are the original parse_params.
m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
[ /// Build a parser object.
@@ -203,7 +200,7 @@ m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
#endif
]m4_popdef([b4_parse_param])dnl
[} // namespace ]b4_namespace[
b4_namespace_close[
]])
@@ -211,10 +208,10 @@ m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
# Let glr.c believe that the user arguments include the parser itself.
m4_ifset([b4_parse_param],
[m4_pushdef([b4_parse_param],
m4_dquote([[[b4_namespace::b4_parser_class_name& yyparser], [[yyparser]]],]
m4_dquote([[[b4_namespace_ref::b4_parser_class_name& yyparser], [[yyparser]]],]
m4_defn([b4_parse_param])))],
[m4_pushdef([b4_parse_param],
[[[[b4_namespace::b4_parser_class_name& yyparser], [[yyparser]]]]])
[[[[b4_namespace_ref::b4_parser_class_name& yyparser], [[yyparser]]]]])
])
m4_include(b4_pkgdatadir/[glr.c])
m4_popdef([b4_parse_param])
@@ -237,11 +234,10 @@ b4_copyright([Skeleton interface for Bison GLR parsers in C++],
/* Using locations. */
#define YYLSP_NEEDED ]b4_locations_flag[
namespace ]b4_namespace[
{
]b4_namespace_open[
class position;
class location;
}
]b4_namespace_close[
#include "location.hh"
@@ -269,8 +265,7 @@ namespace ]b4_namespace[
while (/*CONSTCOND*/ 0)
#endif
namespace ]b4_namespace[
{
]b4_namespace_open[
/// A Bison parser.
class ]b4_parser_class_name[
{
@@ -368,13 +363,13 @@ b4_percent_define_flag_if([[global_tokens_and_yystype]],
[b4_token_defines(b4_tokens)])
[
#ifndef YYSTYPE
# define YYSTYPE ]b4_namespace[::]b4_parser_class_name[::semantic_type
# define YYSTYPE ]b4_namespace_ref[::]b4_parser_class_name[::semantic_type
#endif
#ifndef YYLTYPE
# define YYLTYPE ]b4_namespace[::]b4_parser_class_name[::location_type
# define YYLTYPE ]b4_namespace_ref[::]b4_parser_class_name[::location_type
#endif
}
]b4_namespace_close[
]b4_percent_code_get([[provides]])[]dnl

View File

@@ -20,8 +20,6 @@ m4_include(b4_pkgdatadir/[c++.m4])
m4_define([b4_parser_class_name],
[b4_percent_define_get([[parser_class_name]])])
m4_define([b4_namespace],
[b4_percent_define_get([[namespace]])])
# The header is mandatory.
b4_defines_if([],
@@ -51,11 +49,10 @@ dnl FIXME: This is wrong, we want computed header guards.
#include <iostream>
#include "stack.hh"
namespace ]b4_namespace[
{
]b4_namespace_open[
class position;
class location;
}
]b4_namespace_close[
#include "location.hh"
@@ -96,8 +93,7 @@ do { \
} while (false)
#endif
namespace ]b4_namespace[
{
]b4_namespace_open[
/// A Bison parser.
class ]b4_parser_class_name[
@@ -286,14 +282,14 @@ b4_error_verbose_if([, int tok])[);
static const token_number_type yyundef_token_;
]b4_parse_param_vars[
};
}
]b4_namespace_close[
]b4_percent_define_flag_if([[global_tokens_and_yystype]],
[b4_token_defines(b4_tokens)
#ifndef YYSTYPE
/* Redirection for backward compatibility. */
# define YYSTYPE b4_namespace::b4_parser_class_name::semantic_type
# define YYSTYPE b4_namespace_ref::b4_parser_class_name::semantic_type
#endif
])
b4_percent_code_get([[provides]])[]dnl
@@ -375,8 +371,7 @@ do { \
#define YYABORT goto yyabortlab
#define YYERROR goto yyerrorlab
namespace ]b4_namespace[
{
]b4_namespace_open[
#if YYERROR_VERBOSE
/* Return YYSTR after stripping away unnecessary quotes and
@@ -1049,7 +1044,7 @@ b4_error_verbose_if([, int tok])[)
const unsigned int ]b4_parser_class_name[::yyuser_token_number_max_ = ]b4_user_token_number_max[;
const ]b4_parser_class_name[::token_number_type ]b4_parser_class_name[::yyundef_token_ = ]b4_undef_token_number[;
} // namespace ]b4_namespace[
]b4_namespace_close[
]b4_epilogue
dnl
@@ -1062,8 +1057,7 @@ b4_copyright([Stack handling for Bison parsers in C++],
#include <deque>
namespace ]b4_namespace[
{
]b4_namespace_open[
template <class T, class S = std::deque<T> >
class stack
{
@@ -1149,7 +1143,7 @@ namespace ]b4_namespace[
const S& stack_;
unsigned int range_;
};
}
]b4_namespace_close[
#endif // not BISON_STACK_HH]
m4_divert_pop(0)

View File

@@ -25,7 +25,7 @@ b4_copyright([Positions for Bison parsers in C++],
/**
** \file position.hh
** Define the ]b4_percent_define_get([[namespace]])[::position class.
** Define the ]b4_namespace_ref[::position class.
*/
#ifndef BISON_POSITION_HH
@@ -35,8 +35,7 @@ b4_copyright([Positions for Bison parsers in C++],
# include <string>
# include <algorithm>
namespace ]b4_percent_define_get([[namespace]])[
{
]b4_namespace_open[
/// Abstract a position.
class position
{
@@ -142,7 +141,7 @@ namespace ]b4_percent_define_get([[namespace]])[
return ostr << pos.line << '.' << pos.column;
}
}
]b4_namespace_close[
#endif // not BISON_POSITION_HH]
@output(b4_dir_prefix[]location.hh@)
b4_copyright([Locations for Bison parsers in C++],
@@ -150,7 +149,7 @@ b4_copyright([Locations for Bison parsers in C++],
/**
** \file location.hh
** Define the ]b4_percent_define_get([[namespace]])[::location class.
** Define the ]b4_namespace_ref[::location class.
*/
#ifndef BISON_LOCATION_HH
@@ -160,8 +159,7 @@ b4_copyright([Locations for Bison parsers in C++],
# include <string>
# include "position.hh"
namespace ]b4_percent_define_get([[namespace]])[
{
]b4_namespace_open[
/// Abstract a location.
class location
@@ -270,7 +268,7 @@ namespace ]b4_percent_define_get([[namespace]])[
return ostr;
}
}
]b4_namespace_close[
#endif // not BISON_LOCATION_HH]
m4_divert_pop(0)