File indexing completed on 2025-01-31 10:02:07
0001
0002
0003
0004
0005
0006
0007
0008
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
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
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
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;
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
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;
0136 }
0137 }
0138 unescaped = oct;
0139 }
0140 break;
0141
0142 default:
0143 if (Flags & c_escapes)
0144 {
0145
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();
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 &)
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 }
0217
0218
0219 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
0220
0221 }}
0222
0223 #endif
0224