From 507aa0e2a80ee035146a6429a64df9d6e6fb8a3b Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Tue, 23 Dec 2008 10:44:53 +0100 Subject: [PATCH] Extract variant.hh * data/variant.hh: New, extracted from... * data/lalr1.cc: here. Adjust. * data/local.mk: Adjust. --- ChangeLog | 8 ++ data/lalr1.cc | 187 ++----------------------------------------- data/local.mk | 1 + data/variant.hh | 207 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 224 insertions(+), 179 deletions(-) create mode 100644 data/variant.hh diff --git a/ChangeLog b/ChangeLog index 20135167..7330548b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2009-02-19 Akim Demaille + + Extract variant.hh + * data/variant.hh: New, extracted from... + * data/lalr1.cc: here. + Adjust. + * data/local.mk: Adjust. + 2009-02-19 Akim Demaille Extract stack.hh from lalr1.cc. diff --git a/data/lalr1.cc b/data/lalr1.cc index c3ea4e26..031d13c5 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -42,27 +42,10 @@ m4_define([b4_integral_parser_table_define], # b4_symbol_value_template(VAL, [TYPE]) # ------------------------------------- -# Same as b4_symbol_value, but used in a template method. +# Same as b4_symbol_value, but used in a template method. It makes +# a difference when using variants. m4_copy([b4_symbol_value], [b4_symbol_value_template]) -# How the semantic value is extracted when using variants. -b4_variant_if([ - # b4_symbol_value(VAL, [TYPE]) - # ---------------------------- - m4_define([b4_symbol_value], - [m4_ifval([$2], - [$1.as< $2 >()], - [$1])]) - - # b4_symbol_value_template(VAL, [TYPE]) - # ------------------------------------- - # Same as b4_symbol_value, but used in a template method. - m4_define([b4_symbol_value_template], - [m4_ifval([$2], - [$1.template as< $2 >()], - [$1])]) -]) # b4_variant_if - # b4_lex_symbol_if([IF-YYLEX-RETURNS-A-COMPLETE-SYMBOL], [IF-NOT]) # ---------------------------------------------------------------- @@ -80,14 +63,14 @@ m4_define([b4_assert_if], # -------------------- # Expansion of $$. m4_define([b4_lhs_value], -[b4_symbol_value([yylhs.value], [$1])]) + [b4_symbol_value([yylhs.value], [$1])]) # b4_lhs_location() # ----------------- # Expansion of @$. m4_define([b4_lhs_location], -[yylhs.location]) + [yylhs.location]) # b4_rhs_data(RULE-LENGTH, NUM) @@ -121,6 +104,7 @@ m4_define([b4_rhs_value], m4_define([b4_rhs_location], [b4_rhs_data([$1], [$2]).location]) + # b4_symbol_action(SYMBOL-NUM, KIND) # ---------------------------------- # Run the action KIND (destructor or printer) for SYMBOL-NUM. @@ -287,60 +271,6 @@ m4_define([b4_symbol_constructor_definitions], b4_symbol_foreach([b4_symbol_constructor_definition_])])]) -# b4_symbol_variant(YYTYPE, YYVAL, ACTION, [ARGS]) -# ------------------------------------------------ -# Run some ACTION ("build", or "destroy") on YYVAL of symbol type -# YYTYPE. -m4_define([b4_symbol_variant], -[m4_pushdef([b4_dollar_dollar], - [$2.$3< $][3 >(m4_shift3($@))])dnl - switch ($1) - { -b4_type_foreach([b4_type_action_])[]dnl - default: - break; - } -m4_popdef([b4_dollar_dollar])dnl -]) - - -# _b4_char_sizeof_counter -# ----------------------- -# A counter used by _b4_char_sizeof_dummy to create fresh symbols. -m4_define([_b4_char_sizeof_counter], -[0]) - -# _b4_char_sizeof_dummy -# --------------------- -# At each call return a new C++ identifier. -m4_define([_b4_char_sizeof_dummy], -[m4_define([_b4_char_sizeof_counter], m4_incr(_b4_char_sizeof_counter))dnl -dummy[]_b4_char_sizeof_counter]) - - -# b4_char_sizeof_(SYMBOL-NUM) -# --------------------------- -# A comment describing this symbol. -m4_define([b4_char_sizeof_], -[ // b4_symbol([$1], [tag]) -]) - -# b4_char_sizeof(SYMBOL-NUMS) -# -------------------------- -# To be mapped on the list of type names to produce: -# -# char dummy1[sizeof(type_name_1)]; -# char dummy2[sizeof(type_name_2)]; -# -# for defined type names. -m4_define([b4_char_sizeof], -[b4_symbol_if([$1], [has_type], -[ -m4_map([b4_char_sizeof_], [$@])dnl - char _b4_char_sizeof_dummy@{sizeof([b4_symbol([$1], [type])])@}; -])]) - - # b4_yytranslate_definition # ------------------------- # Define yytranslate_. Sometimes we want it in the header file, @@ -385,6 +315,7 @@ b4_locations_if( m4_define([b4_location_constructors]) m4_include(b4_pkgdatadir/[location.cc])]) m4_include(b4_pkgdatadir/[stack.hh]) +b4_variant_if([m4_include(b4_pkgdatadir/[variant.hh])]) # We do want M4 expansion after # for CPP macros. m4_changecom() @@ -408,109 +339,7 @@ dnl FIXME: This is wrong, we want computed header guards. ]b4_namespace_open[ ]b4_locations_if([ class position; class location;])[ -]b4_variant_if( -[[ - /// A char[S] buffer to store and retrieve objects. - /// - /// Sort of a variant, but does not keep track of the nature - /// of the stored data, since that knowledge is available - /// via the current state. - template - struct variant - {]b4_assert_if([ - /// Whether something is contained. - bool built; -])[ - /// Empty construction. - inline - variant ()]b4_assert_if([ - : built(false)])[ - {} - - /// Instantiate a \a T in here. - template - inline T& - build() - {]b4_assert_if([ - assert(!built); - built = true;])[ - return *new (buffer.raw) T; - } - - /// Instantiate a \a T in here from \a t. - template - inline T& - build(const T& t) - {]b4_assert_if([ - assert(!built); - built = true;])[ - return *new (buffer.raw) T(t); - } - - /// Construct and fill. - template - inline - variant (const T& t)]b4_assert_if([ - : built(true)])[ - { - new (buffer.raw) T(t); - } - - /// Accessor to a built \a T. - template - inline T& - as() - {]b4_assert_if([ - assert(built);])[ - return reinterpret_cast(buffer.raw); - } - - /// Const accessor to a built \a T (for %printer). - template - inline const T& - as() const - {]b4_assert_if([ - assert(built);])[ - return reinterpret_cast(buffer.raw); - } - - /// Swap the content with \a other. - template - inline void - swap(variant& other) - { - std::swap(as(), other.as()); - } - - /// Assign the content of \a other to this. - /// Destroys \a other. - template - inline void - build(variant& other) - { - build(); - swap(other); - other.destroy(); - } - - /// Destroy the stored \a T. - template - inline void - destroy() - { - as().~T();]b4_assert_if([ - built = false;])[ - } - - /// A buffer large enough to store any of the semantic values. - /// Long double is chosen as it has the strongest alignment - /// constraints. - union { - long double align_me; - char raw[S]; - } buffer; - }; -]])[ +]b4_variant_if([b4_variant_definition])[ ]b4_namespace_close[ ]b4_locations_if([#include "location.hh"])[ @@ -1202,7 +1031,7 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param)));])[ /* Variants are always initialized to an empty instance of the correct type. The default $$=$1 rule is NOT applied when using variants */ - ]b4_symbol_variant([[yyr1_@{yyn@}]], [yylhs.value], [build])[],[ + ]b4_symbol_variant([[yyr1_@{yyn@}]], [yylhs.value], [build]),[ /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, use the top of the stack. diff --git a/data/local.mk b/data/local.mk index 55802158..d55bacb0 100644 --- a/data/local.mk +++ b/data/local.mk @@ -28,6 +28,7 @@ dist_pkgdata_DATA = \ data/lalr1.java \ data/location.cc \ data/stack.hh \ + data/variant.hh \ data/yacc.c m4sugardir = $(pkgdatadir)/m4sugar diff --git a/data/variant.hh b/data/variant.hh new file mode 100644 index 00000000..89367338 --- /dev/null +++ b/data/variant.hh @@ -0,0 +1,207 @@ +# C++ skeleton for Bison + +# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 +# Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +## --------- ## +## variant. ## +## --------- ## + +# b4_symbol_variant(YYTYPE, YYVAL, ACTION, [ARGS]) +# ------------------------------------------------ +# Run some ACTION ("build", or "destroy") on YYVAL of symbol type +# YYTYPE. +m4_define([b4_symbol_variant], +[m4_pushdef([b4_dollar_dollar], + [$2.$3< $][3 >(m4_shift3($@))])dnl + switch ($1) + { +b4_type_foreach([b4_type_action_])[]dnl + default: + break; + } +m4_popdef([b4_dollar_dollar])dnl +]) + + +# _b4_char_sizeof_counter +# ----------------------- +# A counter used by _b4_char_sizeof_dummy to create fresh symbols. +m4_define([_b4_char_sizeof_counter], +[0]) + +# _b4_char_sizeof_dummy +# --------------------- +# At each call return a new C++ identifier. +m4_define([_b4_char_sizeof_dummy], +[m4_define([_b4_char_sizeof_counter], m4_incr(_b4_char_sizeof_counter))dnl +dummy[]_b4_char_sizeof_counter]) + + +# b4_char_sizeof_(SYMBOL-NUM) +# --------------------------- +# A comment describing this symbol. +m4_define([b4_char_sizeof_], +[ // b4_symbol([$1], [tag]) +]) + +# b4_char_sizeof(SYMBOL-NUMS) +# --------------------------- +# To be mapped on the list of type names to produce: +# +# char dummy1[sizeof(type_name_1)]; +# char dummy2[sizeof(type_name_2)]; +# +# for defined type names. +m4_define([b4_char_sizeof], +[b4_symbol_if([$1], [has_type], +[ +m4_map([b4_char_sizeof_], [$@])dnl + char _b4_char_sizeof_dummy@{sizeof([b4_symbol([$1], [type])])@}; +])]) + + +# b4_variant_definition +# --------------------- +# Define "variant". +m4_define([b4_variant_definition], +[[ + /// A char[S] buffer to store and retrieve objects. + /// + /// Sort of a variant, but does not keep track of the nature + /// of the stored data, since that knowledge is available + /// via the current state. + template + struct variant + {]b4_assert_if([ + /// Whether something is contained. + bool built; +])[ + /// Empty construction. + inline + variant ()]b4_assert_if([ + : built (false)])[ + {} + + /// Instantiate a \a T in here. + template + inline T& + build () + {]b4_assert_if([ + assert (!built); + built = true;])[ + return *new (buffer.raw) T; + } + + /// Instantiate a \a T in here from \a t. + template + inline T& + build (const T& t) + {]b4_assert_if([ + assert(!built); + built = true;])[ + return *new (buffer.raw) T(t); + } + + /// Construct and fill. + template + inline + variant (const T& t)]b4_assert_if([ + : built (true)])[ + { + new (buffer.raw) T(t); + } + + /// Accessor to a built \a T. + template + inline T& + as () + {]b4_assert_if([ + assert (built);])[ + return reinterpret_cast(buffer.raw); + } + + /// Const accessor to a built \a T (for %printer). + template + inline const T& + as () const + {]b4_assert_if([ + assert(built);])[ + return reinterpret_cast(buffer.raw); + } + + /// Swap the content with \a other. + template + inline void + swap (variant& other) + { + std::swap (as(), other.as()); + } + + /// Assign the content of \a other to this. + /// Destroys \a other. + template + inline void + build (variant& other) + { + build(); + swap(other); + other.destroy(); + } + + /// Destroy the stored \a T. + template + inline void + destroy () + { + as().~T();]b4_assert_if([ + built = false;])[ + } + + /// A buffer large enough to store any of the semantic values. + /// Long double is chosen as it has the strongest alignment + /// constraints. + union + { + long double align_me; + char raw[S]; + } buffer; + }; +]]) + + +## -------------------------- ## +## Adjustments for variants. ## +## -------------------------- ## + + +# How the semantic value is extracted when using variants. + +# b4_symbol_value(VAL, [TYPE]) +# ---------------------------- +m4_define([b4_symbol_value], +[m4_ifval([$2], + [$1.as< $2 >()], + [$1])]) + +# b4_symbol_value_template(VAL, [TYPE]) +# ------------------------------------- +# Same as b4_symbol_value, but used in a template method. +m4_define([b4_symbol_value_template], +[m4_ifval([$2], + [$1.template as< $2 >()], + [$1])]) -- 2.47.2