1 // Copyright (c) 2001-2011 Hartmut Kaiser
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)
6 #if !defined(BOOST_SPIRIT_KARMA_BOOL_SEP_28_2009_1113AM)
7 #define BOOST_SPIRIT_KARMA_BOOL_SEP_28_2009_1113AM
13 #include <boost/limits.hpp>
14 #include <boost/mpl/bool.hpp>
15 #include <boost/utility/enable_if.hpp>
17 #include <boost/spirit/home/support/common_terminals.hpp>
18 #include <boost/spirit/home/support/string_traits.hpp>
19 #include <boost/spirit/home/support/numeric_traits.hpp>
20 #include <boost/spirit/home/support/info.hpp>
21 #include <boost/spirit/home/support/char_class.hpp>
22 #include <boost/spirit/home/karma/meta_compiler.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/bool_policies.hpp>
30 #include <boost/spirit/home/karma/numeric/detail/bool_utils.hpp>
32 ///////////////////////////////////////////////////////////////////////////////
33 namespace boost { namespace spirit
37 ///////////////////////////////////////////////////////////////////////
38 // forward declaration only
42 ///////////////////////////////////////////////////////////////////////
43 // This is the class that the user can instantiate directly in
44 // order to create a customized bool generator
45 template <typename T = bool, typename Policies = bool_policies<T> >
47 : spirit::terminal<tag::stateful_tag<Policies, tag::bool_, T> >
49 typedef tag::stateful_tag<Policies, tag::bool_, T> tag_type;
52 bool_generator(Policies const& data)
53 : spirit::terminal<tag_type>(data) {}
57 ///////////////////////////////////////////////////////////////////////////
59 ///////////////////////////////////////////////////////////////////////////
61 struct use_terminal<karma::domain, tag::bool_> // enables bool_
65 struct use_terminal<karma::domain, tag::true_> // enables true_
69 struct use_terminal<karma::domain, tag::false_> // enables false_
73 struct use_terminal<karma::domain, bool> // enables lit(true)
76 template <typename A0>
77 struct use_terminal<karma::domain // enables bool_(...)
78 , terminal_ex<tag::bool_, fusion::vector1<A0> >
81 template <> // enables *lazy* bool_(...)
82 struct use_lazy_terminal<karma::domain, tag::bool_, 1>
85 ///////////////////////////////////////////////////////////////////////////
86 // enables any custom bool_generator
87 template <typename Policies, typename T>
88 struct use_terminal<karma::domain
89 , tag::stateful_tag<Policies, tag::bool_, T> >
92 // enables any custom bool_generator(...)
93 template <typename Policies, typename T, typename A0>
94 struct use_terminal<karma::domain
95 , terminal_ex<tag::stateful_tag<Policies, tag::bool_, T>
96 , fusion::vector1<A0> > >
99 // enables *lazy* custom bool_generator
100 template <typename Policies, typename T>
101 struct use_lazy_terminal<karma::domain
102 , tag::stateful_tag<Policies, tag::bool_, T>, 1>
106 template <typename A0>
107 struct use_terminal<karma::domain
108 , terminal_ex<tag::lit, fusion::vector1<A0> >
109 , typename enable_if<traits::is_bool<A0> >::type>
113 ///////////////////////////////////////////////////////////////////////////////
114 namespace boost { namespace spirit { namespace karma
116 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
119 using spirit::false_;
120 using spirit::lit; // lit(true) is equivalent to true
123 using spirit::bool_type;
124 using spirit::true_type;
125 using spirit::false_type;
126 using spirit::lit_type;
128 ///////////////////////////////////////////////////////////////////////////
129 // This specialization is used for bool generators not having a direct
130 // initializer: bool_. These generators must be used in conjunction with
132 ///////////////////////////////////////////////////////////////////////////
133 template <typename T, typename CharEncoding, typename Tag, typename Policies>
134 struct any_bool_generator
135 : primitive_generator<any_bool_generator<T, CharEncoding, Tag, Policies> >
138 any_bool_generator(Policies const& p = Policies())
141 typedef typename Policies::properties properties;
143 template <typename Context, typename Unused>
149 // bool_ has a Attribute attached
150 template <typename OutputIterator, typename Context, typename Delimiter
151 , typename Attribute>
153 generate(OutputIterator& sink, Context& context, Delimiter const& d
154 , Attribute const& attr) const
156 if (!traits::has_optional_value(attr))
157 return false; // fail if it's an uninitialized optional
159 return bool_inserter<T, Policies, CharEncoding, Tag>::call(
160 sink, traits::extract_from<T>(attr, context), p_) &&
161 delimit_out(sink, d); // always do post-delimiting
164 // this bool_ has no Attribute attached, it needs to have been
165 // initialized from a direct literal
166 template <typename OutputIterator, typename Context, typename Delimiter>
168 generate(OutputIterator&, Context&, Delimiter const&, unused_type)
170 // It is not possible (doesn't make sense) to use boolean generators
171 // without providing any attribute, as the generator doesn't 'know'
172 // what to output. The following assertion fires if this situation
173 // is detected in your code.
174 BOOST_SPIRIT_ASSERT_MSG(false, bool_not_usable_without_attribute, ());
178 template <typename Context>
179 static info what(Context const& /*context*/)
187 ///////////////////////////////////////////////////////////////////////////
188 // This specialization is used for bool generators having a direct
189 // initializer: bool_(true), bool_(0) etc.
190 ///////////////////////////////////////////////////////////////////////////
191 template <typename T, typename CharEncoding, typename Tag
192 , typename Policies, bool no_attribute>
193 struct literal_bool_generator
194 : primitive_generator<literal_bool_generator<T, CharEncoding, Tag
195 , Policies, no_attribute> >
198 typedef typename Policies::properties properties;
200 template <typename Context, typename Unused = unused_type>
202 : mpl::if_c<no_attribute, unused_type, T>
205 literal_bool_generator(typename add_const<T>::type n
206 , Policies const& p = Policies())
209 // A bool_() which additionally has an associated attribute emits
210 // its immediate literal only if it matches the attribute, otherwise
212 template <typename OutputIterator, typename Context, typename Delimiter
213 , typename Attribute>
214 bool generate(OutputIterator& sink, Context& context
215 , Delimiter const& d, Attribute const& attr) const
217 typedef typename attribute<Context>::type attribute_type;
218 if (!traits::has_optional_value(attr) ||
219 bool(n_) != bool(traits::extract_from<attribute_type>(attr, context)))
223 return bool_inserter<T, Policies, CharEncoding, Tag>::
224 call(sink, n_, p_) && delimit_out(sink, d);
227 // A bool_() without any associated attribute just emits its
229 template <typename OutputIterator, typename Context, typename Delimiter>
230 bool generate(OutputIterator& sink, Context&, Delimiter const& d
233 return bool_inserter<T, Policies, CharEncoding, Tag>::
234 call(sink, n_) && delimit_out(sink, d);
237 template <typename Context>
238 static info what(Context const& /*context*/)
247 ///////////////////////////////////////////////////////////////////////////
248 // Generator generators: make_xxx function (objects)
249 ///////////////////////////////////////////////////////////////////////////
252 template <typename Modifiers, typename T = bool
253 , typename Policies = bool_policies<T> >
256 static bool const lower =
257 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
258 static bool const upper =
259 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
261 typedef any_bool_generator<
263 , typename spirit::detail::get_encoding_with_case<
264 Modifiers, unused_type, lower || upper>::type
265 , typename detail::get_casetag<Modifiers, lower || upper>::type
269 template <typename Terminal>
270 result_type operator()(Terminal const& term, unused_type) const
272 typedef tag::stateful_tag<Policies, tag::bool_, T> tag_type;
273 using spirit::detail::get_stateful_data;
274 return result_type(get_stateful_data<tag_type>::call(term));
278 template <typename Modifiers, bool b>
279 struct make_bool_literal
281 static bool const lower =
282 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
283 static bool const upper =
284 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
286 typedef literal_bool_generator<
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 , bool_policies<>, false
294 result_type operator()(unused_type, unused_type) const
296 return result_type(b);
301 ///////////////////////////////////////////////////////////////////////////
302 template <typename Modifiers>
303 struct make_primitive<tag::bool_, Modifiers>
304 : detail::make_bool<Modifiers> {};
306 template <typename Modifiers>
307 struct make_primitive<tag::true_, Modifiers>
308 : detail::make_bool_literal<Modifiers, true> {};
310 template <typename Modifiers>
311 struct make_primitive<tag::false_, Modifiers>
312 : detail::make_bool_literal<Modifiers, false> {};
314 template <typename T, typename Policies, typename Modifiers>
315 struct make_primitive<
316 tag::stateful_tag<Policies, tag::bool_, T>, Modifiers>
317 : detail::make_bool<Modifiers
318 , typename remove_const<T>::type, Policies> {};
320 ///////////////////////////////////////////////////////////////////////////
323 template <typename Modifiers, typename T = bool
324 , typename Policies = bool_policies<T> >
325 struct make_bool_direct
327 static bool const lower =
328 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
329 static bool const upper =
330 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
332 typedef literal_bool_generator<
334 , typename spirit::detail::get_encoding_with_case<
335 Modifiers, unused_type, lower || upper>::type
336 , typename detail::get_casetag<Modifiers, lower || upper>::type
340 template <typename Terminal>
341 result_type operator()(Terminal const& term, unused_type) const
343 typedef tag::stateful_tag<Policies, tag::bool_, T> tag_type;
344 using spirit::detail::get_stateful_data;
345 return result_type(fusion::at_c<0>(term.args)
346 , get_stateful_data<tag_type>::call(term.term));
351 ///////////////////////////////////////////////////////////////////////////
352 template <typename Modifiers, typename A0>
353 struct make_primitive<
354 terminal_ex<tag::bool_, fusion::vector1<A0> >, Modifiers>
355 : detail::make_bool_direct<Modifiers> {};
357 template <typename T, typename Policies, typename A0, typename Modifiers>
358 struct make_primitive<
359 terminal_ex<tag::stateful_tag<Policies, tag::bool_, T>
360 , fusion::vector1<A0> >
362 : detail::make_bool_direct<Modifiers
363 , typename remove_const<T>::type, Policies> {};
365 ///////////////////////////////////////////////////////////////////////////
368 template <typename Modifiers>
369 struct basic_bool_literal
371 static bool const lower =
372 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
373 static bool const upper =
374 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
376 typedef literal_bool_generator<
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 , bool_policies<>, true
384 template <typename T_>
385 result_type operator()(T_ i, unused_type) const
387 return result_type(i);
392 template <typename Modifiers>
393 struct make_primitive<bool, Modifiers>
394 : detail::basic_bool_literal<Modifiers> {};
396 template <typename Modifiers, typename A0>
397 struct make_primitive<
398 terminal_ex<tag::lit, fusion::vector1<A0> >
400 , typename enable_if<traits::is_bool<A0> >::type>
401 : detail::basic_bool_literal<Modifiers>
403 static bool const lower =
404 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
405 static bool const upper =
406 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
408 typedef literal_bool_generator<
410 , typename spirit::detail::get_encoding_with_case<
411 Modifiers, unused_type, lower || upper>::type
412 , typename detail::get_casetag<Modifiers, lower || upper>::type
413 , bool_policies<>, true
416 template <typename Terminal>
417 result_type operator()(Terminal const& term, unused_type) const
419 return result_type(fusion::at_c<0>(term.args));