Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 10:02:07

0001 /*=============================================================================
0002     Copyright (c) 2001-2003 Daniel Nuffer
0003     Copyright (c) 2002-2003 Hartmut Kaiser
0004     http://spirit.sourceforge.net/
0005 
0006     Use, modification and distribution is subject to the Boost Software
0007     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0008     http://www.boost.org/LICENSE_1_0.txt)
0009 =============================================================================*/
0010 #ifndef BOOST_SPIRIT_ESCAPE_CHAR_IPP
0011 #define BOOST_SPIRIT_ESCAPE_CHAR_IPP
0012 
0013 #include <boost/spirit/home/classic/core/parser.hpp>
0014 #include <boost/spirit/home/classic/core/primitives/numerics.hpp>
0015 #include <boost/spirit/home/classic/core/composite/difference.hpp>
0016 #include <boost/spirit/home/classic/core/composite/sequence.hpp>
0017 
0018 ///////////////////////////////////////////////////////////////////////////////
0019 namespace boost { namespace spirit {
0020 
0021 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
0022 
0023 ///////////////////////////////////////////////////////////////////////////////
0024 //
0025 //  escape_char_parser class
0026 //
0027 ///////////////////////////////////////////////////////////////////////////////
0028 
0029 const unsigned long c_escapes = 1;
0030 const unsigned long lex_escapes = c_escapes << 1;
0031 
0032 //////////////////////////////////
0033 namespace impl {
0034 
0035     //////////////////////////////////
0036 #if defined(BOOST_MSVC)
0037 #pragma warning(push)
0038 #pragma warning(disable:4127)
0039 #endif
0040     template <unsigned long Flags, typename CharT>
0041     struct escape_char_action_parse {
0042 
0043         template <typename ParserT, typename ScannerT>
0044         static typename parser_result<ParserT, ScannerT>::type
0045         parse(ScannerT const& scan, ParserT const &p)
0046         {
0047             // Actually decode the escape char.
0048             typedef CharT char_t;
0049             typedef typename ScannerT::iterator_t iterator_t;
0050             typedef typename parser_result<ParserT, ScannerT>::type result_t;
0051 
0052             if (scan.first != scan.last) {
0053 
0054                 iterator_t save = scan.first;
0055                 if (result_t hit = p.subject().parse(scan)) {
0056 
0057                     char_t unescaped;
0058 
0059                     scan.first = save;
0060                     if (*scan.first == '\\') {
0061 
0062                         ++scan.first;
0063                         switch (*scan.first) {
0064                         case 'b':   unescaped = '\b';   ++scan.first; break;
0065                         case 't':   unescaped = '\t';   ++scan.first; break;
0066                         case 'n':   unescaped = '\n';   ++scan.first; break;
0067                         case 'f':   unescaped = '\f';   ++scan.first; break;
0068                         case 'r':   unescaped = '\r';   ++scan.first; break;
0069                         case '"':   unescaped = '"';    ++scan.first; break;
0070                         case '\'':  unescaped = '\'';   ++scan.first; break;
0071                         case '\\':  unescaped = '\\';   ++scan.first; break;
0072 
0073                         case 'x': case 'X':
0074                             {
0075                                 char_t hex = 0;
0076                                 char_t const lim =
0077                                     (std::numeric_limits<char_t>::max)() >> 4;
0078 
0079                                 ++scan.first;
0080                                 while (scan.first != scan.last)
0081                                 {
0082                                     char_t c = *scan.first;
0083                                     if (hex > lim && impl::isxdigit_(c))
0084                                     {
0085                                         // overflow detected
0086                                         scan.first = save;
0087                                         return scan.no_match();
0088                                     }
0089                                     if (impl::isdigit_(c))
0090                                     {
0091                                         hex <<= 4;
0092                                         hex |= c - '0';
0093                                         ++scan.first;
0094                                     }
0095                                     else if (impl::isxdigit_(c))
0096                                     {
0097                                         hex <<= 4;
0098                                         c = impl::toupper_(c);
0099                                         hex |= c - 'A' + 0xA;
0100                                         ++scan.first;
0101                                     }
0102                                     else
0103                                     {
0104                                         break; // reached the end of the number
0105                                     }
0106                                 }
0107                                 unescaped = hex;
0108                             }
0109                             break;
0110 
0111                         case '0': case '1': case '2': case '3':
0112                         case '4': case '5': case '6': case '7':
0113                             {
0114                                 char_t oct = 0;
0115                                 char_t const lim =
0116                                     (std::numeric_limits<char_t>::max)() >> 3;
0117                                 while (scan.first != scan.last)
0118                                 {
0119                                     char_t c = *scan.first;
0120                                     if (oct > lim && (c >= '0' && c <= '7'))
0121                                     {
0122                                         // overflow detected
0123                                         scan.first = save;
0124                                         return scan.no_match();
0125                                     }
0126 
0127                                     if (c >= '0' && c <= '7')
0128                                     {
0129                                         oct <<= 3;
0130                                         oct |= c - '0';
0131                                         ++scan.first;
0132                                     }
0133                                     else
0134                                     {
0135                                         break; // reached end of digits
0136                                     }
0137                                 }
0138                                 unescaped = oct;
0139                             }
0140                             break;
0141 
0142                         default:
0143                             if (Flags & c_escapes)
0144                             {
0145                                 // illegal C escape sequence
0146                                 scan.first = save;
0147                                 return scan.no_match();
0148                             }
0149                             else
0150                             {
0151                                 unescaped = *scan.first;
0152                                 ++scan.first;
0153                             }
0154                             break;
0155                         }
0156                     }
0157                     else {
0158                         unescaped = *scan.first;
0159                         ++scan.first;
0160                     }
0161 
0162                     scan.do_action(p.predicate(), unescaped, save, scan.first);
0163                     return hit;
0164                 }
0165             }
0166             return scan.no_match(); // overflow detected
0167         }
0168     };
0169 #if defined(BOOST_MSVC)
0170 #pragma warning(pop)
0171 #endif
0172 
0173     //////////////////////////////////
0174     template <typename CharT>
0175     struct escape_char_parse {
0176 
0177         template <typename ScannerT, typename ParserT>
0178         static typename parser_result<ParserT, ScannerT>::type
0179         parse(ScannerT const &scan, ParserT const &/*p*/)
0180         {
0181             typedef
0182                 uint_parser<CharT, 8, 1,
0183                     std::numeric_limits<CharT>::digits / 3 + 1
0184                 >
0185                 oct_parser_t;
0186             typedef
0187                 uint_parser<CharT, 16, 1,
0188                     std::numeric_limits<CharT>::digits / 4 + 1
0189                 >
0190                 hex_parser_t;
0191 
0192             typedef alternative<difference<anychar_parser, chlit<CharT> >,
0193                 sequence<chlit<CharT>, alternative<alternative<oct_parser_t,
0194                 sequence<inhibit_case<chlit<CharT> >, hex_parser_t > >,
0195                 difference<difference<anychar_parser,
0196                 inhibit_case<chlit<CharT> > >, oct_parser_t > > > >
0197                 parser_t;
0198 
0199             static parser_t p =
0200                 ( (anychar_p - chlit<CharT>(CharT('\\')))
0201                 | (chlit<CharT>(CharT('\\')) >>
0202                     (  oct_parser_t()
0203                      | as_lower_d[chlit<CharT>(CharT('x'))] >> hex_parser_t()
0204                      | (anychar_p - as_lower_d[chlit<CharT>(CharT('x'))] - oct_parser_t())
0205                     )
0206                 ));
0207 
0208             BOOST_SPIRIT_DEBUG_TRACE_NODE(p,
0209                 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_ESCAPE_CHAR) != 0);
0210 
0211             return p.parse(scan);
0212         }
0213     };
0214 
0215 ///////////////////////////////////////////////////////////////////////////////
0216 } // namespace impl
0217 
0218 ///////////////////////////////////////////////////////////////////////////////
0219 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
0220 
0221 }} // namespace boost::spirit
0222 
0223 #endif
0224