+Note that when using variants, the interface for @code{yylex} is the same,
+but @code{yylval} is handled differently.
+
+Regular union-based code in Lex scanner typically look like:
+
+@example
+[0-9]+ @{
+ yylval.ival = text_to_int (yytext);
+ return yy::parser::INTEGER;
+ @}
+[a-z]+ @{
+ yylval.sval = new std::string (yytext);
+ return yy::parser::IDENTIFIER;
+ @}
+@end example
+
+Using variants, @code{yylval} is already constructed, but it is not
+initialized. So the code would look like:
+
+@example
+[0-9]+ @{
+ yylval.build<int>() = text_to_int (yytext);
+ return yy::parser::INTEGER;
+ @}
+[a-z]+ @{
+ yylval.build<std::string> = yytext;
+ return yy::parser::IDENTIFIER;
+ @}
+@end example
+
+@noindent
+or
+
+@example
+[0-9]+ @{
+ yylval.build(text_to_int (yytext));
+ return yy::parser::INTEGER;
+ @}
+[a-z]+ @{
+ yylval.build(yytext);
+ return yy::parser::IDENTIFIER;
+ @}
+@end example
+
+
+@node Complete Symbols
+@subsubsection Complete Symbols
+
+If you specified both @code{%define api.value.type variant} and
+@code{%define api.token.constructor},
+the @code{parser} class also defines the class @code{parser::symbol_type}
+which defines a @emph{complete} symbol, aggregating its type (i.e., the
+traditional value returned by @code{yylex}), its semantic value (i.e., the
+value passed in @code{yylval}, and possibly its location (@code{yylloc}).
+
+@deftypemethod {symbol_type} {} symbol_type (token_type @var{type}, const semantic_type& @var{value}, const location_type& @var{location})
+Build a complete terminal symbol which token type is @var{type}, and which
+semantic value is @var{value}. If location tracking is enabled, also pass
+the @var{location}.
+@end deftypemethod
+
+This interface is low-level and should not be used for two reasons. First,
+it is inconvenient, as you still have to build the semantic value, which is
+a variant, and second, because consistency is not enforced: as with unions,
+it is still possible to give an integer as semantic value for a string.
+
+So for each token type, Bison generates named constructors as follows.
+
+@deftypemethod {symbol_type} {} make_@var{token} (const @var{value_type}& @var{value}, const location_type& @var{location})
+@deftypemethodx {symbol_type} {} make_@var{token} (const location_type& @var{location})
+Build a complete terminal symbol for the token type @var{token} (not
+including the @code{api.token.prefix}) whose possible semantic value is
+@var{value} of adequate @var{value_type}. If location tracking is enabled,
+also pass the @var{location}.
+@end deftypemethod
+
+For instance, given the following declarations:
+
+@example
+%define api.token.prefix "TOK_"
+%token <std::string> IDENTIFIER;
+%token <int> INTEGER;
+%token COLON;
+@end example
+
+@noindent
+Bison generates the following functions:
+
+@example
+symbol_type make_IDENTIFIER(const std::string& v,
+ const location_type& l);
+symbol_type make_INTEGER(const int& v,
+ const location_type& loc);
+symbol_type make_COLON(const location_type& loc);
+@end example
+
+@noindent
+which should be used in a Lex-scanner as follows.
+
+@example
+[0-9]+ return yy::parser::make_INTEGER(text_to_int (yytext), loc);
+[a-z]+ return yy::parser::make_IDENTIFIER(yytext, loc);
+":" return yy::parser::make_COLON(loc);
+@end example
+
+Tokens that do not have an identifier are not accessible: you cannot simply
+use characters such as @code{':'}, they must be declared with @code{%token}.