cpp_chlit_grammar.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  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('f') // FF
  171. [
  172. impl::compose(self.value, self.long_lit,
  173. phx::var(self.overflow), phx::val(0x0c))
  174. ]
  175. | ch_p('r') // CR
  176. [
  177. impl::compose(self.value, self.long_lit,
  178. phx::var(self.overflow), phx::val(0x0d))
  179. ]
  180. | ch_p('?')
  181. [
  182. impl::compose(self.value, self.long_lit,
  183. phx::var(self.overflow), phx::val('?'))
  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('x')
  201. >> if_p(self.long_lit)
  202. [
  203. hex_wchar_parser_type()
  204. [
  205. impl::compose(self.value, self.long_lit,
  206. phx::var(self.overflow), phx::arg1)
  207. ]
  208. ]
  209. .else_p
  210. [
  211. hex_char_parser_type()
  212. [
  213. impl::compose(self.value, self.long_lit,
  214. phx::var(self.overflow), phx::arg1)
  215. ]
  216. ]
  217. | ch_p('u')
  218. >> uint_parser<unsigned int, 16, 4, 4>()
  219. [
  220. impl::compose(self.value, self.long_lit,
  221. phx::var(self.overflow), phx::arg1)
  222. ]
  223. | ch_p('U')
  224. >> uint_parser<unsigned int, 16, 8, 8>()
  225. [
  226. impl::compose(self.value, self.long_lit,
  227. phx::var(self.overflow), phx::arg1)
  228. ]
  229. | uint_parser<unsigned int, 8, 1, 3>()
  230. [
  231. impl::compose(self.value, self.long_lit,
  232. phx::var(self.overflow), phx::arg1)
  233. ]
  234. )
  235. )
  236. | ~eps_p(ch_p('\'')) >> anychar_p
  237. [
  238. impl::compose(self.value, self.long_lit,
  239. phx::var(self.overflow), phx::arg1)
  240. ]
  241. )
  242. >> ch_p('\'')
  243. ;
  244. BOOST_SPIRIT_DEBUG_TRACE_RULE(ch_lit, TRACE_CHLIT_GRAMMAR);
  245. }
  246. // start rule of this grammar
  247. rule_t const& start() const
  248. { return ch_lit; }
  249. };
  250. // flag signaling integer overflow during value composition
  251. mutable bool overflow;
  252. };
  253. #undef TRACE_CHLIT_GRAMMAR
  254. ///////////////////////////////////////////////////////////////////////////////
  255. //
  256. // The following function is defined here, to allow the separation of
  257. // the compilation of the intlit_grammap from the function using it.
  258. //
  259. ///////////////////////////////////////////////////////////////////////////////
  260. #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
  261. #define BOOST_WAVE_CHLITGRAMMAR_GEN_INLINE
  262. #else
  263. #define BOOST_WAVE_CHLITGRAMMAR_GEN_INLINE inline
  264. #endif
  265. template <typename IntegralResult, typename TokenT>
  266. BOOST_WAVE_CHLITGRAMMAR_GEN_INLINE
  267. IntegralResult
  268. chlit_grammar_gen<IntegralResult, TokenT>::evaluate(TokenT const &token, value_error &status)
  269. {
  270. using namespace boost::spirit::classic;
  271. chlit_grammar g;
  272. IntegralResult result = 0;
  273. typename TokenT::string_type const &token_val = token.get_value();
  274. parse_info<typename TokenT::string_type::const_iterator> hit =
  275. parse(token_val.begin(), token_val.end(), g[spirit_assign_actor(result)]);
  276. if (!hit.hit) {
  277. BOOST_WAVE_THROW(preprocess_exception, ill_formed_character_literal,
  278. token_val.c_str(), token.get_position());
  279. }
  280. else {
  281. // range check
  282. if ('L' == token_val[0]) {
  283. // recognized wide character
  284. if (g.overflow ||
  285. result > (IntegralResult)(std::numeric_limits<wchar_t>::max)())
  286. {
  287. // out of range
  288. status = error_character_overflow;
  289. }
  290. }
  291. else {
  292. // recognized narrow ('normal') character
  293. if (g.overflow ||
  294. result > (IntegralResult)(std::numeric_limits<unsigned char>::max)())
  295. {
  296. // out of range
  297. status = error_character_overflow;
  298. }
  299. }
  300. }
  301. return result;
  302. }
  303. #undef BOOST_WAVE_CHLITGRAMMAR_GEN_INLINE
  304. ///////////////////////////////////////////////////////////////////////////////
  305. } // namespace grammars
  306. } // namespace wave
  307. } // namespace boost
  308. // the suffix header occurs after all of the code
  309. #ifdef BOOST_HAS_ABI_HEADERS
  310. #include BOOST_ABI_SUFFIX
  311. #endif
  312. #endif // !defined(BOOST_CPP_CHLIT_GRAMMAR_HPP_9527D349_6592_449A_A409_42A001E6C64C_INCLUDED)