[ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
10.1.2.2 C++ Variants
Bison provides a variant based implementation of semantic values for C++. This alleviates all the limitations reported in the previous section, and in particular, object types can be used without pointers.
To enable variant-based semantic values, set %define
variable
variant
(see section variant). Once this defined,
%union
is ignored, and instead of using the name of the fields of the
%union
to “type” the symbols, use genuine types.
For instance, instead of
%union { int ival; std::string* sval; } %token <ival> NUMBER; %token <sval> STRING;
write
%token <int> NUMBER; %token <std::string> STRING;
STRING
is no longer a pointer, which should fairly simplify the user
actions in the grammar and in the scanner (in particular the memory
management).
Since C++ features destructors, and since it is customary to specialize
operator<<
to support uniform printing of values, variants also
typically simplify Bison printers and destructors.
Variants are stricter than unions. When based on unions, you may play any
dirty game with yylval
, say storing an int
, reading a
char*
, and then storing a double
in it. This is no longer
possible with variants: they must be initialized, then assigned to, and
eventually, destroyed.
- Method on semantic_type: T& build<T> ()
Initialize, but leave empty. Returns the address where the actual value may be stored. Requires that the variant was not initialized yet.
Warning: We do not use Boost.Variant, for two reasons. First, it
appeared unacceptable to require Boost on the user’s machine (i.e., the
machine on which the generated parser will be compiled, not the machine on
which bison
was run). Second, for each possible semantic value,
Boost.Variant not only stores the value, but also a tag specifying its
type. But the parser already “knows” the type of the semantic value, so
that would be duplicating the information.
Therefore we developed light-weight variants whose type tag is external (so
they are really like unions
for C++ actually). But our code is much
less mature that Boost.Variant. So there is a number of limitations in
(the current implementation of) variants:
-
Alignment must be enforced: values should be aligned in memory according to
the most demanding type. Computing the smallest alignment possible requires
meta-programming techniques that are not currently implemented in Bison, and
therefore, since, as far as we know,
double
is the most demanding type on all platforms, alignments are enforced fordouble
whatever types are actually used. This may waste space in some cases. - There might be portability issues we are not aware of.
As far as we know, these limitations can be alleviated. All it takes is some time and/or some talented C++ hacker willing to contribute to Bison.
[ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated on December 1, 2013 using texi2html 5.0.