1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381 |
- /*=============================================================================
- 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/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();
- }
- };
- 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 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_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;
- };
- ///////////////////////////////////////////////////////////////////////////
- // 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
|