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_KARMA_BOOL_SEP_28_2009_1113AM) 7 #define BOOST_SPIRIT_KARMA_BOOL_SEP_28_2009_1113AM 8 9 #if defined(_MSC_VER) 10 #pragma once 11 #endif 12 13 #include <boost/limits.hpp> 14 #include <boost/mpl/bool.hpp> 15 #include <boost/utility/enable_if.hpp> 16 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> 31 32 /////////////////////////////////////////////////////////////////////////////// 33 namespace boost { namespace spirit 34 { 35 namespace karma 36 { 37 /////////////////////////////////////////////////////////////////////// 38 // forward declaration only 39 template <typename T> 40 struct bool_policies; 41 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> > 46 struct bool_generator 47 : spirit::terminal<tag::stateful_tag<Policies, tag::bool_, T> > 48 { 49 typedef tag::stateful_tag<Policies, tag::bool_, T> tag_type; 50 bool_generatorboost::spirit::karma::bool_generator51 bool_generator() {} bool_generatorboost::spirit::karma::bool_generator52 bool_generator(Policies const& data) 53 : spirit::terminal<tag_type>(data) {} 54 }; 55 } 56 57 /////////////////////////////////////////////////////////////////////////// 58 // Enablers 59 /////////////////////////////////////////////////////////////////////////// 60 template <> 61 struct use_terminal<karma::domain, tag::bool_> // enables bool_ 62 : mpl::true_ {}; 63 64 template <> 65 struct use_terminal<karma::domain, tag::true_> // enables true_ 66 : mpl::true_ {}; 67 68 template <> 69 struct use_terminal<karma::domain, tag::false_> // enables false_ 70 : mpl::true_ {}; 71 72 template <> 73 struct use_terminal<karma::domain, bool> // enables lit(true) 74 : mpl::true_ {}; 75 76 template <typename A0> 77 struct use_terminal<karma::domain // enables bool_(...) 78 , terminal_ex<tag::bool_, fusion::vector1<A0> > 79 > : mpl::true_ {}; 80 81 template <> // enables *lazy* bool_(...) 82 struct use_lazy_terminal<karma::domain, tag::bool_, 1> 83 : mpl::true_ {}; 84 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> > 90 : mpl::true_ {}; 91 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> > > 97 : mpl::true_ {}; 98 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> 103 : mpl::true_ {}; 104 105 // enables lit(bool) 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> 110 : mpl::true_ {}; 111 }} 112 113 /////////////////////////////////////////////////////////////////////////////// 114 namespace boost { namespace spirit { namespace karma 115 { 116 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS 117 using spirit::bool_; 118 using spirit::true_; 119 using spirit::false_; 120 using spirit::lit; // lit(true) is equivalent to true 121 #endif 122 123 using spirit::bool_type; 124 using spirit::true_type; 125 using spirit::false_type; 126 using spirit::lit_type; 127 128 /////////////////////////////////////////////////////////////////////////// 129 // This specialization is used for bool generators not having a direct 130 // initializer: bool_. These generators must be used in conjunction with 131 // an Attribute. 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> > 136 { 137 public: any_bool_generatorboost::spirit::karma::any_bool_generator138 any_bool_generator(Policies const& p = Policies()) 139 : p_(p) {} 140 141 typedef typename Policies::properties properties; 142 143 template <typename Context, typename Unused> 144 struct attribute 145 { 146 typedef T type; 147 }; 148 149 // bool_ has a Attribute attached 150 template <typename OutputIterator, typename Context, typename Delimiter 151 , typename Attribute> 152 bool generateboost::spirit::karma::any_bool_generator153 generate(OutputIterator& sink, Context& context, Delimiter const& d 154 , Attribute const& attr) const 155 { 156 if (!traits::has_optional_value(attr)) 157 return false; // fail if it's an uninitialized optional 158 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 162 } 163 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> 167 static bool generateboost::spirit::karma::any_bool_generator168 generate(OutputIterator&, Context&, Delimiter const&, unused_type) 169 { 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_FAIL(OutputIterator, bool_not_usable_without_attribute, ()); 175 return false; 176 } 177 178 template <typename Context> whatboost::spirit::karma::any_bool_generator179 static info what(Context const& /*context*/) 180 { 181 return info("bool"); 182 } 183 184 Policies p_; 185 }; 186 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> > 196 { 197 public: 198 typedef typename Policies::properties properties; 199 200 template <typename Context, typename Unused = unused_type> 201 struct attribute 202 : mpl::if_c<no_attribute, unused_type, T> 203 {}; 204 literal_bool_generatorboost::spirit::karma::literal_bool_generator205 literal_bool_generator(typename add_const<T>::type n 206 , Policies const& p = Policies()) 207 : n_(n), p_(p) {} 208 209 // A bool_() which additionally has an associated attribute emits 210 // its immediate literal only if it matches the attribute, otherwise 211 // it fails. 212 template <typename OutputIterator, typename Context, typename Delimiter 213 , typename Attribute> generateboost::spirit::karma::literal_bool_generator214 bool generate(OutputIterator& sink, Context& context 215 , Delimiter const& d, Attribute const& attr) const 216 { 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))) 220 { 221 return false; 222 } 223 return bool_inserter<T, Policies, CharEncoding, Tag>:: 224 call(sink, n_, p_) && delimit_out(sink, d); 225 } 226 227 // A bool_() without any associated attribute just emits its 228 // immediate literal 229 template <typename OutputIterator, typename Context, typename Delimiter> generateboost::spirit::karma::literal_bool_generator230 bool generate(OutputIterator& sink, Context&, Delimiter const& d 231 , unused_type) const 232 { 233 return bool_inserter<T, Policies, CharEncoding, Tag>:: 234 call(sink, n_) && delimit_out(sink, d); 235 } 236 237 template <typename Context> whatboost::spirit::karma::literal_bool_generator238 static info what(Context const& /*context*/) 239 { 240 return info("bool"); 241 } 242 243 T n_; 244 Policies p_; 245 }; 246 247 /////////////////////////////////////////////////////////////////////////// 248 // Generator generators: make_xxx function (objects) 249 /////////////////////////////////////////////////////////////////////////// 250 namespace detail 251 { 252 template <typename Modifiers, typename T = bool 253 , typename Policies = bool_policies<T> > 254 struct make_bool 255 { 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; 260 261 typedef any_bool_generator< 262 T 263 , typename spirit::detail::get_encoding_with_case< 264 Modifiers, unused_type, lower || upper>::type 265 , typename detail::get_casetag<Modifiers, lower || upper>::type 266 , Policies 267 > result_type; 268 269 template <typename Terminal> operator ()boost::spirit::karma::detail::make_bool270 result_type operator()(Terminal const& term, unused_type) const 271 { 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)); 275 } 276 }; 277 278 template <typename Modifiers, bool b> 279 struct make_bool_literal 280 { 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; 285 286 typedef literal_bool_generator< 287 bool 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 292 > result_type; 293 operator ()boost::spirit::karma::detail::make_bool_literal294 result_type operator()(unused_type, unused_type) const 295 { 296 return result_type(b); 297 } 298 }; 299 } 300 301 /////////////////////////////////////////////////////////////////////////// 302 template <typename Modifiers> 303 struct make_primitive<tag::bool_, Modifiers> 304 : detail::make_bool<Modifiers> {}; 305 306 template <typename Modifiers> 307 struct make_primitive<tag::true_, Modifiers> 308 : detail::make_bool_literal<Modifiers, true> {}; 309 310 template <typename Modifiers> 311 struct make_primitive<tag::false_, Modifiers> 312 : detail::make_bool_literal<Modifiers, false> {}; 313 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> {}; 319 320 /////////////////////////////////////////////////////////////////////////// 321 namespace detail 322 { 323 template <typename Modifiers, typename T = bool 324 , typename Policies = bool_policies<T> > 325 struct make_bool_direct 326 { 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; 331 332 typedef literal_bool_generator< 333 T 334 , typename spirit::detail::get_encoding_with_case< 335 Modifiers, unused_type, lower || upper>::type 336 , typename detail::get_casetag<Modifiers, lower || upper>::type 337 , Policies, false 338 > result_type; 339 340 template <typename Terminal> operator ()boost::spirit::karma::detail::make_bool_direct341 result_type operator()(Terminal const& term, unused_type) const 342 { 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)); 347 } 348 }; 349 } 350 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> {}; 356 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> > 361 , Modifiers> 362 : detail::make_bool_direct<Modifiers 363 , typename remove_const<T>::type, Policies> {}; 364 365 /////////////////////////////////////////////////////////////////////////// 366 namespace detail 367 { 368 template <typename Modifiers> 369 struct basic_bool_literal 370 { 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; 375 376 typedef literal_bool_generator< 377 bool 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 382 > result_type; 383 384 template <typename T_> operator ()boost::spirit::karma::detail::basic_bool_literal385 result_type operator()(T_ i, unused_type) const 386 { 387 return result_type(i); 388 } 389 }; 390 } 391 392 template <typename Modifiers> 393 struct make_primitive<bool, Modifiers> 394 : detail::basic_bool_literal<Modifiers> {}; 395 396 template <typename Modifiers, typename A0> 397 struct make_primitive< 398 terminal_ex<tag::lit, fusion::vector1<A0> > 399 , Modifiers 400 , typename enable_if<traits::is_bool<A0> >::type> 401 : detail::basic_bool_literal<Modifiers> 402 { 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; 407 408 typedef literal_bool_generator< 409 bool 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 414 > result_type; 415 416 template <typename Terminal> operator ()boost::spirit::karma::make_primitive417 result_type operator()(Terminal const& term, unused_type) const 418 { 419 return result_type(fusion::at_c<0>(term.args)); 420 } 421 }; 422 }}} 423 424 #endif 425