123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344 |
- /*=============================================================================
- 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/core/invoke_swap.hpp>
- #include <boost/core/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::core::invoke_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
|