1 /*============================================================================= 2 Copyright (c) 2001-2011 Joel de Guzman 3 Copyright (c) 2011 Bryce Lelbach 4 5 Distributed under the Boost Software License, Version 1.0. (See accompanying 6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 ==============================================================================*/ 8 #if !defined(BOOST_SPIRIT_REAL_APRIL_18_2006_0850AM) 9 #define BOOST_SPIRIT_REAL_APRIL_18_2006_0850AM 10 11 #if defined(_MSC_VER) 12 #pragma once 13 #endif 14 15 #include <boost/spirit/home/qi/skip_over.hpp> 16 #include <boost/spirit/home/qi/detail/enable_lit.hpp> 17 #include <boost/spirit/home/qi/meta_compiler.hpp> 18 #include <boost/spirit/home/qi/parser.hpp> 19 #include <boost/spirit/home/qi/numeric/real_policies.hpp> 20 #include <boost/spirit/home/qi/numeric/numeric_utils.hpp> 21 #include <boost/spirit/home/qi/numeric/detail/real_impl.hpp> 22 #include <boost/spirit/home/support/common_terminals.hpp> 23 #include <boost/type_traits/is_same.hpp> 24 25 namespace boost { namespace spirit 26 { 27 namespace qi 28 { 29 /////////////////////////////////////////////////////////////////////// 30 // forward declaration only 31 template <typename T> 32 struct real_policies; 33 34 /////////////////////////////////////////////////////////////////////// 35 // This is the class that the user can instantiate directly in 36 // order to create a customized real parser 37 template <typename T = double, typename Policies = real_policies<T> > 38 struct real_parser 39 : spirit::terminal<tag::stateful_tag<Policies, tag::double_, T> > 40 { 41 typedef tag::stateful_tag<Policies, tag::double_, T> tag_type; 42 real_parserboost::spirit::qi::real_parser43 real_parser() {} real_parserboost::spirit::qi::real_parser44 real_parser(Policies const& p) 45 : spirit::terminal<tag_type>(p) {} 46 }; 47 } 48 49 /////////////////////////////////////////////////////////////////////////// 50 // Enablers 51 /////////////////////////////////////////////////////////////////////////// 52 template <> // enables float_ 53 struct use_terminal<qi::domain, tag::float_> 54 : mpl::true_ {}; 55 56 template <> // enables double_ 57 struct use_terminal<qi::domain, tag::double_> 58 : mpl::true_ {}; 59 60 template <> // enables long_double 61 struct use_terminal<qi::domain, tag::long_double> 62 : mpl::true_ {}; 63 64 /////////////////////////////////////////////////////////////////////////// 65 template <typename A0> // enables lit(n) 66 struct use_terminal<qi::domain 67 , terminal_ex<tag::lit, fusion::vector1<A0> > 68 , typename enable_if<is_same<A0, float> >::type> 69 : mpl::true_ {}; 70 71 template <typename A0> // enables lit(n) 72 struct use_terminal<qi::domain 73 , terminal_ex<tag::lit, fusion::vector1<A0> > 74 , typename enable_if<is_same<A0, double> >::type> 75 : mpl::true_ {}; 76 77 template <typename A0> // enables lit(n) 78 struct use_terminal<qi::domain 79 , terminal_ex<tag::lit, fusion::vector1<A0> > 80 , typename enable_if<is_same<A0, long double> >::type> 81 : mpl::true_ {}; 82 83 /////////////////////////////////////////////////////////////////////////// 84 template <typename A0> // enables float_(...) 85 struct use_terminal<qi::domain 86 , terminal_ex<tag::float_, fusion::vector1<A0> > 87 > : mpl::true_ {}; 88 89 template <typename A0> // enables double_(...) 90 struct use_terminal<qi::domain 91 , terminal_ex<tag::double_, fusion::vector1<A0> > 92 > : mpl::true_ {}; 93 94 template <typename A0> // enables long_double(...) 95 struct use_terminal<qi::domain 96 , terminal_ex<tag::long_double, fusion::vector1<A0> > 97 > : mpl::true_ {}; 98 99 template <> // enables *lazy* float_(...) 100 struct use_lazy_terminal<qi::domain, tag::float_, 1> 101 : mpl::true_ {}; 102 103 template <> // enables *lazy* double_(...) 104 struct use_lazy_terminal<qi::domain, tag::double_, 1> 105 : mpl::true_ {}; 106 107 template <> // enables *lazy* long_double_(...) 108 struct use_lazy_terminal<qi::domain, tag::long_double, 1> 109 : mpl::true_ {}; 110 111 /////////////////////////////////////////////////////////////////////////// 112 // enables custom real_parser 113 template <typename T, typename Policies> 114 struct use_terminal<qi::domain 115 , tag::stateful_tag<Policies, tag::double_, T> > 116 : mpl::true_ {}; 117 118 // enables custom real_parser(...) 119 template <typename T, typename Policies, typename A0> 120 struct use_terminal<qi::domain 121 , terminal_ex<tag::stateful_tag<Policies, tag::double_, T> 122 , fusion::vector1<A0> > > 123 : mpl::true_ {}; 124 125 // enables *lazy* custom real_parser(...) 126 template <typename T, typename Policies> 127 struct use_lazy_terminal< 128 qi::domain 129 , tag::stateful_tag<Policies, tag::double_, T> 130 , 1 // arity 131 > : mpl::true_ {}; 132 }} 133 134 namespace boost { namespace spirit { namespace qi 135 { 136 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS 137 using spirit::float_; 138 using spirit::double_; 139 using spirit::long_double; 140 using spirit::lit; // lit(1.0) is equivalent to 1.0 141 #endif 142 143 using spirit::float_type; 144 using spirit::double_type; 145 using spirit::long_double_type; 146 using spirit::lit_type; 147 148 /////////////////////////////////////////////////////////////////////////// 149 // This is the actual real number parser 150 /////////////////////////////////////////////////////////////////////////// 151 template <typename T, typename RealPolicies = real_policies<T> > 152 struct any_real_parser 153 : primitive_parser<any_real_parser<T, RealPolicies> > 154 { 155 template <typename Context, typename Iterator> 156 struct attribute 157 { 158 typedef T type; 159 }; 160 161 template <typename Iterator, typename Context, typename Skipper> parseboost::spirit::qi::any_real_parser162 bool parse(Iterator& first, Iterator const& last 163 , Context& /*context*/, Skipper const& skipper 164 , T& attr_) const 165 { 166 typedef detail::real_impl<T, RealPolicies> extract; 167 qi::skip_over(first, last, skipper); 168 return extract::parse(first, last, attr_, RealPolicies()); 169 } 170 171 template <typename Iterator, typename Context 172 , typename Skipper, typename Attribute> parseboost::spirit::qi::any_real_parser173 bool parse(Iterator& first, Iterator const& last 174 , Context& context, Skipper const& skipper 175 , Attribute& attr_param) const 176 { 177 // this case is called when Attribute is not T 178 T attr_; 179 if (parse(first, last, context, skipper, attr_)) 180 { 181 traits::assign_to(attr_, attr_param); 182 return true; 183 } 184 return false; 185 } 186 187 template <typename Context> whatboost::spirit::qi::any_real_parser188 info what(Context& /*context*/) const 189 { 190 return info("real"); 191 } 192 }; 193 194 template <typename T, typename RealPolicies = real_policies<T> 195 , bool no_attribute = true> 196 struct literal_real_parser 197 : primitive_parser<literal_real_parser<T, RealPolicies, no_attribute> > 198 { 199 template <typename Value> literal_real_parserboost::spirit::qi::literal_real_parser200 literal_real_parser(Value const& n) : n_(n) {} 201 202 template <typename Context, typename Iterator> 203 struct attribute 204 : mpl::if_c<no_attribute, unused_type, T> 205 {}; 206 207 template <typename Iterator, typename Context 208 , typename Skipper, typename Attribute> parseboost::spirit::qi::literal_real_parser209 bool parse(Iterator& first, Iterator const& last 210 , Context&, Skipper const& skipper 211 , Attribute& attr_param) const 212 { 213 typedef detail::real_impl<T, RealPolicies> extract; 214 qi::skip_over(first, last, skipper); 215 216 Iterator save = first; 217 T attr_; 218 219 if (extract::parse(first, last, attr_, RealPolicies()) && 220 (attr_ == n_)) 221 { 222 traits::assign_to(attr_, attr_param); 223 return true; 224 } 225 226 first = save; 227 return false; 228 } 229 230 template <typename Context> whatboost::spirit::qi::literal_real_parser231 info what(Context& /*context*/) const 232 { 233 return info("real"); 234 } 235 236 T n_; 237 }; 238 239 /////////////////////////////////////////////////////////////////////////// 240 // Parser generators: make_xxx function (objects) 241 /////////////////////////////////////////////////////////////////////////// 242 template <typename T, typename Policies = real_policies<T> > 243 struct make_real 244 { 245 typedef any_real_parser<T, Policies> result_type; 246 operator ()boost::spirit::qi::make_real247 result_type operator()(unused_type, unused_type) const 248 { 249 return result_type(); 250 } 251 }; 252 253 template <typename T, typename Policies = real_policies<T> > 254 struct make_direct_real 255 { 256 typedef literal_real_parser<T, Policies, false> result_type; 257 258 template <typename Terminal> operator ()boost::spirit::qi::make_direct_real259 result_type operator()(Terminal const& term, unused_type) const 260 { 261 return result_type(T(fusion::at_c<0>(term.args))); 262 } 263 }; 264 265 template <typename T, typename Policies = real_policies<T> > 266 struct make_literal_real 267 { 268 typedef literal_real_parser<T, Policies> result_type; 269 270 template <typename Terminal> operator ()boost::spirit::qi::make_literal_real271 result_type operator()(Terminal const& term, unused_type) const 272 { 273 return result_type(fusion::at_c<0>(term.args)); 274 } 275 }; 276 277 /////////////////////////////////////////////////////////////////////////// 278 template <typename Modifiers, typename A0> 279 struct make_primitive< 280 terminal_ex<tag::lit, fusion::vector1<A0> > 281 , Modifiers, typename enable_if<is_same<A0, float> >::type> 282 : make_literal_real<float> {}; 283 284 template <typename Modifiers, typename A0> 285 struct make_primitive< 286 terminal_ex<tag::lit, fusion::vector1<A0> > 287 , Modifiers, typename enable_if<is_same<A0, double> >::type> 288 : make_literal_real<double> {}; 289 290 template <typename Modifiers, typename A0> 291 struct make_primitive< 292 terminal_ex<tag::lit, fusion::vector1<A0> > 293 , Modifiers, typename enable_if<is_same<A0, long double> >::type> 294 : make_literal_real<long double> {}; 295 296 /////////////////////////////////////////////////////////////////////////// 297 template <typename T, typename Policies, typename Modifiers> 298 struct make_primitive< 299 tag::stateful_tag<Policies, tag::double_, T>, Modifiers> 300 : make_real<T, Policies> {}; 301 302 template <typename T, typename Policies, typename A0, typename Modifiers> 303 struct make_primitive< 304 terminal_ex<tag::stateful_tag<Policies, tag::double_, T> 305 , fusion::vector1<A0> >, Modifiers> 306 : make_direct_real<T, Policies> {}; 307 308 /////////////////////////////////////////////////////////////////////////// 309 template <typename Modifiers> 310 struct make_primitive<tag::float_, Modifiers> 311 : make_real<float> {}; 312 313 template <typename Modifiers, typename A0> 314 struct make_primitive< 315 terminal_ex<tag::float_ 316 , fusion::vector1<A0> >, Modifiers> 317 : make_direct_real<float> {}; 318 319 /////////////////////////////////////////////////////////////////////////// 320 template <typename Modifiers> 321 struct make_primitive<tag::double_, Modifiers> 322 : make_real<double> {}; 323 324 template <typename Modifiers, typename A0> 325 struct make_primitive< 326 terminal_ex<tag::double_ 327 , fusion::vector1<A0> >, Modifiers> 328 : make_direct_real<double> {}; 329 330 /////////////////////////////////////////////////////////////////////////// 331 template <typename Modifiers> 332 struct make_primitive<tag::long_double, Modifiers> 333 : make_real<long double> {}; 334 335 template <typename Modifiers, typename A0> 336 struct make_primitive< 337 terminal_ex<tag::long_double 338 , fusion::vector1<A0> >, Modifiers> 339 : make_direct_real<long double> {}; 340 }}} 341 342 #endif 343