mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 20:33:03 +00:00
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.
109 lines
2.2 KiB
Plaintext
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:
|