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/proto/tags.hpp> 27 #include <boost/type_traits/is_same.hpp> 28 #include <boost/fusion/include/as_vector.hpp> 29 30 /////////////////////////////////////////////////////////////////////////////// 31 namespace boost { namespace spirit { namespace qi 32 { 33 /////////////////////////////////////////////////////////////////////////// 34 // compatible STL containers 35 template <typename Container> 36 struct meta_create_container 37 { 38 typedef make_unary_proto_expr< 39 typename Container::value_type 40 , proto::tag::dereference, qi::domain 41 > make_proto_expr; 42 43 typedef typename make_proto_expr::type type; 44 callboost::spirit::qi::meta_create_container45 static type call() 46 { 47 return make_proto_expr::call(); 48 } 49 }; 50 51 /////////////////////////////////////////////////////////////////////////// 52 // Fusion sequences 53 template <typename Sequence> 54 struct meta_create_sequence 55 { 56 // create a mpl sequence from the given fusion sequence 57 typedef typename mpl::fold< 58 typename fusion::result_of::as_vector<Sequence>::type 59 , mpl::vector<>, mpl::push_back<mpl::_, mpl::_> 60 >::type sequence_type; 61 62 typedef make_nary_proto_expr< 63 sequence_type, proto::tag::shift_right, qi::domain 64 > make_proto_expr; 65 66 typedef typename make_proto_expr::type type; 67 callboost::spirit::qi::meta_create_sequence68 static type call() 69 { 70 return make_proto_expr::call(); 71 } 72 }; 73 74 /////////////////////////////////////////////////////////////////////////// 75 // the default is to use the standard streaming operator unless it's a 76 // STL container or a fusion sequence 77 78 // The default implementation will be chosen if no predefined mapping of 79 // the data type T to a Qi component is defined. 80 struct no_auto_mapping_exists {}; 81 82 template <typename T, typename Enable = void> 83 struct meta_create_impl : mpl::identity<no_auto_mapping_exists> {}; 84 85 template <typename T> 86 struct meta_create_impl<T 87 , typename enable_if<mpl::and_< 88 traits::is_container<T>, mpl::not_<traits::is_string<T> > > 89 >::type> 90 : meta_create_container<T> {}; 91 92 template <typename T> 93 struct meta_create_impl<T, typename enable_if< 94 spirit::detail::is_fusion_sequence_but_not_proto_expr<T> 95 >::type> 96 : meta_create_sequence<T> {}; 97 98 template <typename T, typename Enable = void> 99 struct meta_create : meta_create_impl<T> {}; 100 101 /////////////////////////////////////////////////////////////////////////// 102 // optional 103 template <typename T> 104 struct meta_create<boost::optional<T> > 105 { 106 typedef make_unary_proto_expr< 107 T, proto::tag::negate, qi::domain 108 > make_proto_expr; 109 110 typedef typename make_proto_expr::type type; 111 callboost::spirit::qi::meta_create112 static type call() 113 { 114 return make_proto_expr::call(); 115 } 116 }; 117 118 /////////////////////////////////////////////////////////////////////////// 119 // alternatives 120 template <BOOST_VARIANT_ENUM_PARAMS(typename T)> 121 struct meta_create<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > 122 { 123 typedef make_nary_proto_expr< 124 typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types 125 , proto::tag::bitwise_or, qi::domain 126 > make_proto_expr; 127 128 typedef typename make_proto_expr::type type; 129 callboost::spirit::qi::meta_create130 static type call() 131 { 132 return make_proto_expr::call(); 133 } 134 }; 135 136 /////////////////////////////////////////////////////////////////////////// 137 // predefined specializations for primitive components 138 139 // character generator 140 template <> 141 struct meta_create<char> 142 { 143 typedef spirit::standard::char_type type; callboost::spirit::qi::meta_create144 static type call() { return type(); } 145 }; 146 template <> 147 struct meta_create<signed char> 148 { 149 typedef spirit::standard::char_type type; callboost::spirit::qi::meta_create150 static type call() { return type(); } 151 }; 152 template <> 153 struct meta_create<wchar_t> 154 { 155 typedef spirit::standard_wide::char_type type; callboost::spirit::qi::meta_create156 static type call() { return type(); } 157 }; 158 159 template <> 160 struct meta_create<unsigned char> 161 { 162 typedef spirit::standard::char_type type; callboost::spirit::qi::meta_create163 static type call() { return type(); } 164 }; 165 166 // boolean generator 167 template <> 168 struct meta_create<bool> 169 { 170 typedef spirit::bool_type type; callboost::spirit::qi::meta_create171 static type call() { return type(); } 172 }; 173 174 // integral generators 175 template <> 176 struct meta_create<int> 177 { 178 typedef spirit::int_type type; callboost::spirit::qi::meta_create179 static type call() { return type(); } 180 }; 181 template <> 182 struct meta_create<short> 183 { 184 typedef spirit::short_type type; callboost::spirit::qi::meta_create185 static type call() { return type(); } 186 }; 187 template <> 188 struct meta_create<long> 189 { 190 typedef spirit::long_type type; callboost::spirit::qi::meta_create191 static type call() { return type(); } 192 }; 193 template <> 194 struct meta_create<unsigned int> 195 { 196 typedef spirit::uint_type type; callboost::spirit::qi::meta_create197 static type call() { return type(); } 198 }; 199 #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) 200 template <> 201 struct meta_create<unsigned short> 202 { 203 typedef spirit::ushort_type type; callboost::spirit::qi::meta_create204 static type call() { return type(); } 205 }; 206 #endif 207 template <> 208 struct meta_create<unsigned long> 209 { 210 typedef spirit::ulong_type type; callboost::spirit::qi::meta_create211 static type call() { return type(); } 212 }; 213 214 #ifdef BOOST_HAS_LONG_LONG 215 template <> 216 struct meta_create<boost::long_long_type> 217 { 218 typedef spirit::long_long_type type; callboost::spirit::qi::meta_create219 static type call() { return type(); } 220 }; 221 template <> 222 struct meta_create<boost::ulong_long_type> 223 { 224 typedef spirit::ulong_long_type type; callboost::spirit::qi::meta_create225 static type call() { return type(); } 226 }; 227 #endif 228 229 // floating point generators 230 template <> 231 struct meta_create<float> 232 { 233 typedef spirit::float_type type; callboost::spirit::qi::meta_create234 static type call() { return type(); } 235 }; 236 template <> 237 struct meta_create<double> 238 { 239 typedef spirit::double_type type; callboost::spirit::qi::meta_create240 static type call() { return type(); } 241 }; 242 template <> 243 struct meta_create<long double> 244 { 245 typedef spirit::long_double_type type; callboost::spirit::qi::meta_create246 static type call() { return type(); } 247 }; 248 }}} 249 250 /////////////////////////////////////////////////////////////////////////////// 251 namespace boost { namespace spirit { namespace traits 252 { 253 /////////////////////////////////////////////////////////////////////////// 254 // main customization point for create_parser 255 template <typename T, typename Enable = void> 256 struct create_parser : qi::meta_create<T> {}; 257 258 /////////////////////////////////////////////////////////////////////////// 259 // dispatch this to the Qi related specializations 260 template <typename T> 261 struct meta_create<qi::domain, T> 262 : create_parser<typename spirit::detail::remove_const_ref<T>::type> {}; 263 264 /////////////////////////////////////////////////////////////////////////// 265 // Check whether a valid mapping exits for the given data type to a Qi 266 // component 267 template <typename T> 268 struct meta_create_exists<qi::domain, T> 269 : mpl::not_<is_same< 270 qi::no_auto_mapping_exists 271 , typename meta_create<qi::domain, T>::type 272 > > {}; 273 }}} 274 275 #endif 276