bool.hpp 16 KB

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