Previous: , Up: C++ Semantic Values   [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 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.

Method on semantic_type: T& build<T> (const T& t)

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:

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: , Up: C++ Semantic Values   [Contents][Index]