Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 10:02:38

0001 /*=============================================================================
0002     Copyright (c) 2001-2014 Joel de Guzman
0003     http://spirit.sourceforge.net/
0004 
0005     Distributed under the Boost Software License, Version 1.0. (See accompanying
0006     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 =============================================================================*/
0008 #if !defined(BOOST_SPIRIT_X3_IS_SUBSTITUTE_JAN_9_2012_1049PM)
0009 #define BOOST_SPIRIT_X3_IS_SUBSTITUTE_JAN_9_2012_1049PM
0010 
0011 #include <boost/spirit/home/x3/support/traits/container_traits.hpp>
0012 #include <boost/fusion/include/is_sequence.hpp>
0013 #include <boost/fusion/include/map.hpp>
0014 #include <boost/fusion/include/value_at_key.hpp>
0015 #include <boost/fusion/adapted/mpl.hpp>
0016 #include <boost/mpl/placeholders.hpp>
0017 #include <boost/mpl/equal.hpp>
0018 #include <boost/mpl/apply.hpp>
0019 #include <boost/mpl/filter_view.hpp>
0020 #include <boost/mpl/size.hpp>
0021 #include <boost/mpl/logical.hpp>
0022 #include <boost/mpl/at.hpp>
0023 #include <boost/mpl/count_if.hpp>
0024 #include <boost/utility/enable_if.hpp>
0025 #include <boost/optional/optional.hpp>
0026 #include <boost/type_traits/is_same.hpp>
0027 
0028 namespace boost { namespace spirit { namespace x3 { namespace traits
0029 {
0030     ///////////////////////////////////////////////////////////////////////////
0031     // Find out if T can be a (strong) substitute for Attribute
0032     ///////////////////////////////////////////////////////////////////////////
0033     template <typename T, typename Attribute, typename Enable = void>
0034     struct is_substitute;
0035 
0036     template <typename Variant, typename Attribute>
0037     struct variant_has_substitute;
0038 
0039     namespace detail
0040     {
0041         template <typename T, typename Attribute>
0042         struct value_type_is_substitute
0043           : is_substitute<
0044                 typename container_value<T>::type
0045               , typename container_value<Attribute>::type>
0046         {};
0047 
0048         template <typename T, typename Attribute, typename Enable = void>
0049         struct is_substitute_impl : mpl::false_ {};
0050 
0051         template <typename T, typename Attribute>
0052         struct is_substitute_impl<T, Attribute,
0053             typename enable_if<
0054                 mpl::and_<
0055                     fusion::traits::is_sequence<T>,
0056                     fusion::traits::is_sequence<Attribute>,
0057                     mpl::equal<T, Attribute, is_substitute<mpl::_1, mpl::_2>>
0058                 >
0059             >::type>
0060           : mpl::true_ {};
0061 
0062         template <typename T, typename Attribute>
0063         struct is_substitute_impl<T, Attribute,
0064             typename enable_if<
0065                 mpl::and_<
0066                     is_container<T>,
0067                     is_container<Attribute>,
0068                     value_type_is_substitute<T, Attribute>
0069                 >
0070             >::type>
0071           : mpl::true_ {};
0072 
0073         template <typename T, typename Attribute>
0074         struct is_substitute_impl<T, Attribute,
0075             typename enable_if<
0076                 is_variant<Attribute>
0077             >::type>
0078           : variant_has_substitute<Attribute, T>
0079         {};
0080     }
0081 
0082     template <typename T, typename Attribute, typename Enable /*= void*/>
0083     struct is_substitute
0084         : mpl::or_<
0085               is_same<T, Attribute>,
0086               detail::is_substitute_impl<T, Attribute>> {};
0087 
0088     // for reference T
0089     template <typename T, typename Attribute, typename Enable>
0090     struct is_substitute<T&, Attribute, Enable>
0091         : is_substitute<T, Attribute, Enable> {};
0092 
0093     // for reference Attribute
0094     template <typename T, typename Attribute, typename Enable>
0095     struct is_substitute<T, Attribute&, Enable>
0096         : is_substitute<T, Attribute, Enable> {};
0097 
0098     // 2 element mpl tuple is compatible with fusion::map if:
0099     // - it's first element type is existing key in map
0100     // - it second element type is compatible to type stored at the key in map
0101     template <typename T, typename Attribute>
0102     struct is_substitute<T, Attribute
0103     , typename enable_if<
0104           typename mpl::eval_if<
0105           mpl::and_<fusion::traits::is_sequence<T>
0106                 , fusion::traits::is_sequence<Attribute>>
0107           , mpl::and_<traits::has_size<T, 2>
0108                , fusion::traits::is_associative<Attribute>>
0109           , mpl::false_>::type>::type>
0110 
0111     {
0112         // checking that "p_key >> p_value" parser can
0113         // store it's result in fusion::map attribute
0114         typedef typename mpl::at_c<T, 0>::type p_key;
0115         typedef typename mpl::at_c<T, 1>::type p_value;
0116 
0117         // for simple p_key type we just check that
0118         // such key can be found in attr and that value under that key
0119         // matches p_value
0120         template <typename Key, typename Value, typename Map>
0121         struct has_kv_in_map
0122             : mpl::eval_if<
0123                 fusion::result_of::has_key<Map, Key>
0124               , mpl::apply<
0125                     is_substitute<
0126                         fusion::result_of::value_at_key<mpl::_1, Key>
0127                       , Value>
0128                       , Map>
0129               , mpl::false_>
0130         {};
0131 
0132         // if p_key is variant over multiple types (as a result of
0133         // "(key1|key2|key3) >> p_value" parser) check that all
0134         // keys are found in fusion::map attribute and that values
0135         // under these keys match p_value
0136         template <typename Variant>
0137         struct variant_kv
0138             : mpl::equal_to<
0139                 mpl::size< typename Variant::types>
0140               , mpl::size< mpl::filter_view<typename Variant::types
0141               , has_kv_in_map<mpl::_1, p_value, Attribute>>>
0142             >
0143         {};
0144 
0145         typedef typename
0146             mpl::eval_if<
0147                 is_variant<p_key>
0148               , variant_kv<p_key>
0149               , has_kv_in_map<p_key, p_value, Attribute>
0150             >::type
0151         type;
0152     };
0153 
0154     template <typename T, typename Attribute>
0155     struct is_substitute<optional<T>, optional<Attribute>>
0156       : is_substitute<T, Attribute> {};
0157 }}}}
0158 
0159 #endif