1 /*=============================================================================
2 Copyright (c) 2001-2003 Daniel Nuffer
3 Copyright (c) 2002-2003 Hartmut Kaiser
4 http://spirit.sourceforge.net/
6 Use, modification and distribution is subject to the Boost Software
7 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8 http://www.boost.org/LICENSE_1_0.txt)
9 =============================================================================*/
10 #ifndef BOOST_SPIRIT_ESCAPE_CHAR_IPP
11 #define BOOST_SPIRIT_ESCAPE_CHAR_IPP
13 #include <boost/spirit/home/classic/core/parser.hpp>
14 #include <boost/spirit/home/classic/core/primitives/numerics.hpp>
15 #include <boost/spirit/home/classic/core/composite/difference.hpp>
16 #include <boost/spirit/home/classic/core/composite/sequence.hpp>
18 ///////////////////////////////////////////////////////////////////////////////
19 namespace boost { namespace spirit {
21 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
23 ///////////////////////////////////////////////////////////////////////////////
25 // escape_char_parser class
27 ///////////////////////////////////////////////////////////////////////////////
29 const unsigned long c_escapes = 1;
30 const unsigned long lex_escapes = c_escapes << 1;
32 //////////////////////////////////
35 //////////////////////////////////
36 #if (defined(BOOST_MSVC) && (BOOST_MSVC <= 1310))
38 #pragma warning(disable:4127)
40 template <unsigned long Flags, typename CharT>
41 struct escape_char_action_parse {
43 template <typename ParserT, typename ScannerT>
44 static typename parser_result<ParserT, ScannerT>::type
45 parse(ScannerT const& scan, ParserT const &p)
47 // Actually decode the escape char.
49 typedef typename ScannerT::iterator_t iterator_t;
50 typedef typename parser_result<ParserT, ScannerT>::type result_t;
52 if (scan.first != scan.last) {
54 iterator_t save = scan.first;
55 if (result_t hit = p.subject().parse(scan)) {
60 if (*scan.first == '\\') {
63 switch (*scan.first) {
64 case 'b': unescaped = '\b'; ++scan.first; break;
65 case 't': unescaped = '\t'; ++scan.first; break;
66 case 'n': unescaped = '\n'; ++scan.first; break;
67 case 'f': unescaped = '\f'; ++scan.first; break;
68 case 'r': unescaped = '\r'; ++scan.first; break;
69 case '"': unescaped = '"'; ++scan.first; break;
70 case '\'': unescaped = '\''; ++scan.first; break;
71 case '\\': unescaped = '\\'; ++scan.first; break;
77 (std::numeric_limits<char_t>::max)() >> 4;
80 while (scan.first != scan.last)
82 char_t c = *scan.first;
83 if (hex > lim && impl::isxdigit_(c))
87 return scan.no_match();
89 if (impl::isdigit_(c))
95 else if (impl::isxdigit_(c))
98 c = impl::toupper_(c);
104 break; // reached the end of the number
111 case '0': case '1': case '2': case '3':
112 case '4': case '5': case '6': case '7':
116 (std::numeric_limits<char_t>::max)() >> 3;
117 while (scan.first != scan.last)
119 char_t c = *scan.first;
120 if (oct > lim && (c >= '0' && c <= '7'))
124 return scan.no_match();
127 if (c >= '0' && c <= '7')
135 break; // reached end of digits
143 if (Flags & c_escapes)
145 // illegal C escape sequence
147 return scan.no_match();
151 unescaped = *scan.first;
158 unescaped = *scan.first;
162 scan.do_action(p.predicate(), unescaped, save, scan.first);
166 return scan.no_match(); // overflow detected
169 #if (defined(BOOST_MSVC) && (BOOST_MSVC <= 1310))
173 //////////////////////////////////
174 template <typename CharT>
175 struct escape_char_parse {
177 template <typename ScannerT, typename ParserT>
178 static typename parser_result<ParserT, ScannerT>::type
179 parse(ScannerT const &scan, ParserT const &/*p*/)
182 uint_parser<CharT, 8, 1,
183 std::numeric_limits<CharT>::digits / 3 + 1
187 uint_parser<CharT, 16, 1,
188 std::numeric_limits<CharT>::digits / 4 + 1
192 typedef alternative<difference<anychar_parser, chlit<CharT> >,
193 sequence<chlit<CharT>, alternative<alternative<oct_parser_t,
194 sequence<inhibit_case<chlit<CharT> >, hex_parser_t > >,
195 difference<difference<anychar_parser,
196 inhibit_case<chlit<CharT> > >, oct_parser_t > > > >
200 ( (anychar_p - chlit<CharT>(CharT('\\')))
201 | (chlit<CharT>(CharT('\\')) >>
203 | as_lower_d[chlit<CharT>(CharT('x'))] >> hex_parser_t()
204 | (anychar_p - as_lower_d[chlit<CharT>(CharT('x'))] - oct_parser_t())
208 BOOST_SPIRIT_DEBUG_TRACE_NODE(p,
209 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_ESCAPE_CHAR) != 0);
211 return p.parse(scan);
215 ///////////////////////////////////////////////////////////////////////////////
218 ///////////////////////////////////////////////////////////////////////////////
219 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
221 }} // namespace boost::spirit