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

30
NEWS
View File

@@ -96,10 +96,36 @@ GNU Bison NEWS
until it sees the '='. So we notate the two possible reductions to
indicate that each conflicts in one rule.
*** C++: Actual token constructors
When variants and token constructors are enabled, in addition to the
type-safe named token constructors (make_ID, amke_INT, etc.), we now
generate genuine constructors for symbol_type.
For instance with these declarations
%token ':'
<std::string> ID
<int> INT;
you may use these constructors:
symbol_type (int token, const std::string&);
symbol_type (int token, const int&);
symbol_type (int token);
which should be used in a Flex-scanner as follows.
%%
[a-z]+ return yy::parser::symbol_type (ID, yytext);
[0-9]+ return yy::parser::symbol_type (INT, text_to_int (yytext);
":" return yy::parser::symbol_type (:);
<<EOF>> return yy::parser::symbol_type (0);
*** C++: Variadic emplace
If your application requires C++11, you may now use a variadic emplace for
semantic values:
If your application requires C++11 and you don't use symbol constructors,
you may now use a variadic emplace for semantic values:
%define api.value.type variant
%token <std::pair<int, int>> PAIR