Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-19 09:47:43

0001 /*=============================================================================
0002     Copyright (c) 2001-2011 Joel de Guzman
0003     Copyright (c) 2001-2011 Hartmut Kaiser
0004     Copyright (c)      2010 Bryce Lelbach
0005 
0006     Distributed under the Boost Software License, Version 1.0. (See accompanying
0007     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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     // Enablers
0042     ///////////////////////////////////////////////////////////////////////////
0043     template <typename CharEncoding>
0044     struct use_terminal<qi::domain
0045       , terminal<
0046             tag::char_code<tag::char_, CharEncoding>    // enables char_
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>    // enables char_('x'), char_("x")
0054           , fusion::vector1<A0>                         // and char_("a-z0-9")
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>    // enables char_('a','z')
0062           , fusion::vector2<A0, A1>
0063         >
0064     > : mpl::true_ {};
0065 
0066     template <typename CharEncoding>                    // enables *lazy* char_('x'), char_("x")
0067     struct use_lazy_terminal<                           // and char_("a-z0-9")
0068         qi::domain
0069       , tag::char_code<tag::char_, CharEncoding>
0070       , 1 // arity
0071     > : mpl::true_ {};
0072 
0073     template <typename CharEncoding>                    // enables *lazy* char_('a','z')
0074     struct use_lazy_terminal<
0075         qi::domain
0076       , tag::char_code<tag::char_, CharEncoding>
0077       , 2 // arity
0078     > : mpl::true_ {};
0079 
0080     template <>
0081     struct use_terminal<qi::domain, char>               // enables 'x'
0082       : mpl::true_ {};
0083 
0084     template <>
0085     struct use_terminal<qi::domain, char[2]>            // enables "x"
0086       : mpl::true_ {};
0087 
0088     template <>
0089     struct use_terminal<qi::domain, wchar_t>            // enables wchar_t
0090       : mpl::true_ {};
0091 
0092     template <>
0093     struct use_terminal<qi::domain, wchar_t[2]>         // enables L"x"
0094       : mpl::true_ {};
0095 
0096     // enables lit(...)
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; // lit('x') is equivalent to 'x'
0108 #endif
0109     using spirit::lit_type;
0110 
0111     ///////////////////////////////////////////////////////////////////////////
0112     // Parser for a single character
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& /*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> // case insensitive
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_);  // optimize for token based parsing
0182             return this->lo == ch || this->hi == ch;
0183         }
0184 
0185         template <typename Context>
0186         info what(Context& /*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     // Parser for a character range
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_);  // optimize for token based parsing
0214             return !(ch < from) && !(to < ch);
0215         }
0216 
0217         template <typename Context>
0218         info what(Context& /*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> // case insensitive
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_);  // optimize for token based parsing
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& /*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     // Parser for a character set
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& /*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> // case insensitive
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& /*context*/) const
0395         {
0396             return info("no-case-char-set");
0397         }
0398 
0399         support::detail::basic_chset<char_type> chset;
0400     };
0401 
0402     ///////////////////////////////////////////////////////////////////////////
0403     // Parser generators: make_xxx function (objects)
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     // char_('x')
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     // lit('x')
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]> // For single char strings
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]> // For single char strings
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