c++: exhibit a safe symbol_type

Instead of introducing make_symbol (whose name, btw, somewhat
infringes on the user's "name space", if she defines a token named
"symbol"), let's make the construction of symbol_type safer, using
assertions.

For instance with:

    %token ':' <std::string> ID <int> INT;

generate:

    symbol_type (int token, const std::string&);
    symbol_type (int token, const int&);
    symbol_type (int token);

It does mean that now named token constructors (make_ID, make_INT,
etc.) go through a useless assert, but I think we can ignore this: I
assume any decent compiler will inline the symbol_type ctor inside the
make_TOKEN functions, which will show that the assert is trivially
verified, hence I expect no code will be emitted for it.  And anyway,
that's an assert, NDEBUG controls it.

* data/c++.m4 (symbol_type): Turn into a subclass of
basic_symbol<by_type>.
Declare symbol constructors when variants are enabled.
* data/variant.hh (_b4_type_constructor_declare)
(_b4_type_constructor_define): Replace with...
(_b4_symbol_constructor_declare, _b4_symbol_constructor_def): these.
Generate symbol_type constructors.
* doc/bison.texi (Complete Symbols): Document.
* tests/types.at: Check.
This commit is contained in:
Akim Demaille
2018-12-19 17:51:10 +01:00
parent 1f4dd2671a
commit e5780041b9
5 changed files with 142 additions and 43 deletions

View File

@@ -332,7 +332,17 @@ m4_define([b4_symbol_type_declare],
};
/// "External" symbols: returned by the scanner.
typedef basic_symbol<by_type> symbol_type;
struct symbol_type : basic_symbol<by_type>
{]b4_variant_if([[
/// Superclass.
typedef basic_symbol<by_type> super_type;
/// Empty symbol.
symbol_type () {};
/// Constructor for valueless symbols, and symbols from each type.
]b4_type_foreach([_b4_symbol_constructor_declare])[
]])[};
]])

View File

@@ -368,25 +368,21 @@ m4_define([_b4_token_maker_declare],
])])
# _b4_type_constructor_declare(SYMBOL-NUM...)
# -------------------------------------------
# _b4_symbol_constructor_declare(SYMBOL-NUM...)
# ---------------------------------------------
# Declare a unique make_symbol for all the SYMBOL-NUM (they
# have the same type). Use at class-level.
m4_define([_b4_type_constructor_declare],
m4_define([_b4_symbol_constructor_declare],
[m4_ifval(_b4_includes_tokens($@),
[#if 201103L <= YY_CPLUSPLUS
static
symbol_type
make_symbol (dnl
b4_join([int tok],
symbol_type (b4_join(
[int tok],
b4_symbol_if([$1], [has_type],
[b4_symbol([$1], [type]) v]),
b4_locations_if([location_type l])));
#else
static
symbol_type
make_symbol (dnl
b4_join([int tok],
symbol_type (b4_join(
[int tok],
b4_symbol_if([$1], [has_type],
[const b4_symbol([$1], [type])& v]),
b4_locations_if([const location_type& l])));
@@ -399,7 +395,6 @@ b4_join([int tok],
# Declare symbol constructors. Use at class-level.
m4_define([b4_symbol_constructor_declare],
[ // Symbol constructors declarations.
b4_type_foreach([_b4_type_constructor_declare])
b4_symbol_foreach([_b4_token_maker_declare])])
@@ -437,8 +432,8 @@ m4_define([_b4_token_maker_define],
])])
# _b4_type_constructor_define(SYMBOL-NUM...)
# ------------------------------------------
# _b4_symbol_constructor_define(SYMBOL-NUM...)
# --------------------------------------------
# Declare a unique make_symbol for all the SYMBOL-NUM (they
# have the same type). Use at class-level.
m4_define([_b4_type_clause],
@@ -447,38 +442,36 @@ m4_define([_b4_type_clause],
[tok == token::b4_symbol([$1], [id])],
[tok == b4_symbol([$1], [user_number])])])])
m4_define([_b4_type_constructor_define],
m4_define([_b4_symbol_constructor_define],
[m4_ifval(_b4_includes_tokens($@),
[#if 201103L <= YY_CPLUSPLUS
[[#if 201103L <= YY_CPLUSPLUS
inline
b4_parser_class_name::symbol_type
b4_parser_class_name::make_symbol (dnl
b4_join([int tok],
]b4_parser_class_name[::symbol_type::symbol_type (]b4_join(
[int tok],
b4_symbol_if([$1], [has_type],
[b4_symbol([$1], [type]) v]),
b4_locations_if([location_type l])))
{b4_parse_assert_if([
assert (m4_join([ || ], m4_map_sep([_b4_type_clause], [, ], [$@])));])[
return symbol_type (]b4_join([token_type (tok)],
b4_symbol_if([$1], [has_type], [std::move (v)]),
b4_locations_if([std::move (l)])));
b4_locations_if([location_type l]))[)
: super_type(]b4_join([token_type (tok)],
b4_symbol_if([$1], [has_type], [std::move (v)]),
b4_locations_if([std::move (l)]))[)
{
YYASSERT (]m4_join([ || ], m4_map_sep([_b4_type_clause], [, ], [$@]))[);
}
#else
inline
b4_parser_class_name::symbol_type
b4_parser_class_name::make_symbol (dnl
b4_join([int tok],
]b4_parser_class_name[::symbol_type::symbol_type (]b4_join(
[int tok],
b4_symbol_if([$1], [has_type],
[const b4_symbol([$1], [type])& v]),
b4_locations_if([const location_type& l])))
{b4_parse_assert_if([
assert (m4_join([ || ], m4_map_sep([_b4_type_clause], [, ], [$@])));])[
return symbol_type (]b4_join([token_type (tok)],
b4_symbol_if([$1], [has_type], [v]),
b4_locations_if([l])));
b4_locations_if([const location_type& l]))[)
: super_type(]b4_join([token_type (tok)],
b4_symbol_if([$1], [has_type], [v]),
b4_locations_if([l]))[)
{
YYASSERT (]m4_join([ || ], m4_map_sep([_b4_type_clause], [, ], [$@]))[);
}
#endif
])])
]])])
# b4_basic_symbol_constructor_declare(SYMBOL-NUM)
@@ -532,5 +525,5 @@ m4_define([b4_basic_symbol_constructor_define],
# Define the overloaded versions of make_symbol for all the value types.
m4_define([b4_symbol_constructor_define],
[ // Implementation of make_symbol for each symbol type.
b4_type_foreach([_b4_type_constructor_define])
b4_type_foreach([_b4_symbol_constructor_define])
b4_symbol_foreach([_b4_token_maker_define])])