1 // Copyright (c) 2001-2011 Hartmut Kaiser 2 // 3 // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 #if !defined(BOOST_SPIRIT_QI_META_CREATE_NOV_21_2009_0432PM) 7 #define BOOST_SPIRIT_QI_META_CREATE_NOV_21_2009_0432PM 8 9 #if defined(_MSC_VER) 10 #pragma once 11 #endif 12 13 #include <boost/spirit/home/qi/domain.hpp> 14 #include <boost/spirit/home/support/common_terminals.hpp> 15 #include <boost/spirit/home/support/auto/meta_create.hpp> 16 17 #include <boost/utility/enable_if.hpp> 18 #include <boost/variant.hpp> 19 #include <boost/optional.hpp> 20 #include <boost/config.hpp> 21 #include <boost/mpl/and.hpp> 22 #include <boost/mpl/not.hpp> 23 #include <boost/mpl/fold.hpp> 24 #include <boost/mpl/vector.hpp> 25 #include <boost/mpl/push_back.hpp> 26 #include <boost/type_traits/is_same.hpp> 27 #include <boost/fusion/include/as_vector.hpp> 28 29 /////////////////////////////////////////////////////////////////////////////// 30 namespace boost { namespace spirit { namespace qi 31 { 32 /////////////////////////////////////////////////////////////////////////// 33 // compatible STL containers 34 template <typename Container> 35 struct meta_create_container 36 { 37 typedef make_unary_proto_expr< 38 typename Container::value_type 39 , proto::tag::dereference, qi::domain 40 > make_proto_expr; 41 42 typedef typename make_proto_expr::type type; 43 callboost::spirit::qi::meta_create_container44 static type call() 45 { 46 return make_proto_expr::call(); 47 } 48 }; 49 50 /////////////////////////////////////////////////////////////////////////// 51 // Fusion sequences 52 template <typename Sequence> 53 struct meta_create_sequence 54 { 55 // create a mpl sequence from the given fusion sequence 56 typedef typename mpl::fold< 57 typename fusion::result_of::as_vector<Sequence>::type 58 , mpl::vector<>, mpl::push_back<mpl::_, mpl::_> 59 >::type sequence_type; 60 61 typedef make_nary_proto_expr< 62 sequence_type, proto::tag::shift_right, qi::domain 63 > make_proto_expr; 64 65 typedef typename make_proto_expr::type type; 66 callboost::spirit::qi::meta_create_sequence67 static type call() 68 { 69 return make_proto_expr::call(); 70 } 71 }; 72 73 /////////////////////////////////////////////////////////////////////////// 74 // the default is to use the standard streaming operator unless it's a 75 // STL container or a fusion sequence 76 77 // The default implementation will be chosen if no predefined mapping of 78 // the data type T to a Qi component is defined. 79 struct no_auto_mapping_exists {}; 80 81 template <typename T, typename Enable = void> 82 struct meta_create_impl : mpl::identity<no_auto_mapping_exists> {}; 83 84 template <typename T> 85 struct meta_create_impl<T 86 , typename enable_if<mpl::and_< 87 traits::is_container<T>, mpl::not_<traits::is_string<T> > > 88 >::type> 89 : meta_create_container<T> {}; 90 91 template <typename T> 92 struct meta_create_impl<T, typename enable_if< 93 spirit::detail::is_fusion_sequence_but_not_proto_expr<T> 94 >::type> 95 : meta_create_sequence<T> {}; 96 97 template <typename T, typename Enable = void> 98 struct meta_create : meta_create_impl<T> {}; 99 100 /////////////////////////////////////////////////////////////////////////// 101 // optional 102 template <typename T> 103 struct meta_create<boost::optional<T> > 104 { 105 typedef make_unary_proto_expr< 106 T, proto::tag::negate, qi::domain 107 > make_proto_expr; 108 109 typedef typename make_proto_expr::type type; 110 callboost::spirit::qi::meta_create111 static type call() 112 { 113 return make_proto_expr::call(); 114 } 115 }; 116 117 /////////////////////////////////////////////////////////////////////////// 118 // alternatives 119 template <BOOST_VARIANT_ENUM_PARAMS(typename T)> 120 struct meta_create<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > 121 { 122 typedef make_nary_proto_expr< 123 typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types 124 , proto::tag::bitwise_or, qi::domain 125 > make_proto_expr; 126 127 typedef typename make_proto_expr::type type; 128 callboost::spirit::qi::meta_create129 static type call() 130 { 131 return make_proto_expr::call(); 132 } 133 }; 134 135 /////////////////////////////////////////////////////////////////////////// 136 // predefined specializations for primitive components 137 138 // character generator 139 template <> 140 struct meta_create<char> 141 { 142 typedef spirit::standard::char_type type; callboost::spirit::qi::meta_create143 static type call() { return type(); } 144 }; 145 template <> 146 struct meta_create<signed char> 147 { 148 typedef spirit::standard::char_type type; callboost::spirit::qi::meta_create149 static type call() { return type(); } 150 }; 151 template <> 152 struct meta_create<wchar_t> 153 { 154 typedef spirit::standard_wide::char_type type; callboost::spirit::qi::meta_create155 static type call() { return type(); } 156 }; 157 158 template <> 159 struct meta_create<unsigned char> 160 { 161 typedef spirit::standard::char_type type; callboost::spirit::qi::meta_create162 static type call() { return type(); } 163 }; 164 165 // boolean generator 166 template <> 167 struct meta_create<bool> 168 { 169 typedef spirit::bool_type type; callboost::spirit::qi::meta_create170 static type call() { return type(); } 171 }; 172 173 // integral generators 174 template <> 175 struct meta_create<int> 176 { 177 typedef spirit::int_type type; callboost::spirit::qi::meta_create178 static type call() { return type(); } 179 }; 180 template <> 181 struct meta_create<short> 182 { 183 typedef spirit::short_type type; callboost::spirit::qi::meta_create184 static type call() { return type(); } 185 }; 186 template <> 187 struct meta_create<long> 188 { 189 typedef spirit::long_type type; callboost::spirit::qi::meta_create190 static type call() { return type(); } 191 }; 192 template <> 193 struct meta_create<unsigned int> 194 { 195 typedef spirit::uint_type type; callboost::spirit::qi::meta_create196 static type call() { return type(); } 197 }; 198 #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) 199 template <> 200 struct meta_create<unsigned short> 201 { 202 typedef spirit::ushort_type type; callboost::spirit::qi::meta_create203 static type call() { return type(); } 204 }; 205 #endif 206 template <> 207 struct meta_create<unsigned long> 208 { 209 typedef spirit::ulong_type type; callboost::spirit::qi::meta_create210 static type call() { return type(); } 211 }; 212 213 #ifdef BOOST_HAS_LONG_LONG 214 template <> 215 struct meta_create<boost::long_long_type> 216 { 217 typedef spirit::long_long_type type; callboost::spirit::qi::meta_create218 static type call() { return type(); } 219 }; 220 template <> 221 struct meta_create<boost::ulong_long_type> 222 { 223 typedef spirit::ulong_long_type type; callboost::spirit::qi::meta_create224 static type call() { return type(); } 225 }; 226 #endif 227 228 // floating point generators 229 template <> 230 struct meta_create<float> 231 { 232 typedef spirit::float_type type; callboost::spirit::qi::meta_create233 static type call() { return type(); } 234 }; 235 template <> 236 struct meta_create<double> 237 { 238 typedef spirit::double_type type; callboost::spirit::qi::meta_create239 static type call() { return type(); } 240 }; 241 template <> 242 struct meta_create<long double> 243 { 244 typedef spirit::long_double_type type; callboost::spirit::qi::meta_create245 static type call() { return type(); } 246 }; 247 }}} 248 249 /////////////////////////////////////////////////////////////////////////////// 250 namespace boost { namespace spirit { namespace traits 251 { 252 /////////////////////////////////////////////////////////////////////////// 253 // main customization point for create_parser 254 template <typename T, typename Enable = void> 255 struct create_parser : qi::meta_create<T> {}; 256 257 /////////////////////////////////////////////////////////////////////////// 258 // dispatch this to the Qi related specializations 259 template <typename T> 260 struct meta_create<qi::domain, T> 261 : create_parser<typename spirit::detail::remove_const_ref<T>::type> {}; 262 263 /////////////////////////////////////////////////////////////////////////// 264 // Check whether a valid mapping exits for the given data type to a Qi 265 // component 266 template <typename T> 267 struct meta_create_exists<qi::domain, T> 268 : mpl::not_<is_same< 269 qi::no_auto_mapping_exists 270 , typename meta_create<qi::domain, T>::type 271 > > {}; 272 }}} 273 274 #endif 275