X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/507aa0e2a80ee035146a6429a64df9d6e6fb8a3b..3afe18fd1fdc467e6662158275c5d8c3b7121e83:/data/variant.hh diff --git a/data/variant.hh b/data/variant.hh index 89367338..19538f6d 100644 --- a/data/variant.hh +++ b/data/variant.hh @@ -1,7 +1,6 @@ # C++ skeleton for Bison -# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 -# Free Software Foundation, Inc. +# Copyright (C) 2002-2013 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 @@ -27,7 +26,7 @@ # YYTYPE. m4_define([b4_symbol_variant], [m4_pushdef([b4_dollar_dollar], - [$2.$3< $][3 >(m4_shift3($@))])dnl + [$2.$3< $][3 > (m4_shift3($@))])dnl switch ($1) { b4_type_foreach([b4_type_action_])[]dnl @@ -52,13 +51,6 @@ m4_define([_b4_char_sizeof_dummy], 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: @@ -70,116 +62,178 @@ m4_define([b4_char_sizeof_], 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])])@}; +m4_map([ b4_symbol_tag_comment], [$@])dnl + char _b4_char_sizeof_dummy@{sizeof(b4_symbol([$1], [type]))@}; ])]) -# b4_variant_definition -# --------------------- +# b4_variant_includes +# ------------------- +# The needed includes for variants support. +m4_define([b4_variant_includes], +[b4_parse_assert_if([[#include ]])[ +#ifndef YYASSERT +# include +# define YYASSERT assert +#endif +]]) + +# b4_variant_define +# ----------------- # Define "variant". -m4_define([b4_variant_definition], -[[ - /// A char[S] buffer to store and retrieve objects. +m4_define([b4_variant_define], +[[ /// 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; -])[ + { + /// Type of *this. + typedef variant self_type; + /// Empty construction. - inline - variant ()]b4_assert_if([ - : built (false)])[ + variant ()]b4_parse_assert_if([ + : yytname_ (YY_NULL)])[ {} - /// Instantiate a \a T in here. + /// Construct and fill. template - inline T& - build () - {]b4_assert_if([ - assert (!built); - built = true;])[ - return *new (buffer.raw) T; + variant (const T& t)]b4_parse_assert_if([ + : yytname_ (typeid (T).name ())])[ + { + YYASSERT (sizeof (T) <= S); + new (yyas_ ()) T (t); } - /// Instantiate a \a T in here from \a t. + /// Destruction, allowed only if empty. + ~variant () + {]b4_parse_assert_if([ + YYASSERT (!yytname_); + ])[} + + /// Instantiate an empty \a T in here. template - inline T& - build (const T& t) - {]b4_assert_if([ - assert(!built); - built = true;])[ - return *new (buffer.raw) T(t); + T& + build () + {]b4_parse_assert_if([ + YYASSERT (!yytname_); + YYASSERT (sizeof (T) <= S); + yytname_ = typeid (T).name ();])[ + return *new (yyas_ ()) T; } - /// Construct and fill. + /// Instantiate a \a T in here from \a t. template - inline - variant (const T& t)]b4_assert_if([ - : built (true)])[ - { - new (buffer.raw) T(t); + T& + build (const T& t) + {]b4_parse_assert_if([ + YYASSERT (!yytname_); + YYASSERT (sizeof (T) <= S); + yytname_ = typeid (T).name ();])[ + return *new (yyas_ ()) T (t); } /// Accessor to a built \a T. template - inline T& + T& as () - {]b4_assert_if([ - assert (built);])[ - return reinterpret_cast(buffer.raw); + {]b4_parse_assert_if([ + YYASSERT (yytname_ == typeid (T).name ()); + YYASSERT (sizeof (T) <= S);])[ + return *yyas_ (); } /// Const accessor to a built \a T (for %printer). template - inline const T& + const T& as () const - {]b4_assert_if([ - assert(built);])[ - return reinterpret_cast(buffer.raw); + {]b4_parse_assert_if([ + YYASSERT (yytname_ == typeid (T).name ()); + YYASSERT (sizeof (T) <= S);])[ + return *yyas_ (); } - /// Swap the content with \a other. + /// Swap the content with \a other, of same type. + /// + /// Both variants must be built beforehand, because swapping the actual + /// data requires reading it (with as()), and this is not possible on + /// unconstructed variants: it would require some dynamic testing, which + /// should not be the variant's responsability. + /// Swapping between built and (possibly) non-built is done with + /// variant::move (). template - inline void - swap (variant& other) - { - std::swap (as(), other.as()); + void + swap (self_type& other) + {]b4_parse_assert_if([ + YYASSERT (yytname_); + YYASSERT (yytname_ == other.yytname_);])[ + std::swap (as (), other.as ()); } - /// Assign the content of \a other to this. + /// Move the content of \a other to this. + /// /// Destroys \a other. template - inline void - build (variant& other) + void + move (self_type& other) { - build(); - swap(other); - other.destroy(); + build (); + swap (other); + other.destroy (); + } + + /// Copy the content of \a other to this. + template + void + copy (const self_type& other) + { + build (other.as ()); } /// Destroy the stored \a T. template - inline void + void destroy () { - as().~T();]b4_assert_if([ - built = false;])[ + as ().~T ();]b4_parse_assert_if([ + yytname_ = YY_NULL;])[ } - /// A buffer large enough to store any of the semantic values. - /// Long double is chosen as it has the strongest alignment - /// constraints. + private: + /// Prohibit blind copies. + self_type& operator=(const self_type&); + variant (const self_type&); + + /// Accessor to raw memory as \a T. + template + T* + yyas_ () + { + void *yyp = yybuffer_.yyraw; + return static_cast (yyp); + } + + /// Const accessor to raw memory as \a T. + template + const T* + yyas_ () const + { + const void *yyp = yybuffer_.yyraw; + return static_cast (yyp); + } + union { - long double align_me; - char raw[S]; - } buffer; + /// Strongest alignment constraints. + long double yyalign_me; + /// A buffer large enough to store any of the semantic values. + char yyraw[S]; + } yybuffer_;]b4_parse_assert_if([ + + /// Whether the content is built: if defined, the name of the stored type. + const char *yytname_;])[ }; ]]) @@ -189,13 +243,26 @@ m4_define([b4_variant_definition], ## -------------------------- ## +# b4_value_type_declare +# --------------------- +# Declare semantic_type. +m4_define([b4_value_type_declare], +[[ /// An auxiliary type to compute the largest semantic type. + union union_type + {]b4_type_foreach([b4_char_sizeof])[}; + + /// Symbol semantic values. + typedef variant semantic_type;][]dnl +]) + + # 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.as< $2 > ()], [$1])]) # b4_symbol_value_template(VAL, [TYPE]) @@ -203,5 +270,92 @@ m4_define([b4_symbol_value], # 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.template as< $2 > ()], [$1])]) + + + +## ------------- ## +## make_SYMBOL. ## +## ------------- ## + + +# b4_symbol_constructor_declare_(SYMBOL-NUMBER) +# --------------------------------------------- +# Declare the overloaded version of make_symbol for the (common) type of +# these SYMBOL-NUMBERS. Use at class-level. +m4_define([b4_symbol_constructor_declare_], +[b4_symbol_if([$1], [is_token], [b4_symbol_if([$1], [has_id], +[ static inline + symbol_type + make_[]b4_symbol_([$1], [id]) (dnl +b4_join(b4_symbol_if([$1], [has_type], + [const b4_symbol([$1], [type])& v]), + b4_locations_if([const location_type& l]))); + +])])]) + + +# b4_symbol_constructor_declare +# ----------------------------- +# Declare symbol constructors for all the value types. +# Use at class-level. +m4_define([b4_symbol_constructor_declare], +[ // Symbol constructors declarations. +b4_symbol_foreach([b4_symbol_constructor_declare_])]) + + + +# b4_symbol_constructor_define_(SYMBOL-NUMBER) +# -------------------------------------------- +# Define symbol constructor for this SYMBOL-NUMBER. +m4_define([b4_symbol_constructor_define_], +[b4_symbol_if([$1], [is_token], [b4_symbol_if([$1], [has_id], +[ b4_parser_class_name::symbol_type + b4_parser_class_name::make_[]b4_symbol_([$1], [id]) (dnl +b4_join(b4_symbol_if([$1], [has_type], + [const b4_symbol([$1], [type])& v]), + b4_locations_if([const location_type& l]))) + { + return symbol_type (b4_join([token::b4_symbol([$1], [id])], + b4_symbol_if([$1], [has_type], [v]), + b4_locations_if([l]))); + + } + +])])]) + + +# b4_basic_symbol_constructor_declare +# ----------------------------------- +# Generate a constructor declaration for basic_symbol from given type. +m4_define([b4_basic_symbol_constructor_declare], +[[ + basic_symbol (]b4_join( + [typename Base::kind_type t], + b4_symbol_if([$1], [has_type], const b4_symbol([$1], [type])[ v]), + b4_locations_if([const location_type& l]))[); +]]) + +# b4_basic_symbol_constructor_define +# ---------------------------------- +# Generate a constructor implementation for basic_symbol from given type. +m4_define([b4_basic_symbol_constructor_define], +[[ + template + ]b4_parser_class_name[::basic_symbol::basic_symbol (]b4_join( + [typename Base::kind_type t], + b4_symbol_if([$1], [has_type], const b4_symbol([$1], [type])[ v]), + b4_locations_if([const location_type& l]))[) + : Base (t) + , value (]b4_symbol_if([$1], [has_type], [v])[)]b4_locations_if([ + , location (l)])[ + {} +]]) + +# b4_symbol_constructor_define +# ---------------------------- +# Define the overloaded versions of make_symbol for all the value types. +m4_define([b4_symbol_constructor_define], +[ // Implementation of make_symbol for each symbol type. +b4_symbol_foreach([b4_symbol_constructor_define_])])