cpp_chlit_grammar.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. /*=============================================================================
  2. Boost.Wave: A Standard compliant C++ preprocessor library
  3. http://www.boost.org/
  4. Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
  5. Software License, Version 1.0. (See accompanying file
  6. LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. =============================================================================*/
  8. #if !defined(BOOST_CPP_CHLIT_GRAMMAR_HPP_9527D349_6592_449A_A409_42A001E6C64C_INCLUDED)
  9. #define BOOST_CPP_CHLIT_GRAMMAR_HPP_9527D349_6592_449A_A409_42A001E6C64C_INCLUDED
  10. #include <limits> // std::numeric_limits
  11. #include <climits> // CHAR_BIT
  12. #include <boost/wave/wave_config.hpp>
  13. #include <boost/static_assert.hpp>
  14. #include <boost/cstdint.hpp>
  15. #include <boost/spirit/include/classic_core.hpp>
  16. #include <boost/spirit/include/classic_closure.hpp>
  17. #include <boost/spirit/include/classic_if.hpp>
  18. #include <boost/spirit/include/classic_assign_actor.hpp>
  19. #include <boost/spirit/include/classic_push_back_actor.hpp>
  20. #include <boost/spirit/include/phoenix1_operators.hpp>
  21. #include <boost/spirit/include/phoenix1_primitives.hpp>
  22. #include <boost/spirit/include/phoenix1_statements.hpp>
  23. #include <boost/spirit/include/phoenix1_functions.hpp>
  24. #include <boost/wave/cpp_exceptions.hpp>
  25. #include <boost/wave/grammars/cpp_literal_grammar_gen.hpp>
  26. #if !defined(spirit_append_actor)
  27. #define spirit_append_actor(actor) boost::spirit::classic::push_back_a(actor)
  28. #define spirit_assign_actor(actor) boost::spirit::classic::assign_a(actor)
  29. #endif // !defined(spirit_append_actor)
  30. // this must occur after all of the includes and before any code appears
  31. #ifdef BOOST_HAS_ABI_HEADERS
  32. #include BOOST_ABI_PREFIX
  33. #endif
  34. ///////////////////////////////////////////////////////////////////////////////
  35. //
  36. // Reusable grammar to parse a C++ style character literal
  37. //
  38. ///////////////////////////////////////////////////////////////////////////////
  39. namespace boost {
  40. namespace wave {
  41. namespace grammars {
  42. namespace closures {
  43. struct chlit_closure
  44. : boost::spirit::classic::closure<chlit_closure, boost::uint32_t, bool>
  45. {
  46. member1 value;
  47. member2 long_lit;
  48. };
  49. }
  50. namespace impl {
  51. ///////////////////////////////////////////////////////////////////////////////
  52. //
  53. // compose a multibyte character literal
  54. //
  55. ///////////////////////////////////////////////////////////////////////////////
  56. struct compose_character_literal {
  57. template <typename A1, typename A2, typename A3, typename A4>
  58. struct result
  59. {
  60. typedef void type;
  61. };
  62. void
  63. operator()(boost::uint32_t& value, bool long_lit, bool& overflow,
  64. boost::uint32_t character) const
  65. {
  66. // The following assumes that wchar_t is max. 32 Bit
  67. BOOST_STATIC_ASSERT(sizeof(wchar_t) <= 4);
  68. static boost::uint32_t masks[] = {
  69. 0x000000ff, 0x0000ffff, 0x00ffffff, 0xffffffff
  70. };
  71. static boost::uint32_t overflow_masks[] = {
  72. 0xff000000, 0xffff0000, 0xffffff00, 0xffffffff
  73. };
  74. if (long_lit) {
  75. // make sure no overflow will occur below
  76. if ((value & overflow_masks[sizeof(wchar_t)-1]) != 0) {
  77. overflow |= true;
  78. }
  79. else {
  80. // calculate the new value (avoiding a warning regarding
  81. // shifting count >= size of the type)
  82. value <<= CHAR_BIT * (sizeof(wchar_t)-1);
  83. value <<= CHAR_BIT;
  84. value |= character & masks[sizeof(wchar_t)-1];
  85. }
  86. }
  87. else {
  88. // make sure no overflow will occur below
  89. if ((value & overflow_masks[sizeof(char)-1]) != 0) {
  90. overflow |= true;
  91. }
  92. else {
  93. // calculate the new value
  94. value <<= CHAR_BIT * sizeof(char);
  95. value |= character & masks[sizeof(char)-1];
  96. }
  97. }
  98. }
  99. };
  100. phoenix::function<compose_character_literal> const compose;
  101. } // namespace impl
  102. ///////////////////////////////////////////////////////////////////////////////
  103. // define, whether the rule's should generate some debug output
  104. #define TRACE_CHLIT_GRAMMAR \
  105. bool(BOOST_SPIRIT_DEBUG_FLAGS_CPP & BOOST_SPIRIT_DEBUG_FLAGS_CHLIT_GRAMMAR) \
  106. /**/
  107. struct chlit_grammar :
  108. public boost::spirit::classic::grammar<chlit_grammar,
  109. closures::chlit_closure::context_t>
  110. {
  111. chlit_grammar()
  112. : overflow(false)
  113. {
  114. BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME(*this, "chlit_grammar",
  115. TRACE_CHLIT_GRAMMAR);
  116. }
  117. // no need for copy constructor/assignment operator
  118. chlit_grammar(chlit_grammar const&);
  119. chlit_grammar& operator=(chlit_grammar const&);
  120. template <typename ScannerT>
  121. struct definition
  122. {
  123. typedef boost::spirit::classic::rule<
  124. ScannerT, closures::chlit_closure::context_t>
  125. rule_t;
  126. rule_t ch_lit;
  127. definition(chlit_grammar const &self)
  128. {
  129. using namespace boost::spirit::classic;
  130. namespace phx = phoenix;
  131. // special parsers for '\x..' and L'\x....'
  132. typedef uint_parser<
  133. unsigned int, 16, 1, 2 * sizeof(char)
  134. > hex_char_parser_type;
  135. typedef uint_parser<
  136. unsigned int, 16, 1, 2 * sizeof(wchar_t)
  137. > hex_wchar_parser_type;
  138. // the rule for a character literal
  139. ch_lit
  140. = eps_p[(self.value = phx::val(0), self.long_lit = phx::val(false))]
  141. >> !ch_p('L')[self.long_lit = phx::val(true)]
  142. >> ch_p('\'')
  143. >> +( (
  144. ch_p('\\')
  145. >> ( ch_p('a') // BEL
  146. [
  147. impl::compose(self.value, self.long_lit,
  148. phx::var(self.overflow), phx::val(0x07))
  149. ]
  150. | ch_p('b') // BS
  151. [
  152. impl::compose(self.value, self.long_lit,
  153. phx::var(self.overflow), phx::val(0x08))
  154. ]
  155. | ch_p('t') // HT
  156. [
  157. impl::compose(self.value, self.long_lit,
  158. phx::var(self.overflow), phx::val(0x09))
  159. ]
  160. | ch_p('n') // NL
  161. [
  162. impl::compose(self.value, self.long_lit,
  163. phx::var(self.overflow), phx::val(0x0a))
  164. ]
  165. | ch_p('v') // VT
  166. [
  167. impl::compose(self.value, self.long_lit,
  168. phx::var(self.overflow), phx::val(0x0b))
  169. ]
  170. | (ch_p('e') | ch_p('E')) // ESC
  171. [
  172. impl::compose(self.value, self.long_lit,
  173. phx::var(self.overflow), phx::val(0x1b))
  174. ]
  175. | ch_p('f') // FF
  176. [
  177. impl::compose(self.value, self.long_lit,
  178. phx::var(self.overflow), phx::val(0x0c))
  179. ]
  180. | ch_p('r') // CR
  181. [
  182. impl::compose(self.value, self.long_lit,
  183. phx::var(self.overflow), phx::val(0x0d))
  184. ]
  185. | ch_p('?')
  186. [
  187. impl::compose(self.value, self.long_lit,
  188. phx::var(self.overflow), phx::val('?'))
  189. ]
  190. | ch_p('\'')
  191. [
  192. impl::compose(self.value, self.long_lit,
  193. phx::var(self.overflow), phx::val('\''))
  194. ]
  195. | ch_p('\"')
  196. [
  197. impl::compose(self.value, self.long_lit,
  198. phx::var(self.overflow), phx::val('\"'))
  199. ]
  200. | ch_p('\\')
  201. [
  202. impl::compose(self.value, self.long_lit,
  203. phx::var(self.overflow), phx::val('\\'))
  204. ]
  205. | ch_p('x')
  206. >> if_p(self.long_lit)
  207. [
  208. hex_wchar_parser_type()
  209. [
  210. impl::compose(self.value, self.long_lit,
  211. phx::var(self.overflow), phx::arg1)
  212. ]
  213. ]
  214. .else_p
  215. [
  216. hex_char_parser_type()
  217. [
  218. impl::compose(self.value, self.long_lit,
  219. phx::var(self.overflow), phx::arg1)
  220. ]
  221. ]
  222. | ch_p('u')
  223. >> uint_parser<unsigned int, 16, 4, 4>()
  224. [
  225. impl::compose(self.value, self.long_lit,
  226. phx::var(self.overflow), phx::arg1)
  227. ]
  228. | ch_p('U')
  229. >> uint_parser<unsigned int, 16, 8, 8>()
  230. [
  231. impl::compose(self.value, self.long_lit,
  232. phx::var(self.overflow), phx::arg1)
  233. ]
  234. | uint_parser<unsigned int, 8, 1, 3>()
  235. [
  236. impl::compose(self.value, self.long_lit,
  237. phx::var(self.overflow), phx::arg1)
  238. ]
  239. )
  240. )
  241. | ~eps_p(ch_p('\'')) >> anychar_p
  242. [
  243. impl::compose(self.value, self.long_lit,
  244. phx::var(self.overflow), phx::arg1)
  245. ]
  246. )
  247. >> ch_p('\'')
  248. ;
  249. BOOST_SPIRIT_DEBUG_TRACE_RULE(ch_lit, TRACE_CHLIT_GRAMMAR);
  250. }
  251. // start rule of this grammar
  252. rule_t const& start() const
  253. { return ch_lit; }
  254. };
  255. // flag signaling integer overflow during value composition
  256. mutable bool overflow;
  257. };
  258. #undef TRACE_CHLIT_GRAMMAR
  259. ///////////////////////////////////////////////////////////////////////////////
  260. //
  261. // The following function is defined here, to allow the separation of
  262. // the compilation of the intlit_grammap from the function using it.
  263. //
  264. ///////////////////////////////////////////////////////////////////////////////
  265. #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
  266. #define BOOST_WAVE_CHLITGRAMMAR_GEN_INLINE
  267. #else
  268. #define BOOST_WAVE_CHLITGRAMMAR_GEN_INLINE inline
  269. #endif
  270. template <typename IntegralResult, typename TokenT>
  271. BOOST_WAVE_CHLITGRAMMAR_GEN_INLINE
  272. IntegralResult
  273. chlit_grammar_gen<IntegralResult, TokenT>::evaluate(TokenT const &token, value_error &status)
  274. {
  275. using namespace boost::spirit::classic;
  276. chlit_grammar g;
  277. IntegralResult result = 0;
  278. typename TokenT::string_type const &token_val = token.get_value();
  279. parse_info<typename TokenT::string_type::const_iterator> hit =
  280. parse(token_val.begin(), token_val.end(), g[spirit_assign_actor(result)]);
  281. if (!hit.hit) {
  282. BOOST_WAVE_THROW(preprocess_exception, ill_formed_character_literal,
  283. token_val.c_str(), token.get_position());
  284. }
  285. else {
  286. // range check
  287. if ('L' == token_val[0]) {
  288. // recognized wide character
  289. if (g.overflow ||
  290. result > (IntegralResult)(std::numeric_limits<wchar_t>::max)())
  291. {
  292. // out of range
  293. status = error_character_overflow;
  294. }
  295. }
  296. else {
  297. // recognized narrow ('normal') character
  298. if (g.overflow ||
  299. result > (IntegralResult)(std::numeric_limits<unsigned char>::max)())
  300. {
  301. // out of range
  302. status = error_character_overflow;
  303. }
  304. }
  305. }
  306. return result;
  307. }
  308. #undef BOOST_WAVE_CHLITGRAMMAR_GEN_INLINE
  309. ///////////////////////////////////////////////////////////////////////////////
  310. } // namespace grammars
  311. } // namespace wave
  312. } // namespace boost
  313. // the suffix header occurs after all of the code
  314. #ifdef BOOST_HAS_ABI_HEADERS
  315. #include BOOST_ABI_SUFFIX
  316. #endif
  317. #endif // !defined(BOOST_CPP_CHLIT_GRAMMAR_HPP_9527D349_6592_449A_A409_42A001E6C64C_INCLUDED)