9
3

escape_char.ipp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*=============================================================================
  2. Copyright (c) 2001-2003 Daniel Nuffer
  3. Copyright (c) 2002-2003 Hartmut Kaiser
  4. http://spirit.sourceforge.net/
  5. Use, modification and distribution is subject to the Boost Software
  6. License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  7. http://www.boost.org/LICENSE_1_0.txt)
  8. =============================================================================*/
  9. #ifndef BOOST_SPIRIT_ESCAPE_CHAR_IPP
  10. #define BOOST_SPIRIT_ESCAPE_CHAR_IPP
  11. #include <boost/spirit/home/classic/core/parser.hpp>
  12. #include <boost/spirit/home/classic/core/primitives/numerics.hpp>
  13. #include <boost/spirit/home/classic/core/composite/difference.hpp>
  14. #include <boost/spirit/home/classic/core/composite/sequence.hpp>
  15. ///////////////////////////////////////////////////////////////////////////////
  16. namespace boost { namespace spirit {
  17. BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
  18. ///////////////////////////////////////////////////////////////////////////////
  19. //
  20. // escape_char_parser class
  21. //
  22. ///////////////////////////////////////////////////////////////////////////////
  23. const unsigned long c_escapes = 1;
  24. const unsigned long lex_escapes = c_escapes << 1;
  25. //////////////////////////////////
  26. namespace impl {
  27. //////////////////////////////////
  28. #if defined(BOOST_MSVC)
  29. #pragma warning(push)
  30. #pragma warning(disable:4127)
  31. #endif
  32. template <unsigned long Flags, typename CharT>
  33. struct escape_char_action_parse {
  34. template <typename ParserT, typename ScannerT>
  35. static typename parser_result<ParserT, ScannerT>::type
  36. parse(ScannerT const& scan, ParserT const &p)
  37. {
  38. // Actually decode the escape char.
  39. typedef CharT char_t;
  40. typedef typename ScannerT::iterator_t iterator_t;
  41. typedef typename parser_result<ParserT, ScannerT>::type result_t;
  42. if (scan.first != scan.last) {
  43. iterator_t save = scan.first;
  44. if (result_t hit = p.subject().parse(scan)) {
  45. char_t unescaped;
  46. scan.first = save;
  47. if (*scan.first == '\\') {
  48. ++scan.first;
  49. switch (*scan.first) {
  50. case 'b': unescaped = '\b'; ++scan.first; break;
  51. case 't': unescaped = '\t'; ++scan.first; break;
  52. case 'n': unescaped = '\n'; ++scan.first; break;
  53. case 'f': unescaped = '\f'; ++scan.first; break;
  54. case 'r': unescaped = '\r'; ++scan.first; break;
  55. case '"': unescaped = '"'; ++scan.first; break;
  56. case '\'': unescaped = '\''; ++scan.first; break;
  57. case '\\': unescaped = '\\'; ++scan.first; break;
  58. case 'x': case 'X':
  59. {
  60. char_t hex = 0;
  61. char_t const lim =
  62. (std::numeric_limits<char_t>::max)() >> 4;
  63. ++scan.first;
  64. while (scan.first != scan.last)
  65. {
  66. char_t c = *scan.first;
  67. if (hex > lim && impl::isxdigit_(c))
  68. {
  69. // overflow detected
  70. scan.first = save;
  71. return scan.no_match();
  72. }
  73. if (impl::isdigit_(c))
  74. {
  75. hex <<= 4;
  76. hex |= c - '0';
  77. ++scan.first;
  78. }
  79. else if (impl::isxdigit_(c))
  80. {
  81. hex <<= 4;
  82. c = impl::toupper_(c);
  83. hex |= c - 'A' + 0xA;
  84. ++scan.first;
  85. }
  86. else
  87. {
  88. break; // reached the end of the number
  89. }
  90. }
  91. unescaped = hex;
  92. }
  93. break;
  94. case '0': case '1': case '2': case '3':
  95. case '4': case '5': case '6': case '7':
  96. {
  97. char_t oct = 0;
  98. char_t const lim =
  99. (std::numeric_limits<char_t>::max)() >> 3;
  100. while (scan.first != scan.last)
  101. {
  102. char_t c = *scan.first;
  103. if (oct > lim && (c >= '0' && c <= '7'))
  104. {
  105. // overflow detected
  106. scan.first = save;
  107. return scan.no_match();
  108. }
  109. if (c >= '0' && c <= '7')
  110. {
  111. oct <<= 3;
  112. oct |= c - '0';
  113. ++scan.first;
  114. }
  115. else
  116. {
  117. break; // reached end of digits
  118. }
  119. }
  120. unescaped = oct;
  121. }
  122. break;
  123. default:
  124. if (Flags & c_escapes)
  125. {
  126. // illegal C escape sequence
  127. scan.first = save;
  128. return scan.no_match();
  129. }
  130. else
  131. {
  132. unescaped = *scan.first;
  133. ++scan.first;
  134. }
  135. break;
  136. }
  137. }
  138. else {
  139. unescaped = *scan.first;
  140. ++scan.first;
  141. }
  142. scan.do_action(p.predicate(), unescaped, save, scan.first);
  143. return hit;
  144. }
  145. }
  146. return scan.no_match(); // overflow detected
  147. }
  148. };
  149. #if defined(BOOST_MSVC)
  150. #pragma warning(pop)
  151. #endif
  152. //////////////////////////////////
  153. template <typename CharT>
  154. struct escape_char_parse {
  155. template <typename ScannerT, typename ParserT>
  156. static typename parser_result<ParserT, ScannerT>::type
  157. parse(ScannerT const &scan, ParserT const &/*p*/)
  158. {
  159. typedef
  160. uint_parser<CharT, 8, 1,
  161. std::numeric_limits<CharT>::digits / 3 + 1
  162. >
  163. oct_parser_t;
  164. typedef
  165. uint_parser<CharT, 16, 1,
  166. std::numeric_limits<CharT>::digits / 4 + 1
  167. >
  168. hex_parser_t;
  169. typedef alternative<difference<anychar_parser, chlit<CharT> >,
  170. sequence<chlit<CharT>, alternative<alternative<oct_parser_t,
  171. sequence<inhibit_case<chlit<CharT> >, hex_parser_t > >,
  172. difference<difference<anychar_parser,
  173. inhibit_case<chlit<CharT> > >, oct_parser_t > > > >
  174. parser_t;
  175. static parser_t p =
  176. ( (anychar_p - chlit<CharT>(CharT('\\')))
  177. | (chlit<CharT>(CharT('\\')) >>
  178. ( oct_parser_t()
  179. | as_lower_d[chlit<CharT>(CharT('x'))] >> hex_parser_t()
  180. | (anychar_p - as_lower_d[chlit<CharT>(CharT('x'))] - oct_parser_t())
  181. )
  182. ));
  183. BOOST_SPIRIT_DEBUG_TRACE_NODE(p,
  184. (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_ESCAPE_CHAR) != 0);
  185. return p.parse(scan);
  186. }
  187. };
  188. ///////////////////////////////////////////////////////////////////////////////
  189. } // namespace impl
  190. ///////////////////////////////////////////////////////////////////////////////
  191. BOOST_SPIRIT_CLASSIC_NAMESPACE_END
  192. }} // namespace boost::spirit
  193. #endif