real.hpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  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. #if !defined(BOOST_SPIRIT_KARMA_REAL_FEB_26_2007_0512PM)
  6. #define BOOST_SPIRIT_KARMA_REAL_FEB_26_2007_0512PM
  7. #if defined(_MSC_VER)
  8. #pragma once
  9. #endif
  10. #include <boost/config/no_tr1/cmath.hpp>
  11. #include <boost/config.hpp>
  12. #include <boost/mpl/bool.hpp>
  13. #include <boost/utility/enable_if.hpp>
  14. #include <boost/spirit/home/support/common_terminals.hpp>
  15. #include <boost/spirit/home/support/string_traits.hpp>
  16. #include <boost/spirit/home/support/numeric_traits.hpp>
  17. #include <boost/spirit/home/support/info.hpp>
  18. #include <boost/spirit/home/support/char_class.hpp>
  19. #include <boost/spirit/home/support/container.hpp>
  20. #include <boost/spirit/home/support/detail/get_encoding.hpp>
  21. #include <boost/spirit/home/karma/meta_compiler.hpp>
  22. #include <boost/spirit/home/karma/char.hpp>
  23. #include <boost/spirit/home/karma/delimit_out.hpp>
  24. #include <boost/spirit/home/karma/auxiliary/lazy.hpp>
  25. #include <boost/spirit/home/karma/detail/get_casetag.hpp>
  26. #include <boost/spirit/home/karma/detail/extract_from.hpp>
  27. #include <boost/spirit/home/karma/detail/enable_lit.hpp>
  28. #include <boost/spirit/home/karma/domain.hpp>
  29. #include <boost/spirit/home/karma/numeric/real_policies.hpp>
  30. #include <boost/spirit/home/karma/numeric/detail/real_utils.hpp>
  31. #include <boost/fusion/include/at.hpp>
  32. #include <boost/fusion/include/value_at.hpp>
  33. #include <boost/fusion/include/vector.hpp>
  34. namespace boost { namespace spirit
  35. {
  36. namespace karma
  37. {
  38. ///////////////////////////////////////////////////////////////////////
  39. // forward declaration only
  40. template <typename T>
  41. struct real_policies;
  42. ///////////////////////////////////////////////////////////////////////
  43. // This is the class that the user can instantiate directly in
  44. // order to create a customized real generator
  45. template <typename T = double, typename Policies = real_policies<T> >
  46. struct real_generator
  47. : spirit::terminal<tag::stateful_tag<Policies, tag::double_, T> >
  48. {
  49. typedef tag::stateful_tag<Policies, tag::double_, T> tag_type;
  50. real_generator() {}
  51. real_generator(Policies const& p)
  52. : spirit::terminal<tag_type>(p) {}
  53. };
  54. }
  55. ///////////////////////////////////////////////////////////////////////////
  56. // Enablers
  57. ///////////////////////////////////////////////////////////////////////////
  58. template <>
  59. struct use_terminal<karma::domain, tag::float_> // enables float_
  60. : mpl::true_ {};
  61. template <>
  62. struct use_terminal<karma::domain, tag::double_> // enables double_
  63. : mpl::true_ {};
  64. template <>
  65. struct use_terminal<karma::domain, tag::long_double> // enables long_double
  66. : mpl::true_ {};
  67. ///////////////////////////////////////////////////////////////////////////
  68. template <>
  69. struct use_terminal<karma::domain, float> // enables lit(1.0f)
  70. : mpl::true_ {};
  71. template <>
  72. struct use_terminal<karma::domain, double> // enables lit(1.0)
  73. : mpl::true_ {};
  74. template <>
  75. struct use_terminal<karma::domain, long double> // enables lit(1.0l)
  76. : mpl::true_ {};
  77. ///////////////////////////////////////////////////////////////////////////
  78. template <typename A0>
  79. struct use_terminal<karma::domain // enables float_(...)
  80. , terminal_ex<tag::float_, fusion::vector1<A0> >
  81. > : mpl::true_ {};
  82. template <typename A0>
  83. struct use_terminal<karma::domain // enables double_(...)
  84. , terminal_ex<tag::double_, fusion::vector1<A0> >
  85. > : mpl::true_ {};
  86. template <typename A0>
  87. struct use_terminal<karma::domain // enables long_double(...)
  88. , terminal_ex<tag::long_double, fusion::vector1<A0> >
  89. > : mpl::true_ {};
  90. // lazy float_(...), double_(...), long_double(...)
  91. template <>
  92. struct use_lazy_terminal<karma::domain, tag::float_, 1>
  93. : mpl::true_ {};
  94. template <>
  95. struct use_lazy_terminal<karma::domain, tag::double_, 1>
  96. : mpl::true_ {};
  97. template <>
  98. struct use_lazy_terminal<karma::domain, tag::long_double, 1>
  99. : mpl::true_ {};
  100. ///////////////////////////////////////////////////////////////////////////
  101. // enables custom real generator
  102. template <typename T, typename Policies>
  103. struct use_terminal<karma::domain
  104. , tag::stateful_tag<Policies, tag::double_, T> >
  105. : mpl::true_ {};
  106. template <typename T, typename Policies, typename A0>
  107. struct use_terminal<karma::domain
  108. , terminal_ex<tag::stateful_tag<Policies, tag::double_, T>
  109. , fusion::vector1<A0> > >
  110. : mpl::true_ {};
  111. // enables *lazy* custom real generator
  112. template <typename T, typename Policies>
  113. struct use_lazy_terminal<
  114. karma::domain
  115. , tag::stateful_tag<Policies, tag::double_, T>
  116. , 1 // arity
  117. > : mpl::true_ {};
  118. // enables lit(double)
  119. template <typename A0>
  120. struct use_terminal<karma::domain
  121. , terminal_ex<tag::lit, fusion::vector1<A0> >
  122. , typename enable_if<traits::is_real<A0> >::type>
  123. : mpl::true_ {};
  124. }}
  125. ///////////////////////////////////////////////////////////////////////////////
  126. namespace boost { namespace spirit { namespace karma
  127. {
  128. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  129. using spirit::float_;
  130. using spirit::double_;
  131. using spirit::long_double;
  132. #endif
  133. using spirit::float_type;
  134. using spirit::double_type;
  135. using spirit::long_double_type;
  136. ///////////////////////////////////////////////////////////////////////////
  137. // This specialization is used for real generators not having a direct
  138. // initializer: float_, double_ etc. These generators must be used in
  139. // conjunction with an attribute.
  140. ///////////////////////////////////////////////////////////////////////////
  141. template <
  142. typename T, typename Policies, typename CharEncoding, typename Tag>
  143. struct any_real_generator
  144. : primitive_generator<any_real_generator<T, Policies, CharEncoding, Tag> >
  145. {
  146. typedef typename Policies::properties properties;
  147. template <typename Context, typename Unused>
  148. struct attribute
  149. {
  150. typedef T type;
  151. };
  152. any_real_generator(Policies const& policies = Policies())
  153. : p_(policies) {}
  154. // double_/float_/etc. has an attached attribute
  155. template <typename OutputIterator, typename Context, typename Delimiter
  156. , typename Attribute>
  157. bool generate(OutputIterator& sink, Context& context
  158. , Delimiter const& d, Attribute const& attr) const
  159. {
  160. if (!traits::has_optional_value(attr))
  161. return false; // fail if it's an uninitialized optional
  162. typedef real_inserter<T, Policies, CharEncoding, Tag> inserter_type;
  163. return inserter_type::call(sink, traits::extract_from<T>(attr, context), p_) &&
  164. karma::delimit_out(sink, d); // always do post-delimiting
  165. }
  166. // this double_/float_/etc. has no attribute attached, it needs to have
  167. // been initialized from a direct literal
  168. template <typename OutputIterator, typename Context, typename Delimiter>
  169. static bool generate(OutputIterator&, Context&, Delimiter const&
  170. , unused_type)
  171. {
  172. // It is not possible (doesn't make sense) to use numeric generators
  173. // without providing any attribute, as the generator doesn't 'know'
  174. // what to output. The following assertion fires if this situation
  175. // is detected in your code.
  176. BOOST_SPIRIT_ASSERT_FAIL(OutputIterator, real_not_usable_without_attribute, ());
  177. return false;
  178. }
  179. template <typename Context>
  180. static info what(Context const& /*context*/)
  181. {
  182. return info("real");
  183. }
  184. Policies p_;
  185. };
  186. ///////////////////////////////////////////////////////////////////////////
  187. // This specialization is used for real generators having a direct
  188. // initializer: float_(10.), double_(20.) etc.
  189. ///////////////////////////////////////////////////////////////////////////
  190. template <
  191. typename T, typename Policies, typename CharEncoding, typename Tag
  192. , bool no_attribute>
  193. struct literal_real_generator
  194. : primitive_generator<literal_real_generator<T, Policies, CharEncoding
  195. , Tag, no_attribute> >
  196. {
  197. typedef typename Policies::properties properties;
  198. template <typename Context, typename Unused = unused_type>
  199. struct attribute
  200. : mpl::if_c<no_attribute, unused_type, T>
  201. {};
  202. literal_real_generator(typename add_const<T>::type n
  203. , Policies const& policies = Policies())
  204. : n_(n), p_(policies) {}
  205. // A double_(1.0) which additionally has an associated attribute emits
  206. // its immediate literal only if it matches the attribute, otherwise
  207. // it fails.
  208. template <typename OutputIterator, typename Context, typename Delimiter
  209. , typename Attribute>
  210. bool generate(OutputIterator& sink, Context& context
  211. , Delimiter const& d, Attribute const& attr) const
  212. {
  213. typedef typename attribute<Context>::type attribute_type;
  214. if (!traits::has_optional_value(attr) ||
  215. n_ != traits::extract_from<attribute_type>(attr, context))
  216. {
  217. return false;
  218. }
  219. typedef real_inserter<T, Policies, CharEncoding, Tag> inserter_type;
  220. return inserter_type::call(sink, n_, p_) &&
  221. karma::delimit_out(sink, d); // always do post-delimiting
  222. }
  223. // A double_(1.0) without any associated attribute just emits its
  224. // immediate literal
  225. template <typename OutputIterator, typename Context, typename Delimiter>
  226. bool generate(OutputIterator& sink, Context&, Delimiter const& d
  227. , unused_type) const
  228. {
  229. typedef real_inserter<T, Policies, CharEncoding, Tag> inserter_type;
  230. return inserter_type::call(sink, n_, p_) &&
  231. karma::delimit_out(sink, d); // always do post-delimiting
  232. }
  233. template <typename Context>
  234. static info what(Context const& /*context*/)
  235. {
  236. return info("real");
  237. }
  238. T n_;
  239. Policies p_;
  240. };
  241. ///////////////////////////////////////////////////////////////////////////
  242. // Generator generators: make_xxx function (objects)
  243. ///////////////////////////////////////////////////////////////////////////
  244. namespace detail
  245. {
  246. template <typename T, typename Modifiers
  247. , typename Policies = real_policies<T> >
  248. struct make_real
  249. {
  250. static bool const lower =
  251. has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
  252. static bool const upper =
  253. has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
  254. typedef any_real_generator<
  255. T, Policies
  256. , typename spirit::detail::get_encoding_with_case<
  257. Modifiers, unused_type, lower || upper>::type
  258. , typename detail::get_casetag<Modifiers, lower || upper>::type
  259. > result_type;
  260. template <typename Terminal>
  261. result_type operator()(Terminal const& term, unused_type) const
  262. {
  263. typedef tag::stateful_tag<Policies, tag::double_, T> tag_type;
  264. using spirit::detail::get_stateful_data;
  265. return result_type(get_stateful_data<tag_type>::call(term));
  266. }
  267. };
  268. }
  269. template <typename Modifiers>
  270. struct make_primitive<tag::float_, Modifiers>
  271. : detail::make_real<float, Modifiers> {};
  272. template <typename Modifiers>
  273. struct make_primitive<tag::double_, Modifiers>
  274. : detail::make_real<double, Modifiers> {};
  275. template <typename Modifiers>
  276. struct make_primitive<tag::long_double, Modifiers>
  277. : detail::make_real<long double, Modifiers> {};
  278. ///////////////////////////////////////////////////////////////////////////
  279. template <typename T, typename Policies, typename Modifiers>
  280. struct make_primitive<
  281. tag::stateful_tag<Policies, tag::double_, T>, Modifiers>
  282. : detail::make_real<typename remove_const<T>::type
  283. , Modifiers, Policies> {};
  284. ///////////////////////////////////////////////////////////////////////////
  285. namespace detail
  286. {
  287. template <typename T, typename Modifiers
  288. , typename Policies = real_policies<T> >
  289. struct make_real_direct
  290. {
  291. static bool const lower =
  292. has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
  293. static bool const upper =
  294. has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
  295. typedef literal_real_generator<
  296. T, Policies
  297. , typename spirit::detail::get_encoding_with_case<
  298. Modifiers, unused_type, lower || upper>::type
  299. , typename detail::get_casetag<Modifiers, lower || upper>::type
  300. , false
  301. > result_type;
  302. template <typename Terminal>
  303. result_type operator()(Terminal const& term, unused_type) const
  304. {
  305. typedef tag::stateful_tag<Policies, tag::double_, T> tag_type;
  306. using spirit::detail::get_stateful_data;
  307. return result_type(T(fusion::at_c<0>(term.args))
  308. , get_stateful_data<tag_type>::call(term.term));
  309. }
  310. };
  311. }
  312. template <typename Modifiers, typename A0>
  313. struct make_primitive<
  314. terminal_ex<tag::float_, fusion::vector1<A0> >, Modifiers>
  315. : detail::make_real_direct<float, Modifiers> {};
  316. template <typename Modifiers, typename A0>
  317. struct make_primitive<
  318. terminal_ex<tag::double_, fusion::vector1<A0> >, Modifiers>
  319. : detail::make_real_direct<double, Modifiers> {};
  320. template <typename Modifiers, typename A0>
  321. struct make_primitive<
  322. terminal_ex<tag::long_double, fusion::vector1<A0> >, Modifiers>
  323. : detail::make_real_direct<long double, Modifiers> {};
  324. ///////////////////////////////////////////////////////////////////////////
  325. template <typename T, typename Policies, typename A0, typename Modifiers>
  326. struct make_primitive<
  327. terminal_ex<tag::stateful_tag<Policies, tag::double_, T>
  328. , fusion::vector1<A0> >
  329. , Modifiers>
  330. : detail::make_real_direct<typename remove_const<T>::type
  331. , Modifiers, Policies> {};
  332. ///////////////////////////////////////////////////////////////////////////
  333. namespace detail
  334. {
  335. template <typename T, typename Modifiers>
  336. struct basic_real_literal
  337. {
  338. static bool const lower =
  339. has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
  340. static bool const upper =
  341. has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
  342. typedef literal_real_generator<
  343. T, real_policies<T>
  344. , typename spirit::detail::get_encoding_with_case<
  345. Modifiers, unused_type, lower || upper>::type
  346. , typename detail::get_casetag<Modifiers, lower || upper>::type
  347. , true
  348. > result_type;
  349. template <typename T_>
  350. result_type operator()(T_ i, unused_type) const
  351. {
  352. return result_type(T(i));
  353. }
  354. };
  355. }
  356. template <typename Modifiers>
  357. struct make_primitive<float, Modifiers>
  358. : detail::basic_real_literal<float, Modifiers> {};
  359. template <typename Modifiers>
  360. struct make_primitive<double, Modifiers>
  361. : detail::basic_real_literal<double, Modifiers> {};
  362. template <typename Modifiers>
  363. struct make_primitive<long double, Modifiers>
  364. : detail::basic_real_literal<long double, Modifiers> {};
  365. // lit(double)
  366. template <typename Modifiers, typename A0>
  367. struct make_primitive<
  368. terminal_ex<tag::lit, fusion::vector1<A0> >
  369. , Modifiers
  370. , typename enable_if<traits::is_real<A0> >::type>
  371. {
  372. static bool const lower =
  373. has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
  374. static bool const upper =
  375. has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
  376. typedef literal_real_generator<
  377. typename remove_const<A0>::type, real_policies<A0>
  378. , typename spirit::detail::get_encoding_with_case<
  379. Modifiers, unused_type, lower || upper>::type
  380. , typename detail::get_casetag<Modifiers, lower || upper>::type
  381. , true
  382. > result_type;
  383. template <typename Terminal>
  384. result_type operator()(Terminal const& term, unused_type) const
  385. {
  386. return result_type(fusion::at_c<0>(term.args));
  387. }
  388. };
  389. }}}
  390. #endif // defined(BOOST_SPIRIT_KARMA_REAL_FEB_26_2007_0512PM)