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.
This commit is contained in:
Akim Demaille
2008-10-21 18:00:29 -05:00
parent 1fa5d8bbf9
commit 5ab8c47bcf
6 changed files with 299 additions and 10 deletions

View File

@@ -283,6 +283,31 @@ prepare_states (void)
/*-----------------------------------------------.
| For each symbol type, its tags and type name. |
`-----------------------------------------------*/
static void
type_names_output (FILE *out)
{
int i;
char const *sep = "";
fputs ("m4_define([b4_type_names],\n[", out);
for (i = 0; i < nsyms; ++i)
{
symbol *sym = symbols[i];
/* Symbol-name, Symbol-number, optional typename. */
fprintf (out, "%s[", i ? ",\n" : "");
escaped_output (out, sym->tag);
fprintf (out, ", %d, [[%s]]]",
sym->number,
sym->type_name ? sym->type_name : "");
}
fputs ("])\n\n", out);
}
/*---------------------------------.
| Output the user actions to OUT. |
`---------------------------------*/
@@ -461,7 +486,6 @@ prepare_actions (void)
muscle_insert_unsigned_int_table ("conflicting_rules", conflict_list,
0, 1, conflict_list_cnt);
}
/*---------------------------.
| Call the skeleton parser. |
@@ -567,6 +591,7 @@ output_skeleton (void)
/* Output the definitions of all the muscles. */
fputs ("m4_init()\n", out);
type_names_output (out);
user_actions_output (out);
merger_output (out);
token_definitions_output (out);