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