Files
bison/examples/variant.yy
Akim Demaille 5ab8c47bcf Use variants to support objects as semantic values.
This patch was inspired by work by Michiel De Wilde.  But he used Boost
variants which (i) requires Boost on the user side, (ii) is slow, and
(iii) has useless overhead (the parser knows the type of the semantic value
there is no reason to duplicate this information as Boost.Variants do).

This implementation reserves a buffer large enough to store the largest
objects.  yy::variant implements this buffer.  It was implemented with
Quentin Hocquet.

	* src/output.c (type_names_output): New.
	(output_skeleton): Invoke it.
	* data/c++.m4 (b4_variant_if): New.
	(b4_symbol_value): If needed, provide a definition for variants.
	* data/lalr1.cc (b4_symbol_value, b4_symbol_action_)
	(b4_symbol_variant, _b4_char_sizeof_counter, _b4_char_sizeof_dummy)
	(b4_char_sizeof, yy::variant): New.
	(parser::parse): If variants are requested, define
	parser::union_type, parser::variant, change the definition of
	semantic_type, construct $$ before running the user action instead
	of performing a default $$ = $1.
	* examples/variant.yy: New.
	Based on an example by Michiel De Wilde.
2008-11-03 21:50:48 +01:00

109 lines
2.2 KiB
Plaintext

/* Test file for C++ parsers using variants.
Based on an example by Michiel De Wilde <mdewilde.agilent@gmail.com>. */
%language "C++"
%debug
%defines
%define variant
%code requires // *.hh
{
#include <string>
}
%code // *.cc
{
#include <algorithm>
#include <iostream>
#include <sstream>
static yy::parser::token_type yylex(yy::parser::semantic_type* yylval);
}
%token <std::string> TEXT
%token <int> NUMBER
%printer { debug_stream() << $$; } <int> <std::string>
%token END_OF_FILE 0
%type <std::string> text result
%%
result:
text { std::cout << $1 << std::endl; }
;
text:
/* nothing */ { /* This will generate an empty string */ }
| text TEXT { std::swap($$,$1); $$.append($2); }
| text NUMBER {
std::swap($$,$1);
std::ostringstream o;
o << ' ' << $2;
$$.append(o.str());
}
;
%%
// The yylex function providing subsequent tokens:
// TEXT "I have three numbers for you:"
// NUMBER 1
// NUMBER 2
// NUMBER 3
// TEXT " and that's all!"
// END_OF_FILE
static
yy::parser::token_type
yylex(yy::parser::semantic_type* yylval)
{
static int stage = 0;
yy::parser::token_type result;
switch (stage)
{
case 0:
yylval->build<std::string>();
yylval->as<std::string>() = std::string("I have three numbers for you:");
result = yy::parser::token::TEXT;
break;
case 1:
case 2:
case 3:
yylval->build<int>();
yylval->as<int>() = stage;
result = yy::parser::token::NUMBER;
break;
case 4:
yylval->build<std::string>();
yylval->as<std::string>() = std::string(" and that's all!");
result = yy::parser::token::TEXT;
break;
default:
result = yy::parser::token::END_OF_FILE;
break;
}
stage++;
return result;
}
// Mandatory error function
void
yy::parser::error(const yy::parser::location_type& yylloc,
const std::string& message)
{
std::cerr << yylloc << ": " << message << std::endl;
}
int
main(int argc, char *argv[])
{
yy::parser p;
p.set_debug_level(!!getenv("YYDEBUG"));
p.parse();
}
// Local Variables:
// mode: C++
// End: