File indexing completed on 2025-12-16 10:09:12
0001
0002
0003
0004
0005
0006
0007 #if !defined(BOOST_SPIRIT_KARMA_CHAR_FEB_21_2007_0543PM)
0008 #define BOOST_SPIRIT_KARMA_CHAR_FEB_21_2007_0543PM
0009
0010 #if defined(_MSC_VER)
0011 #pragma once
0012 #endif
0013
0014 #include <boost/spirit/home/support/common_terminals.hpp>
0015 #include <boost/spirit/home/support/string_traits.hpp>
0016 #include <boost/spirit/home/support/info.hpp>
0017 #include <boost/spirit/home/support/char_class.hpp>
0018 #include <boost/spirit/home/support/detail/get_encoding.hpp>
0019 #include <boost/spirit/home/support/char_set/basic_chset.hpp>
0020 #include <boost/spirit/home/karma/domain.hpp>
0021 #include <boost/spirit/home/karma/meta_compiler.hpp>
0022 #include <boost/spirit/home/karma/delimit_out.hpp>
0023 #include <boost/spirit/home/karma/char/char_generator.hpp>
0024 #include <boost/spirit/home/karma/auxiliary/lazy.hpp>
0025 #include <boost/spirit/home/karma/detail/get_casetag.hpp>
0026 #include <boost/spirit/home/karma/detail/generate_to.hpp>
0027 #include <boost/spirit/home/karma/detail/enable_lit.hpp>
0028 #include <boost/fusion/include/at.hpp>
0029 #include <boost/fusion/include/vector.hpp>
0030 #include <boost/fusion/include/cons.hpp>
0031 #include <boost/mpl/if.hpp>
0032 #include <boost/mpl/assert.hpp>
0033 #include <boost/mpl/bool.hpp>
0034 #include <boost/utility/enable_if.hpp>
0035 #include <string>
0036
0037
0038 namespace boost { namespace spirit
0039 {
0040
0041
0042
0043 template <typename CharEncoding>
0044 struct use_terminal<karma::domain
0045 , tag::char_code<tag::char_, CharEncoding>
0046 > : mpl::true_ {};
0047
0048 template <typename CharEncoding, typename A0>
0049 struct use_terminal<karma::domain
0050 , terminal_ex<
0051 tag::char_code<tag::char_, CharEncoding>
0052 , fusion::vector1<A0>
0053 >
0054 > : mpl::true_ {};
0055
0056 template <typename A0>
0057 struct use_terminal<karma::domain
0058 , terminal_ex<tag::lit, fusion::vector1<A0> >
0059 , typename enable_if<traits::is_char<A0> >::type>
0060 : mpl::true_ {};
0061
0062 template <typename CharEncoding, typename A0, typename A1>
0063 struct use_terminal<karma::domain
0064 , terminal_ex<
0065 tag::char_code<tag::char_, CharEncoding>
0066 , fusion::vector2<A0, A1>
0067 >
0068 > : mpl::true_ {};
0069
0070 template <typename CharEncoding>
0071 struct use_lazy_terminal<
0072 karma::domain
0073 , tag::char_code<tag::char_, CharEncoding>
0074 , 1
0075 > : mpl::true_ {};
0076
0077 template <>
0078 struct use_terminal<karma::domain, char>
0079 : mpl::true_ {};
0080
0081 template <>
0082 struct use_terminal<karma::domain, char[2]>
0083 : mpl::true_ {};
0084
0085 template <>
0086 struct use_terminal<karma::domain, wchar_t>
0087 : mpl::true_ {};
0088
0089 template <>
0090 struct use_terminal<karma::domain, wchar_t[2]>
0091 : mpl::true_ {};
0092 }}
0093
0094
0095 namespace boost { namespace spirit { namespace karma
0096 {
0097 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
0098 using spirit::lit;
0099 #endif
0100 using spirit::lit_type;
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110 template <typename CharEncoding, typename Tag>
0111 struct any_char
0112 : char_generator<any_char<CharEncoding, Tag>, CharEncoding, Tag>
0113 {
0114 typedef typename CharEncoding::char_type char_type;
0115 typedef CharEncoding char_encoding;
0116
0117 template <typename Context, typename Unused>
0118 struct attribute
0119 {
0120 typedef char_type type;
0121 };
0122
0123
0124 template <typename Attribute, typename CharParam, typename Context>
0125 bool test(Attribute const& attr, CharParam& ch, Context&) const
0126 {
0127 ch = CharParam(attr);
0128 return true;
0129 }
0130
0131
0132
0133 template <typename CharParam, typename Context>
0134 bool test(unused_type, CharParam&, Context&) const
0135 {
0136
0137
0138
0139
0140 BOOST_SPIRIT_ASSERT_FAIL(CharParam, char_not_usable_without_attribute, ());
0141 return false;
0142 }
0143
0144 template <typename Context>
0145 static info what(Context const& )
0146 {
0147 return info("any-char");
0148 }
0149 };
0150
0151
0152
0153
0154
0155
0156
0157
0158 template <typename CharEncoding, typename Tag, bool no_attribute>
0159 struct literal_char
0160 : char_generator<literal_char<CharEncoding, Tag, no_attribute>
0161 , CharEncoding, Tag>
0162 {
0163 typedef typename CharEncoding::char_type char_type;
0164 typedef CharEncoding char_encoding;
0165
0166 literal_char(char_type ch)
0167 : ch (spirit::char_class::convert<char_encoding>::to(Tag(), ch))
0168 {}
0169
0170 template <typename Context, typename Unused>
0171 struct attribute
0172 : mpl::if_c<no_attribute, unused_type, char_type>
0173 {};
0174
0175
0176
0177
0178
0179 template <typename Attribute, typename CharParam, typename Context>
0180 bool test(Attribute const& attr, CharParam& ch_, Context&) const
0181 {
0182
0183 ch_ = static_cast<char_type>(attr);
0184 return attr == ch;
0185 }
0186
0187
0188
0189 template <typename CharParam, typename Context>
0190 bool test(unused_type, CharParam& ch_, Context&) const
0191 {
0192 ch_ = ch;
0193 return true;
0194 }
0195
0196 template <typename Context>
0197 info what(Context const& ) const
0198 {
0199 return info("literal-char", char_encoding::toucs4(ch));
0200 }
0201
0202 char_type ch;
0203 };
0204
0205
0206
0207 template <typename CharEncoding, typename Tag>
0208 struct char_range
0209 : char_generator<char_range<CharEncoding, Tag>, CharEncoding, Tag>
0210 {
0211 typedef typename CharEncoding::char_type char_type;
0212 typedef CharEncoding char_encoding;
0213
0214 char_range(char_type from, char_type to)
0215 : from(spirit::char_class::convert<char_encoding>::to(Tag(), from))
0216 , to(spirit::char_class::convert<char_encoding>::to(Tag(), to))
0217 {}
0218
0219
0220
0221 template <typename Attribute, typename CharParam, typename Context>
0222 bool test(Attribute const& attr, CharParam& ch, Context&) const
0223 {
0224
0225 ch = attr;
0226 return (from <= char_type(attr)) && (char_type(attr) <= to);
0227 }
0228
0229
0230 template <typename CharParam, typename Context>
0231 bool test(unused_type, CharParam&, Context&) const
0232 {
0233
0234
0235
0236
0237 BOOST_SPIRIT_ASSERT_FAIL(CharParam
0238 , char_range_not_usable_without_attribute, ());
0239 return false;
0240 }
0241
0242 template <typename Context>
0243 info what(Context& ) const
0244 {
0245 info result("char-range", char_encoding::toucs4(from));
0246 boost::get<std::string>(result.value) += '-';
0247 boost::get<std::string>(result.value) += to_utf8(char_encoding::toucs4(to));
0248 return result;
0249 }
0250
0251 char_type from, to;
0252 };
0253
0254
0255
0256 template <typename CharEncoding, typename Tag, bool no_attribute>
0257 struct char_set
0258 : char_generator<char_set<CharEncoding, Tag, no_attribute>
0259 , CharEncoding, Tag>
0260 {
0261 typedef typename CharEncoding::char_type char_type;
0262 typedef CharEncoding char_encoding;
0263
0264 template <typename Context, typename Unused>
0265 struct attribute
0266 : mpl::if_c<no_attribute, unused_type, char_type>
0267 {};
0268
0269 template <typename String>
0270 char_set(String const& str)
0271 {
0272 typedef typename traits::char_type_of<String>::type in_type;
0273
0274 BOOST_SPIRIT_ASSERT_MSG((
0275 (sizeof(char_type) == sizeof(in_type))
0276 ), cannot_convert_string, (String));
0277
0278 typedef spirit::char_class::convert<char_encoding> convert_type;
0279
0280 char_type const* definition =
0281 (char_type const*)traits::get_c_string(str);
0282 char_type ch = convert_type::to(Tag(), *definition++);
0283 while (ch)
0284 {
0285 char_type next = convert_type::to(Tag(), *definition++);
0286 if (next == '-')
0287 {
0288 next = convert_type::to(Tag(), *definition++);
0289 if (next == 0)
0290 {
0291 chset.set(ch);
0292 chset.set('-');
0293 break;
0294 }
0295 chset.set(ch, next);
0296 }
0297 else
0298 {
0299 chset.set(ch);
0300 }
0301 ch = next;
0302 }
0303 }
0304
0305
0306
0307 template <typename Attribute, typename CharParam, typename Context>
0308 bool test(Attribute const& attr, CharParam& ch, Context&) const
0309 {
0310
0311 ch = attr;
0312 return chset.test(char_type(attr));
0313 }
0314
0315
0316 template <typename CharParam, typename Context>
0317 bool test(unused_type, CharParam&, Context&) const
0318 {
0319
0320
0321
0322
0323 BOOST_SPIRIT_ASSERT_FAIL(CharParam
0324 , char_set_not_usable_without_attribute, ());
0325 return false;
0326 }
0327
0328 template <typename Context>
0329 info what(Context& ) const
0330 {
0331 return info("char-set");
0332 }
0333
0334 support::detail::basic_chset<char_type> chset;
0335 };
0336
0337
0338
0339
0340 namespace detail
0341 {
0342 template <typename Modifiers, typename Encoding>
0343 struct basic_literal
0344 {
0345 static bool const lower =
0346 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0347 static bool const upper =
0348 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0349
0350 typedef literal_char<
0351 typename spirit::detail::get_encoding_with_case<
0352 Modifiers, Encoding, lower || upper>::type
0353 , typename get_casetag<Modifiers, lower || upper>::type
0354 , true>
0355 result_type;
0356
0357 template <typename Char>
0358 result_type operator()(Char ch, unused_type) const
0359 {
0360 return result_type(ch);
0361 }
0362
0363 template <typename Char>
0364 result_type operator()(Char const* str, unused_type) const
0365 {
0366 return result_type(str[0]);
0367 }
0368 };
0369 }
0370
0371
0372 template <typename Modifiers>
0373 struct make_primitive<char, Modifiers>
0374 : detail::basic_literal<Modifiers, char_encoding::standard> {};
0375
0376 template <typename Modifiers>
0377 struct make_primitive<char const(&)[2], Modifiers>
0378 : detail::basic_literal<Modifiers, char_encoding::standard> {};
0379
0380
0381 template <typename Modifiers>
0382 struct make_primitive<wchar_t, Modifiers>
0383 : detail::basic_literal<Modifiers, char_encoding::standard_wide> {};
0384
0385 template <typename Modifiers>
0386 struct make_primitive<wchar_t const(&)[2], Modifiers>
0387 : detail::basic_literal<Modifiers, char_encoding::standard_wide> {};
0388
0389
0390 template <typename CharEncoding, typename Modifiers>
0391 struct make_primitive<tag::char_code<tag::char_, CharEncoding>, Modifiers>
0392 {
0393 static bool const lower =
0394 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0395 static bool const upper =
0396 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0397
0398 typedef any_char<
0399 typename spirit::detail::get_encoding_with_case<
0400 Modifiers, CharEncoding, lower || upper>::type
0401 , typename detail::get_casetag<Modifiers, lower || upper>::type
0402 > result_type;
0403
0404 result_type operator()(unused_type, unused_type) const
0405 {
0406 return result_type();
0407 }
0408 };
0409
0410
0411 namespace detail
0412 {
0413 template <typename CharEncoding, typename Modifiers, typename A0
0414 , bool no_attribute>
0415 struct make_char_direct
0416 {
0417 static bool const lower =
0418 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0419 static bool const upper =
0420 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0421
0422 typedef typename spirit::detail::get_encoding_with_case<
0423 Modifiers, CharEncoding, lower || upper>::type encoding;
0424 typedef typename detail::get_casetag<
0425 Modifiers, lower || upper>::type tag;
0426
0427 typedef typename mpl::if_<
0428 traits::is_string<A0>
0429 , char_set<encoding, tag, no_attribute>
0430 , literal_char<encoding, tag, no_attribute>
0431 >::type result_type;
0432
0433 template <typename Terminal>
0434 result_type operator()(Terminal const& term, unused_type) const
0435 {
0436 return result_type(fusion::at_c<0>(term.args));
0437 }
0438 };
0439 }
0440
0441
0442 template <typename CharEncoding, typename Modifiers, typename A0>
0443 struct make_primitive<
0444 terminal_ex<
0445 tag::char_code<tag::char_, CharEncoding>
0446 , fusion::vector1<A0> >
0447 , Modifiers>
0448 : detail::make_char_direct<CharEncoding, Modifiers, A0, false>
0449 {};
0450
0451 template <typename Modifiers, typename A0>
0452 struct make_primitive<
0453 terminal_ex<tag::lit, fusion::vector1<A0> >
0454 , Modifiers
0455 , typename enable_if<traits::is_char<A0> >::type>
0456 : detail::make_char_direct<
0457 typename traits::char_encoding_from_char<
0458 typename traits::char_type_of<A0>::type>::type
0459 , Modifiers, A0, true>
0460 {};
0461
0462
0463
0464 template <typename CharEncoding, typename Modifiers, typename Char>
0465 struct make_primitive<
0466 terminal_ex<
0467 tag::char_code<tag::char_, CharEncoding>
0468 , fusion::vector1<Char(&)[2]> >
0469 , Modifiers>
0470 {
0471 static bool const lower =
0472 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0473 static bool const upper =
0474 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0475
0476 typedef literal_char<
0477 typename spirit::detail::get_encoding_with_case<
0478 Modifiers, CharEncoding, lower || upper>::type
0479 , typename detail::get_casetag<Modifiers, lower || upper>::type
0480 , false
0481 > result_type;
0482
0483 template <typename Terminal>
0484 result_type operator()(Terminal const& term, unused_type) const
0485 {
0486 return result_type(fusion::at_c<0>(term.args)[0]);
0487 }
0488 };
0489
0490
0491
0492 template <typename CharEncoding, typename Modifiers, typename A0, typename A1>
0493 struct make_primitive<
0494 terminal_ex<
0495 tag::char_code<tag::char_, CharEncoding>
0496 , fusion::vector2<A0, A1>
0497 >
0498 , Modifiers>
0499 {
0500 static bool const lower =
0501 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0502 static bool const upper =
0503 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0504
0505 typedef char_range<
0506 typename spirit::detail::get_encoding_with_case<
0507 Modifiers, CharEncoding, lower || upper>::type
0508 , typename detail::get_casetag<Modifiers, lower || upper>::type
0509 > result_type;
0510
0511 template <typename Terminal>
0512 result_type operator()(Terminal const& term, unused_type) const
0513 {
0514 return result_type(fusion::at_c<0>(term.args)
0515 , fusion::at_c<1>(term.args));
0516 }
0517 };
0518
0519 template <typename CharEncoding, typename Modifiers, typename Char>
0520 struct make_primitive<
0521 terminal_ex<
0522 tag::char_code<tag::char_, CharEncoding>
0523 , fusion::vector2<Char(&)[2], Char(&)[2]>
0524 >
0525 , Modifiers>
0526 {
0527 static bool const lower =
0528 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0529 static bool const upper =
0530 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0531
0532 typedef char_range<
0533 typename spirit::detail::get_encoding_with_case<
0534 Modifiers, CharEncoding, lower || upper>::type
0535 , typename detail::get_casetag<Modifiers, lower || upper>::type
0536 > result_type;
0537
0538 template <typename Terminal>
0539 result_type operator()(Terminal const& term, unused_type) const
0540 {
0541 return result_type(fusion::at_c<0>(term.args)[0]
0542 , fusion::at_c<1>(term.args)[0]);
0543 }
0544 };
0545 }}}
0546
0547 #endif