12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343 |
- /*=============================================================================
- Copyright (c) 2001-2011 Joel de Guzman
- Copyright (c) 2001-2012 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/type_traits/is_same.hpp>
- #include <boost/type_traits/is_convertible.hpp>
- #include <boost/type_traits/is_reference.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/traits.hpp>
- #include <boost/utility/enable_if.hpp>
- #include <boost/variant.hpp>
- #include <boost/range/range_fwd.hpp>
- #include <boost/config.hpp>
- #include <iterator> // for std::iterator_traits, std::distance
- #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> {};
- #if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
- template <typename T, typename Expected>
- struct is_weak_substitute<boost::variant<T>, Expected>
- : is_weak_substitute<T, Expected>
- {};
- template <typename T0, typename T1, typename ...TN, typename Expected>
- struct is_weak_substitute<boost::variant<T0, T1, TN...>,
- Expected>
- : mpl::bool_<is_weak_substitute<T0, Expected>::type::value &&
- is_weak_substitute<boost::variant<T1, TN...>, Expected>::type::value>
- {};
- #else
- #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
- #endif
- 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_
- {};
- // 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>
- {};
- template <typename T, typename Domain>
- struct not_is_variant_or_variant_in_optional
- : not_is_variant<typename variant_type<T>::type, Domain>
- {};
- ///////////////////////////////////////////////////////////////////////////
- // 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<typename variant_type<Variant>::type> >::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 not_is_variant_or_variant_in_optional<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 traits::size(val.get());
- }
- };
- namespace detail
- {
- struct attribute_size_visitor : static_visitor<std::size_t>
- {
- template <typename T>
- std::size_t operator()(T const& val) const
- {
- return spirit::traits::size(val);
- }
- };
- }
- template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
- struct attribute_size<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
- {
- typedef std::size_t type;
- static type call(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& val)
- {
- return apply_visitor(detail::attribute_size_visitor(), val);
- }
- };
- template <typename Iterator>
- struct attribute_size<iterator_range<Iterator> >
- {
- typedef typename std::iterator_traits<Iterator>::
- difference_type type;
- static type call(iterator_range<Iterator> const& r)
- {
- return std::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_CXX11_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;
- };
- namespace detail {
- // Domain-agnostic class template partial specializations and
- // type agnostic domain partial specializations are ambious.
- // To resolve the ambiguity type agnostic domain partial
- // specializations are dispatched via intermediate type.
- template <typename Exposed, typename Transformed, typename Domain>
- struct transform_attribute_base;
- template <typename Attribute>
- struct synthesize_attribute
- {
- typedef Attribute type;
- static Attribute pre(unused_type) { return Attribute(); }
- static void post(unused_type, Attribute const&) {}
- static void fail(unused_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.
- //
- // Note: the transformations involving unused_type are internal details
- // and may be subject to change at any time.
- //
- ///////////////////////////////////////////////////////////////////////////
- template <typename Exposed, typename Transformed, typename Domain
- , typename Enable/* = void*/>
- struct transform_attribute
- : detail::transform_attribute_base<Exposed, Transformed, Domain>
- {
- BOOST_STATIC_ASSERT_MSG(!is_reference<Exposed>::value,
- "Exposed cannot be a reference type");
- BOOST_STATIC_ASSERT_MSG(!is_reference<Transformed>::value,
- "Transformed cannot be a reference type");
- };
- template <typename Transformed, typename Domain>
- struct transform_attribute<unused_type, Transformed, Domain>
- : detail::synthesize_attribute<Transformed>
- {};
- template <typename Transformed, typename Domain>
- struct transform_attribute<unused_type const, Transformed, Domain>
- : detail::synthesize_attribute<Transformed>
- {};
- ///////////////////////////////////////////////////////////////////////////
- // 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)
- {
- boost::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;
- };
- #if !defined(BOOST_FUSION_HAS_VARIADIC_VECTOR)
- template <typename T>
- struct strip_single_element_vector<fusion::vector1<T> >
- {
- typedef T type;
- };
- #endif
- 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; // 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);
- }
- }}}
- #endif
|