123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- /*=============================================================================
- Copyright (c) 2001-2014 Joel de Guzman
- http://spirit.sourceforge.net/
- 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_X3_IS_SUBSTITUTE_JAN_9_2012_1049PM)
- #define BOOST_SPIRIT_X3_IS_SUBSTITUTE_JAN_9_2012_1049PM
- #include <boost/spirit/home/x3/support/traits/container_traits.hpp>
- #include <boost/fusion/include/is_sequence.hpp>
- #include <boost/fusion/include/map.hpp>
- #include <boost/fusion/include/value_at_key.hpp>
- #include <boost/fusion/adapted/mpl.hpp>
- #include <boost/mpl/placeholders.hpp>
- #include <boost/mpl/equal.hpp>
- #include <boost/mpl/apply.hpp>
- #include <boost/mpl/filter_view.hpp>
- #include <boost/mpl/size.hpp>
- #include <boost/mpl/logical.hpp>
- #include <boost/mpl/at.hpp>
- #include <boost/mpl/count_if.hpp>
- #include <boost/utility/enable_if.hpp>
- #include <boost/optional/optional.hpp>
- #include <boost/type_traits/is_same.hpp>
- namespace boost { namespace spirit { namespace x3 { namespace traits
- {
- ///////////////////////////////////////////////////////////////////////////
- // Find out if T can be a (strong) substitute for Attribute
- ///////////////////////////////////////////////////////////////////////////
- template <typename T, typename Attribute, typename Enable = void>
- struct is_substitute;
- template <typename Variant, typename Attribute>
- struct variant_has_substitute;
- namespace detail
- {
- template <typename T, typename Attribute>
- struct value_type_is_substitute
- : is_substitute<
- typename container_value<T>::type
- , typename container_value<Attribute>::type>
- {};
- template <typename T, typename Attribute, typename Enable = void>
- struct is_substitute_impl : mpl::false_ {};
- template <typename T, typename Attribute>
- struct is_substitute_impl<T, Attribute,
- typename enable_if<
- mpl::and_<
- fusion::traits::is_sequence<T>,
- fusion::traits::is_sequence<Attribute>,
- mpl::equal<T, Attribute, is_substitute<mpl::_1, mpl::_2>>
- >
- >::type>
- : mpl::true_ {};
- template <typename T, typename Attribute>
- struct is_substitute_impl<T, Attribute,
- typename enable_if<
- mpl::and_<
- is_container<T>,
- is_container<Attribute>,
- value_type_is_substitute<T, Attribute>
- >
- >::type>
- : mpl::true_ {};
- template <typename T, typename Attribute>
- struct is_substitute_impl<T, Attribute,
- typename enable_if<
- is_variant<Attribute>
- >::type>
- : variant_has_substitute<Attribute, T>
- {};
- }
- template <typename T, typename Attribute, typename Enable /*= void*/>
- struct is_substitute
- : mpl::or_<
- is_same<T, Attribute>,
- detail::is_substitute_impl<T, Attribute>> {};
- // for reference T
- template <typename T, typename Attribute, typename Enable>
- struct is_substitute<T&, Attribute, Enable>
- : is_substitute<T, Attribute, Enable> {};
- // for reference Attribute
- template <typename T, typename Attribute, typename Enable>
- struct is_substitute<T, Attribute&, Enable>
- : is_substitute<T, Attribute, Enable> {};
- // 2 element mpl tuple is compatible with fusion::map if:
- // - it's first element type is existing key in map
- // - it second element type is compatible to type stored at the key in map
- template <typename T, typename Attribute>
- struct is_substitute<T, Attribute
- , typename enable_if<
- typename mpl::eval_if<
- mpl::and_<fusion::traits::is_sequence<T>
- , fusion::traits::is_sequence<Attribute>>
- , mpl::and_<traits::has_size<T, 2>
- , fusion::traits::is_associative<Attribute>>
- , mpl::false_>::type>::type>
- {
- // checking that "p_key >> p_value" parser can
- // store it's result in fusion::map attribute
- typedef typename mpl::at_c<T, 0>::type p_key;
- typedef typename mpl::at_c<T, 1>::type p_value;
- // for simple p_key type we just check that
- // such key can be found in attr and that value under that key
- // matches p_value
- template <typename Key, typename Value, typename Map>
- struct has_kv_in_map
- : mpl::eval_if<
- fusion::result_of::has_key<Map, Key>
- , mpl::apply<
- is_substitute<
- fusion::result_of::value_at_key<mpl::_1, Key>
- , Value>
- , Map>
- , mpl::false_>
- {};
- // if p_key is variant over multiple types (as a result of
- // "(key1|key2|key3) >> p_value" parser) check that all
- // keys are found in fusion::map attribute and that values
- // under these keys match p_value
- template <typename Variant>
- struct variant_kv
- : mpl::equal_to<
- mpl::size< typename Variant::types>
- , mpl::size< mpl::filter_view<typename Variant::types
- , has_kv_in_map<mpl::_1, p_value, Attribute>>>
- >
- {};
- typedef typename
- mpl::eval_if<
- is_variant<p_key>
- , variant_kv<p_key>
- , has_kv_in_map<p_key, p_value, Attribute>
- >::type
- type;
- };
- template <typename T, typename Attribute>
- struct is_substitute<optional<T>, optional<Attribute>>
- : is_substitute<T, Attribute> {};
- }}}}
- #endif
|