diff options
Diffstat (limited to '3rdParty/Boost/src/boost/spirit/home/support/attributes.hpp')
-rw-r--r-- | 3rdParty/Boost/src/boost/spirit/home/support/attributes.hpp | 1358 |
1 files changed, 1358 insertions, 0 deletions
diff --git a/3rdParty/Boost/src/boost/spirit/home/support/attributes.hpp b/3rdParty/Boost/src/boost/spirit/home/support/attributes.hpp new file mode 100644 index 0000000..48bff06 --- /dev/null +++ b/3rdParty/Boost/src/boost/spirit/home/support/attributes.hpp @@ -0,0 +1,1358 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_SPIRIT_ATTRIBUTES_JANUARY_29_2007_0954AM) +#define BOOST_SPIRIT_ATTRIBUTES_JANUARY_29_2007_0954AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/support/unused.hpp> +#include <boost/spirit/home/support/has_semantic_action.hpp> +#include <boost/spirit/home/support/attributes_fwd.hpp> +#include <boost/spirit/home/support/container.hpp> +#include <boost/spirit/home/support/detail/hold_any.hpp> +#include <boost/spirit/home/support/detail/as_variant.hpp> +#include <boost/optional/optional.hpp> +#include <boost/fusion/include/transform.hpp> +#include <boost/fusion/include/filter_if.hpp> +#include <boost/fusion/include/as_vector.hpp> +#include <boost/fusion/include/push_front.hpp> +#include <boost/fusion/include/pop_front.hpp> +#include <boost/fusion/include/is_sequence.hpp> +#include <boost/fusion/include/for_each.hpp> +#include <boost/fusion/include/is_view.hpp> +#include <boost/fusion/include/mpl.hpp> +#include <boost/foreach.hpp> +#include <boost/utility/value_init.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/is_convertible.hpp> +#include <boost/mpl/eval_if.hpp> +#include <boost/mpl/end.hpp> +#include <boost/mpl/find_if.hpp> +#include <boost/mpl/identity.hpp> +#include <boost/mpl/deref.hpp> +#include <boost/mpl/distance.hpp> +#include <boost/mpl/or.hpp> +#include <boost/mpl/has_xxx.hpp> +#include <boost/mpl/equal.hpp> +#include <boost/proto/proto_fwd.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/variant.hpp> +#include <boost/range/iterator_range.hpp> +#include <boost/config.hpp> +#include <vector> +#include <utility> +#include <ios> + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { namespace traits +{ + /////////////////////////////////////////////////////////////////////////// + // This file deals with attribute related functions and meta-functions + // including generalized attribute transformation utilities for Spirit + // components. + /////////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////// + // Find out if T can be a (strong) substitute for Expected attribute + namespace detail + { + template <typename T, typename Expected> + struct value_type_is_substitute + : is_substitute< + typename container_value<T>::type + , typename container_value<Expected>::type> + {}; + + template <typename T, typename Expected, typename Enable = void> + struct is_substitute_impl : is_same<T, Expected> {}; + + template <typename T, typename Expected> + struct is_substitute_impl<T, Expected, + typename enable_if< + mpl::and_< + fusion::traits::is_sequence<T>, + fusion::traits::is_sequence<Expected>, + mpl::equal<T, Expected, is_substitute<mpl::_1, mpl::_2> > + > + >::type> + : mpl::true_ {}; + + template <typename T, typename Expected> + struct is_substitute_impl<T, Expected, + typename enable_if< + mpl::and_< + is_container<T>, + is_container<Expected>, + detail::value_type_is_substitute<T, Expected> + > + >::type> + : mpl::true_ {}; + } + + template <typename T, typename Expected, typename Enable /*= void*/> + struct is_substitute + : detail::is_substitute_impl<T, Expected> {}; + + template <typename T, typename Expected> + struct is_substitute<optional<T>, optional<Expected> > + : is_substitute<T, Expected> {}; + + template <typename T> + struct is_substitute<T, T + , typename enable_if<not_is_optional<T> >::type> + : mpl::true_ {}; + + /////////////////////////////////////////////////////////////////////////// + // Find out if T can be a weak substitute for Expected attribute + namespace detail + { + // A type, which is convertible to the attribute is at the same time + // usable as its weak substitute. + template <typename T, typename Expected, typename Enable = void> + struct is_weak_substitute_impl : is_convertible<T, Expected> {}; + +// // An exposed attribute is a weak substitute for a supplied container +// // attribute if it is a weak substitute for its value_type. This is +// // true as all character parsers are compatible with a container +// // attribute having the corresponding character type as its value_type. +// template <typename T, typename Expected> +// struct is_weak_substitute_for_value_type +// : is_weak_substitute<T, typename container_value<Expected>::type> +// {}; +// +// template <typename T, typename Expected> +// struct is_weak_substitute_impl<T, Expected, +// typename enable_if< +// mpl::and_< +// mpl::not_<is_string<T> > +// , is_string<Expected> +// , is_weak_substitute_for_value_type<T, Expected> > +// >::type> +// : mpl::true_ +// {}; + + // An exposed container attribute is a weak substitute for a supplied + // container attribute if and only if their value_types are weak + // substitutes. + template <typename T, typename Expected> + struct value_type_is_weak_substitute + : is_weak_substitute< + typename container_value<T>::type + , typename container_value<Expected>::type> + {}; + + template <typename T, typename Expected> + struct is_weak_substitute_impl<T, Expected, + typename enable_if< + mpl::and_< + is_container<T> + , is_container<Expected> + , value_type_is_weak_substitute<T, Expected> > + >::type> + : mpl::true_ {}; + + // Two fusion sequences are weak substitutes if and only if their + // elements are pairwise weak substitutes. + template <typename T, typename Expected> + struct is_weak_substitute_impl<T, Expected, + typename enable_if< + mpl::and_< + fusion::traits::is_sequence<T> + , fusion::traits::is_sequence<Expected> + , mpl::equal<T, Expected, is_weak_substitute<mpl::_1, mpl::_2> > > + >::type> + : mpl::true_ {}; + + // If this is not defined, the main template definition above will return + // true if T is convertible to the first type in a fusion::vector. We + // globally declare any non-Fusion sequence T as not compatible with any + // Fusion sequence 'Expected'. + template <typename T, typename Expected> + struct is_weak_substitute_impl<T, Expected, + typename enable_if< + mpl::and_< + mpl::not_<fusion::traits::is_sequence<T> > + , fusion::traits::is_sequence<Expected> > + >::type> + : mpl::false_ {}; + } + + // main template forwards to detail namespace, this helps older compilers + // to disambiguate things + template <typename T, typename Expected, typename Enable /*= void*/> + struct is_weak_substitute + : detail::is_weak_substitute_impl<T, Expected> {}; + + template <typename T, typename Expected> + struct is_weak_substitute<optional<T>, optional<Expected> > + : is_weak_substitute<T, Expected> {}; + + template <typename T, typename Expected> + struct is_weak_substitute<optional<T>, Expected> + : is_weak_substitute<T, Expected> {}; + + template <typename T, typename Expected> + struct is_weak_substitute<T, optional<Expected> > + : is_weak_substitute<T, Expected> {}; + +#define BOOST_SPIRIT_IS_WEAK_SUBSTITUTE(z, N, _) \ + is_weak_substitute<BOOST_PP_CAT(T, N), Expected>::type::value && \ + /***/ + + // make sure unused variant parameters do not affect the outcome + template <typename Expected> + struct is_weak_substitute<boost::detail::variant::void_, Expected> + : mpl::true_ + {}; + + template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Expected> + struct is_weak_substitute< + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Expected> + : mpl::bool_<BOOST_PP_REPEAT(BOOST_VARIANT_LIMIT_TYPES + , BOOST_SPIRIT_IS_WEAK_SUBSTITUTE, _) true> + {}; + +#undef BOOST_SPIRIT_IS_WEAK_SUBSTITUTE + + template <typename T> + struct is_weak_substitute<T, T + , typename enable_if< + mpl::and_<not_is_optional<T>, not_is_variant<T> > + >::type> + : mpl::true_ {}; + + /////////////////////////////////////////////////////////////////////////// + template <typename T, typename Enable/* = void*/> + struct is_proxy : mpl::false_ {}; + + template <typename T> + struct is_proxy<T, + typename enable_if< + mpl::and_< + fusion::traits::is_sequence<T>, + fusion::traits::is_view<T> + > + >::type> + : mpl::true_ {}; + + namespace detail + { + // By declaring a nested struct in your class/struct, you tell + // spirit that it is regarded as a variant type. The minimum + // required interface for such a variant is that it has constructors + // for various types supported by your variant and a typedef 'types' + // which is an mpl sequence of the contained types. + // + // This is an intrusive interface. For a non-intrusive interface, + // use the not_is_variant trait. + BOOST_MPL_HAS_XXX_TRAIT_DEF(adapted_variant_tag) + } + + template <typename T, typename Domain, typename Enable/* = void*/> + struct not_is_variant + : mpl::not_<detail::has_adapted_variant_tag<T> > + {}; + + template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Domain> + struct not_is_variant<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Domain> + : mpl::false_ + {}; + + template <typename T, typename Domain> + struct not_is_variant<boost::optional<T>, Domain> + : not_is_variant<T, Domain> + {}; + + // we treat every type as if it where the variant (as this meta function is + // invoked for variant types only) + template <typename T> + struct variant_type + : mpl::identity<T> + {}; + + template <typename T> + struct variant_type<boost::optional<T> > + : variant_type<T> + {}; + + /////////////////////////////////////////////////////////////////////////// + // The compute_compatible_component_variant + /////////////////////////////////////////////////////////////////////////// + namespace detail + { + // A component is compatible to a given Attribute type if the + // Attribute is the same as the expected type of the component or if + // it is convertible to the expected type. + template <typename Expected, typename Attribute> + struct attribute_is_compatible + : is_convertible<Attribute, Expected> + {}; + + template <typename Expected, typename Attribute> + struct attribute_is_compatible<Expected, boost::optional<Attribute> > + : is_convertible<Attribute, Expected> + {}; + + template <typename Container> + struct is_hold_any_container + : traits::is_hold_any<typename traits::container_value<Container>::type> + {}; + } + + template <typename Attribute, typename Expected + , typename IsNotVariant = mpl::false_, typename Enable = void> + struct compute_compatible_component_variant + : mpl::or_< + traits::detail::attribute_is_compatible<Expected, Attribute> + , traits::is_hold_any<Expected> + , mpl::eval_if< + is_container<Expected> + , traits::detail::is_hold_any_container<Expected> + , mpl::false_> > + {}; + + namespace detail + { + BOOST_MPL_HAS_XXX_TRAIT_DEF(types) + } + + template <typename Variant, typename Expected> + struct compute_compatible_component_variant<Variant, Expected, mpl::false_ + , typename enable_if<detail::has_types<Variant> >::type> + { + typedef typename traits::variant_type<Variant>::type variant_type; + typedef typename variant_type::types types; + typedef typename mpl::end<types>::type end; + + typedef typename + mpl::find_if<types, is_same<Expected, mpl::_1> >::type + iter; + + typedef typename mpl::distance< + typename mpl::begin<types>::type, iter + >::type distance; + + // true_ if the attribute matches one of the types in the variant + typedef typename mpl::not_<is_same<iter, end> >::type type; + enum { value = type::value }; + + // return the type in the variant the attribute is compatible with + typedef typename + mpl::eval_if<type, mpl::deref<iter>, mpl::identity<unused_type> >::type + compatible_type; + + // return whether the given type is compatible with the Expected type + static bool is_compatible(int which) + { + return which == distance::value; + } + }; + + template <typename Expected, typename Attribute, typename Domain> + struct compute_compatible_component + : compute_compatible_component_variant<Attribute, Expected + , typename spirit::traits::not_is_variant<Attribute, Domain>::type> {}; + + template <typename Expected, typename Domain> + struct compute_compatible_component<Expected, unused_type, Domain> + : mpl::false_ {}; + + template <typename Attribute, typename Domain> + struct compute_compatible_component<unused_type, Attribute, Domain> + : mpl::false_ {}; + + template <typename Domain> + struct compute_compatible_component<unused_type, unused_type, Domain> + : mpl::false_ {}; + + /////////////////////////////////////////////////////////////////////////// + // return the type currently stored in the given variant + template <BOOST_VARIANT_ENUM_PARAMS(typename T)> + struct variant_which<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > + { + static int call(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& v) + { + return v.which(); + } + }; + + template <typename T> + int which(T const& v) + { + return variant_which<T>::call(v); + } + + /////////////////////////////////////////////////////////////////////////// + template <typename T, typename Domain, typename Enable/* = void*/> + struct not_is_optional + : mpl::true_ + {}; + + template <typename T, typename Domain> + struct not_is_optional<boost::optional<T>, Domain> + : mpl::false_ + {}; + + /////////////////////////////////////////////////////////////////////////// + // attribute_of + // + // Get the component's attribute + /////////////////////////////////////////////////////////////////////////// + template <typename Component + , typename Context = unused_type, typename Iterator = unused_type> + struct attribute_of + { + typedef typename Component::template + attribute<Context, Iterator>::type type; + }; + + /////////////////////////////////////////////////////////////////////////// + // attribute_not_unused + // + // An mpl meta-function class that determines whether a component's + // attribute is not unused. + /////////////////////////////////////////////////////////////////////////// + template <typename Context, typename Iterator = unused_type> + struct attribute_not_unused + { + template <typename Component> + struct apply + : not_is_unused<typename + attribute_of<Component, Context, Iterator>::type> + {}; + }; + + /////////////////////////////////////////////////////////////////////////// + // Retrieve the attribute type to use from the given type + // + // This is needed to extract the correct attribute type from proxy classes + // as utilized in FUSION_ADAPT_ADT et. al. + /////////////////////////////////////////////////////////////////////////// + template <typename Attribute, typename Enable/* = void*/> + struct attribute_type : mpl::identity<Attribute> {}; + + /////////////////////////////////////////////////////////////////////////// + // Retrieve the size of a fusion sequence (compile time) + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct sequence_size + : fusion::result_of::size<T> + {}; + + template <> + struct sequence_size<unused_type> + : mpl::int_<0> + {}; + + /////////////////////////////////////////////////////////////////////////// + // Retrieve the size of an attribute (runtime) + /////////////////////////////////////////////////////////////////////////// + namespace detail + { + template <typename Attribute, typename Enable = void> + struct attribute_size_impl + { + typedef std::size_t type; + + static type call(Attribute const&) + { + return 1; + } + }; + + template <typename Attribute> + struct attribute_size_impl<Attribute + , typename enable_if< + mpl::and_< + fusion::traits::is_sequence<Attribute> + , mpl::not_<traits::is_container<Attribute> > + > + >::type> + { + typedef typename fusion::result_of::size<Attribute>::value_type type; + + static type call(Attribute const& attr) + { + return fusion::size(attr); + } + }; + + template <typename Attribute> + struct attribute_size_impl<Attribute + , typename enable_if< + mpl::and_< + traits::is_container<Attribute> + , mpl::not_<traits::is_iterator_range<Attribute> > + > + >::type> + { + typedef typename Attribute::size_type type; + + static type call(Attribute const& attr) + { + return attr.size(); + } + }; + } + + template <typename Attribute, typename Enable/* = void*/> + struct attribute_size + : detail::attribute_size_impl<Attribute> + {}; + + template <typename Attribute> + struct attribute_size<optional<Attribute> > + { + typedef typename attribute_size<Attribute>::type type; + + static type call(optional<Attribute> const& val) + { + if (!val) + return 0; + return val.get(); + } + }; + + template <typename Iterator> + struct attribute_size<iterator_range<Iterator> > + { + typedef typename boost::detail::iterator_traits<Iterator>:: + difference_type type; + + static type call(iterator_range<Iterator> const& r) + { + return boost::detail::distance(r.begin(), r.end()); + } + }; + + template <> + struct attribute_size<unused_type> + { + typedef std::size_t type; + + static type call(unused_type) + { + return 0; + } + }; + + template <typename Attribute> + typename attribute_size<Attribute>::type + size (Attribute const& attr) + { + return attribute_size<Attribute>::call(attr); + } + + /////////////////////////////////////////////////////////////////////////// + // pass_attribute + // + // Determines how we pass attributes to semantic actions. This + // may be specialized. By default, all attributes are wrapped in + // a fusion sequence, because the attribute has to be treated as being + // a single value in any case (even if it actually already is a fusion + // sequence in its own). + /////////////////////////////////////////////////////////////////////////// + template <typename Component, typename Attribute, typename Enable/* = void*/> + struct pass_attribute + { + typedef fusion::vector1<Attribute&> type; + }; + + /////////////////////////////////////////////////////////////////////////// + // Subclass a pass_attribute specialization from this to wrap + // the attribute in a tuple only IFF it is not already a fusion tuple. + /////////////////////////////////////////////////////////////////////////// + template <typename Attribute, typename Force = mpl::false_> + struct wrap_if_not_tuple + : mpl::if_< + fusion::traits::is_sequence<Attribute> + , Attribute&, fusion::vector1<Attribute&> > + {}; + + template <typename Attribute> + struct wrap_if_not_tuple<Attribute, mpl::true_> + { + typedef fusion::vector1<Attribute&> type; + }; + + template <> + struct wrap_if_not_tuple<unused_type, mpl::false_> + { + typedef unused_type type; + }; + + template <> + struct wrap_if_not_tuple<unused_type const, mpl::false_> + { + typedef unused_type type; + }; + + /////////////////////////////////////////////////////////////////////////// + // build_optional + // + // Build a boost::optional from T. Return unused_type if T is unused_type. + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct build_optional + { + typedef boost::optional<T> type; + }; + + template <typename T> + struct build_optional<boost::optional<T> > + { + typedef boost::optional<T> type; + }; + + template <> + struct build_optional<unused_type> + { + typedef unused_type type; + }; + + /////////////////////////////////////////////////////////////////////////// + // build_std_vector + // + // Build a std::vector from T. Return unused_type if T is unused_type. + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct build_std_vector + { + typedef std::vector<T> type; + }; + + template <> + struct build_std_vector<unused_type> + { + typedef unused_type type; + }; + + /////////////////////////////////////////////////////////////////////////// + // filter_unused_attributes + // + // Remove unused_types from a sequence + /////////////////////////////////////////////////////////////////////////// + + // Compute the list of all *used* attributes of sub-components + // (filter all unused attributes from the list) + template <typename Sequence> + struct filter_unused_attributes + : fusion::result_of::filter_if<Sequence, not_is_unused<mpl::_> > + {}; + + /////////////////////////////////////////////////////////////////////////// + // sequence_attribute_transform + // + // This transform is invoked for every attribute in a sequence allowing + // to modify the attribute type exposed by a component to the enclosing + // sequence component. By default no transformation is performed. + /////////////////////////////////////////////////////////////////////////// + template <typename Attribute, typename Domain> + struct sequence_attribute_transform + : mpl::identity<Attribute> + {}; + + /////////////////////////////////////////////////////////////////////////// + // permutation_attribute_transform + // + // This transform is invoked for every attribute in a sequence allowing + // to modify the attribute type exposed by a component to the enclosing + // permutation component. By default a build_optional transformation is + // performed. + /////////////////////////////////////////////////////////////////////////// + template <typename Attribute, typename Domain> + struct permutation_attribute_transform + : traits::build_optional<Attribute> + {}; + + /////////////////////////////////////////////////////////////////////////// + // sequential_or_attribute_transform + // + // This transform is invoked for every attribute in a sequential_or allowing + // to modify the attribute type exposed by a component to the enclosing + // sequential_or component. By default a build_optional transformation is + // performed. + /////////////////////////////////////////////////////////////////////////// + template <typename Attribute, typename Domain> + struct sequential_or_attribute_transform + : traits::build_optional<Attribute> + {}; + + /////////////////////////////////////////////////////////////////////////// + // build_fusion_vector + // + // Build a fusion vector from a fusion sequence. All unused attributes + // are filtered out. If the result is empty after the removal of unused + // types, return unused_type. If the input sequence is an unused_type, + // also return unused_type. + /////////////////////////////////////////////////////////////////////////// + template <typename Sequence> + struct build_fusion_vector + { + // Remove all unused attributes + typedef typename + filter_unused_attributes<Sequence>::type + filtered_attributes; + + // Build a fusion vector from a fusion sequence (Sequence), + // But *only if* the sequence is not empty. i.e. if the + // sequence is empty, our result will be unused_type. + + typedef typename + mpl::eval_if< + fusion::result_of::empty<filtered_attributes> + , mpl::identity<unused_type> + , fusion::result_of::as_vector<filtered_attributes> + >::type + type; + }; + + template <> + struct build_fusion_vector<unused_type> + { + typedef unused_type type; + }; + + /////////////////////////////////////////////////////////////////////////// + // build_attribute_sequence + // + // Build a fusion sequence attribute sequence from a sequence of + // components. Transform<T>::type is called on each element. + /////////////////////////////////////////////////////////////////////////// + template <typename Sequence, typename Context + , template <typename T, typename D> class Transform + , typename Iterator = unused_type, typename Domain = unused_type> + struct build_attribute_sequence + { + struct element_attribute + { + template <typename T> + struct result; + + template <typename F, typename Element> + struct result<F(Element)> + { + typedef typename + Transform< + typename attribute_of<Element, Context, Iterator>::type + , Domain + >::type + type; + }; + + // never called, but needed for decltype-based result_of (C++0x) +#ifndef BOOST_NO_RVALUE_REFERENCES + template <typename Element> + typename result<element_attribute(Element)>::type + operator()(Element&&) const; +#endif + }; + + // Compute the list of attributes of all sub-components + typedef typename + fusion::result_of::transform<Sequence, element_attribute>::type + type; + }; + + /////////////////////////////////////////////////////////////////////////// + // has_no_unused + // + // Test if there are no unused attributes in Sequence + /////////////////////////////////////////////////////////////////////////// + template <typename Sequence> + struct has_no_unused + : is_same< + typename mpl::find_if<Sequence, is_same<mpl::_, unused_type> >::type + , typename mpl::end<Sequence>::type> + {}; + + namespace detail + { + template <typename Sequence, bool no_unused + , int size = mpl::size<Sequence>::value> + struct build_collapsed_variant; + + // N element case, no unused + template <typename Sequence, int size> + struct build_collapsed_variant<Sequence, true, size> + : spirit::detail::as_variant<Sequence> {}; + + // N element case with unused + template <typename Sequence, int size> + struct build_collapsed_variant<Sequence, false, size> + { + typedef boost::optional< + typename spirit::detail::as_variant< + typename fusion::result_of::pop_front<Sequence>::type + >::type + > type; + }; + + // 1 element case, no unused + template <typename Sequence> + struct build_collapsed_variant<Sequence, true, 1> + : mpl::front<Sequence> {}; + + // 1 element case, with unused + template <typename Sequence> + struct build_collapsed_variant<Sequence, false, 1> + : mpl::front<Sequence> {}; + + // 2 element case, no unused + template <typename Sequence> + struct build_collapsed_variant<Sequence, true, 2> + : spirit::detail::as_variant<Sequence> {}; + + // 2 element case, with unused + template <typename Sequence> + struct build_collapsed_variant<Sequence, false, 2> + { + typedef boost::optional< + typename mpl::deref< + typename mpl::next< + typename mpl::begin<Sequence>::type + >::type + >::type + > + type; + }; + } + + /////////////////////////////////////////////////////////////////////////// + // alternative_attribute_transform + // + // This transform is invoked for every attribute in an alternative allowing + // to modify the attribute type exposed by a component to the enclosing + // alternative component. By default no transformation is performed. + /////////////////////////////////////////////////////////////////////////// + template <typename Attribute, typename Domain> + struct alternative_attribute_transform + : mpl::identity<Attribute> + {}; + + /////////////////////////////////////////////////////////////////////////// + // build_variant + // + // Build a boost::variant from a fusion sequence. build_variant makes sure + // that 1) all attributes in the variant are unique 2) puts the unused + // attribute, if there is any, to the front and 3) collapses single element + // variants, variant<T> to T. + /////////////////////////////////////////////////////////////////////////// + template <typename Sequence> + struct build_variant + { + // Remove all unused attributes. + typedef typename + filter_unused_attributes<Sequence>::type + filtered_attributes; + + typedef has_no_unused<Sequence> no_unused; + + // If the original attribute list does not contain any unused + // attributes, it is used, otherwise a single unused_type is + // pushed to the front of the list. This is to make sure that if + // there is an unused_type in the list, it is the first one. + typedef typename + mpl::eval_if< + no_unused, + mpl::identity<Sequence>, + fusion::result_of::push_front<filtered_attributes, unused_type> + >::type + attribute_sequence; + + // Make sure each of the types occur only once in the type list + typedef typename + mpl::fold< + attribute_sequence, mpl::vector<>, + mpl::if_< + mpl::contains<mpl::_1, mpl::_2>, + mpl::_1, mpl::push_back<mpl::_1, mpl::_2> + > + >::type + no_duplicates; + + // If there is only one type in the list of types we strip off the + // variant. IOTW, collapse single element variants, variant<T> to T. + // Take note that this also collapses variant<unused_type, T> to T. + typedef typename + traits::detail::build_collapsed_variant< + no_duplicates, no_unused::value>::type + type; + }; + + /////////////////////////////////////////////////////////////////////////// + // transform_attribute + // + // Sometimes the user needs to transform the attribute types for certain + // attributes. This template can be used as a customization point, where + // the user is able specify specific transformation rules for any attribute + // type. + /////////////////////////////////////////////////////////////////////////// + template <typename Exposed, typename Transformed, typename Domain + , typename Enable/* = void*/> + struct transform_attribute; + + /////////////////////////////////////////////////////////////////////////// + template <typename Domain, typename Transformed, typename Exposed> + typename spirit::result_of::pre_transform<Exposed, Transformed, Domain>::type + pre_transform(Exposed& attr BOOST_PROTO_DISABLE_IF_IS_CONST(Exposed)) + { + return transform_attribute<Exposed, Transformed, Domain>::pre(attr); + } + + template <typename Domain, typename Transformed, typename Exposed> + typename spirit::result_of::pre_transform<Exposed const, Transformed, Domain>::type + pre_transform(Exposed const& attr) + { + return transform_attribute<Exposed const, Transformed, Domain>::pre(attr); + } + + /////////////////////////////////////////////////////////////////////////// + // make_attribute + // + // All parsers and generators have specific attribute types. + // Spirit parsers and generators are passed an attribute; these are either + // references to the expected type, or an unused_type -- to flag that we do + // not care about the attribute. For semantic actions, however, we need to + // have a real value to pass to the semantic action. If the client did not + // provide one, we will have to synthesize the value. This class takes care + // of that. *Note that this behavior has changed. From Boost 1.47, semantic + // actions always take in the passed attribute as-is if the PP constant: + // BOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT is defined. + /////////////////////////////////////////////////////////////////////////// + template <typename Attribute, typename ActualAttribute> + struct make_attribute + { + typedef typename remove_const<Attribute>::type attribute_type; + typedef typename + mpl::if_< + is_same<typename remove_const<ActualAttribute>::type, unused_type> + , attribute_type + , ActualAttribute&>::type + type; + + typedef typename + mpl::if_< + is_same<typename remove_const<ActualAttribute>::type, unused_type> + , attribute_type + , ActualAttribute>::type + value_type; + + static Attribute call(unused_type) + { + // synthesize the attribute/parameter + return boost::get(value_initialized<attribute_type>()); + } + + template <typename T> + static T& call(T& value) + { + return value; // just pass the one provided + } + }; + + template <typename Attribute, typename ActualAttribute> + struct make_attribute<Attribute&, ActualAttribute> + : make_attribute<Attribute, ActualAttribute> + {}; + + template <typename Attribute, typename ActualAttribute> + struct make_attribute<Attribute const&, ActualAttribute> + : make_attribute<Attribute const, ActualAttribute> + {}; + + template <typename ActualAttribute> + struct make_attribute<unused_type, ActualAttribute> + { + typedef unused_type type; + typedef unused_type value_type; + static unused_type call(unused_type) + { + return unused; + } + }; + + /////////////////////////////////////////////////////////////////////////// + // swap_impl + // + // Swap (with proper handling of unused_types) + /////////////////////////////////////////////////////////////////////////// + template <typename A, typename B> + void swap_impl(A& a, B& b) + { + A temp = a; + a = b; + b = temp; + } + + template <typename T> + void swap_impl(T& a, T& b) + { + using namespace std; + swap(a, b); + } + + template <typename A> + void swap_impl(A&, unused_type) + { + } + + template <typename A> + void swap_impl(unused_type, A&) + { + } + + inline void swap_impl(unused_type, unused_type) + { + } + + /////////////////////////////////////////////////////////////////////////// + // Strips single element fusion vectors into its 'naked' + // form: vector<T> --> T + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct strip_single_element_vector + { + typedef T type; + }; + + template <typename T> + struct strip_single_element_vector<fusion::vector1<T> > + { + typedef T type; + }; + + template <typename T> + struct strip_single_element_vector<fusion::vector<T> > + { + typedef T type; + }; + + /////////////////////////////////////////////////////////////////////////// + // meta function to return whether the argument is a one element fusion + // sequence + /////////////////////////////////////////////////////////////////////////// + template <typename T + , bool IsFusionSeq = fusion::traits::is_sequence<T>::value + , bool IsProtoExpr = proto::is_expr<T>::value> + struct one_element_sequence + : mpl::false_ + {}; + + template <typename T> + struct one_element_sequence<T, true, false> + : mpl::bool_<mpl::size<T>::value == 1> + {}; + + /////////////////////////////////////////////////////////////////////////// + // clear + // + // Clear data efficiently + /////////////////////////////////////////////////////////////////////////// + template <typename T> + void clear(T& val); + + namespace detail + { + // this is used by the variant and fusion sequence dispatch + struct clear_visitor : static_visitor<> + { + template <typename T> + void operator()(T& val) const + { + spirit::traits::clear(val); + } + }; + + // default + template <typename T> + void clear_impl2(T& val, mpl::false_) + { + val = T(); + } + + // for fusion sequences + template <typename T> + void clear_impl2(T& val, mpl::true_) + { + fusion::for_each(val, clear_visitor()); + } + + // dispatch default or fusion sequence + template <typename T> + void clear_impl(T& val, mpl::false_) + { + clear_impl2(val, fusion::traits::is_sequence<T>()); + } + + // STL containers + template <typename T> + void clear_impl(T& val, mpl::true_) + { + val.clear(); + } + } + + template <typename T, typename Enable/* = void*/> + struct clear_value + { + static void call(T& val) + { + detail::clear_impl(val, typename is_container<T>::type()); + } + }; + + // optionals + template <typename T> + struct clear_value<boost::optional<T> > + { + static void call(boost::optional<T>& val) + { + if (val) + val = none_t(); // leave optional uninitialized + } + }; + + // variants + template <BOOST_VARIANT_ENUM_PARAMS(typename T)> + struct clear_value<variant<BOOST_VARIANT_ENUM_PARAMS(T)> > + { + static void call(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& val) + { + apply_visitor(detail::clear_visitor(), val); + } + }; + + // iterator range + template <typename T> + struct clear_value<iterator_range<T> > + { + static void call(iterator_range<T>& val) + { + val = iterator_range<T>(val.end(), val.end()); + } + }; + + // main dispatch + template <typename T> + void clear(T& val) + { + clear_value<T>::call(val); + } + + // for unused + inline void clear(unused_type) + { + } + + /////////////////////////////////////////////////////////////////////////// + namespace detail + { + template <typename Out> + struct print_fusion_sequence + { + print_fusion_sequence(Out& out) + : out(out), is_first(true) {} + + typedef void result_type; + + template <typename T> + void operator()(T const& val) const + { + if (is_first) + is_first = false; + else + out << ", "; + spirit::traits::print_attribute(out, val); + } + + Out& out; + mutable bool is_first; + }; + + // print elements in a variant + template <typename Out> + struct print_visitor : static_visitor<> + { + print_visitor(Out& out) : out(out) {} + + template <typename T> + void operator()(T const& val) const + { + spirit::traits::print_attribute(out, val); + } + + Out& out; + }; + } + + template <typename Out, typename T, typename Enable> + struct print_attribute_debug + { + // for plain data types + template <typename T_> + static void call_impl3(Out& out, T_ const& val, mpl::false_) + { + out << val; + } + + // for fusion data types + template <typename T_> + static void call_impl3(Out& out, T_ const& val, mpl::true_) + { + out << '['; + fusion::for_each(val, detail::print_fusion_sequence<Out>(out)); + out << ']'; + } + + // non-stl container + template <typename T_> + static void call_impl2(Out& out, T_ const& val, mpl::false_) + { + call_impl3(out, val, fusion::traits::is_sequence<T_>()); + } + + // stl container + template <typename T_> + static void call_impl2(Out& out, T_ const& val, mpl::true_) + { + out << '['; + if (!traits::is_empty(val)) + { + bool first = true; + typename container_iterator<T_ const>::type iend = traits::end(val); + for (typename container_iterator<T_ const>::type i = traits::begin(val); + !traits::compare(i, iend); traits::next(i)) + { + if (!first) + out << ", "; + first = false; + spirit::traits::print_attribute(out, traits::deref(i)); + } + } + out << ']'; + } + + // for variant types + template <typename T_> + static void call_impl(Out& out, T_ const& val, mpl::false_) + { + apply_visitor(detail::print_visitor<Out>(out), val); + } + + // for non-variant types + template <typename T_> + static void call_impl(Out& out, T_ const& val, mpl::true_) + { + call_impl2(out, val, is_container<T_>()); + } + + // main entry point + static void call(Out& out, T const& val) + { + call_impl(out, val, not_is_variant<T>()); + } + }; + + template <typename Out, typename T> + struct print_attribute_debug<Out, boost::optional<T> > + { + static void call(Out& out, boost::optional<T> const& val) + { + if (val) + spirit::traits::print_attribute(out, *val); + else + out << "[empty]"; + } + }; + + /////////////////////////////////////////////////////////////////////////// + template <typename Out, typename T> + inline void print_attribute(Out& out, T const& val) + { + print_attribute_debug<Out, T>::call(out, val); + } + + template <typename Out> + inline void print_attribute(Out&, unused_type) + { + } + + /////////////////////////////////////////////////////////////////////////// + // generate debug output for lookahead token (character) stream + namespace detail + { + struct token_printer_debug_for_chars + { + template<typename Out, typename Char> + static void print(Out& o, Char c) + { + using namespace std; // allow for ADL to find the proper iscntrl + + if (c == static_cast<Char>('\a')) + o << "\\a"; + else if (c == static_cast<Char>('\b')) + o << "\\b"; + else if (c == static_cast<Char>('\f')) + o << "\\f"; + else if (c == static_cast<Char>('\n')) + o << "\\n"; + else if (c == static_cast<Char>('\r')) + o << "\\r"; + else if (c == static_cast<Char>('\t')) + o << "\\t"; + else if (c == static_cast<Char>('\v')) + o << "\\v"; + else if (c >= 0 && c < 127 && iscntrl(c)) + o << "\\" << std::oct << static_cast<int>(c); + else + o << static_cast<char>(c); + } + }; + + // for token types where the comparison with char constants wouldn't work + struct token_printer_debug + { + template<typename Out, typename T> + static void print(Out& o, T const& val) + { + o << val; + } + }; + } + + template <typename T, typename Enable> + struct token_printer_debug + : mpl::if_< + mpl::and_< + is_convertible<T, char>, is_convertible<char, T> > + , detail::token_printer_debug_for_chars + , detail::token_printer_debug>::type + {}; + + template <typename Out, typename T> + inline void print_token(Out& out, T const& val) + { + // allow to customize the token printer routine + token_printer_debug<T>::print(out, val); + } +}}} + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { namespace result_of +{ + template <typename Exposed, typename Transformed, typename Domain> + struct pre_transform + : traits::transform_attribute<Exposed, Transformed, Domain> + {}; +}}} + + +#endif |