Previous: C++ Unions, Up: C++ Semantic Values [Contents][Index]
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 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.
Initialize, but leave empty. Returns the address where the actual value may be stored. Requires that the variant was not initialized yet.
Initialize, and copy-construct from t.
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:
double
is the most demanding
type on all platforms, alignments are enforced for double
whatever
types are actually used. This may waste space in some cases.
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.
Previous: C++ Unions, Up: C++ Semantic Values [Contents][Index]