1 /*=============================================================================
2 Boost.Wave: A Standard compliant C++ preprocessor library
6 Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
7 Software License, Version 1.0. (See accompanying file
8 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 =============================================================================*/
11 #if !defined(CPP_CHLIT_GRAMMAR_HPP_9527D349_6592_449A_A409_42A001E6C64C_INCLUDED)
12 #define CPP_CHLIT_GRAMMAR_HPP_9527D349_6592_449A_A409_42A001E6C64C_INCLUDED
14 #include <limits> // std::numeric_limits
15 #include <climits> // CHAR_BIT
17 #include <boost/wave/wave_config.hpp>
19 #include <boost/static_assert.hpp>
20 #include <boost/cstdint.hpp>
22 #include <boost/spirit/include/classic_core.hpp>
23 #include <boost/spirit/include/classic_closure.hpp>
24 #include <boost/spirit/include/classic_if.hpp>
25 #include <boost/spirit/include/classic_assign_actor.hpp>
26 #include <boost/spirit/include/classic_push_back_actor.hpp>
28 #include <boost/spirit/include/phoenix1_operators.hpp>
29 #include <boost/spirit/include/phoenix1_primitives.hpp>
30 #include <boost/spirit/include/phoenix1_statements.hpp>
31 #include <boost/spirit/include/phoenix1_functions.hpp>
33 #include <boost/wave/cpp_exceptions.hpp>
34 #include <boost/wave/grammars/cpp_literal_grammar_gen.hpp>
36 #if !defined(spirit_append_actor)
37 #define spirit_append_actor(actor) boost::spirit::classic::push_back_a(actor)
38 #define spirit_assign_actor(actor) boost::spirit::classic::assign_a(actor)
39 #endif // !defined(spirit_append_actor)
41 // this must occur after all of the includes and before any code appears
42 #ifdef BOOST_HAS_ABI_HEADERS
43 #include BOOST_ABI_PREFIX
46 ///////////////////////////////////////////////////////////////////////////////
48 // Reusable grammar to parse a C++ style character literal
50 ///////////////////////////////////////////////////////////////////////////////
58 : boost::spirit::classic::closure<chlit_closure, boost::uint32_t, bool>
67 ///////////////////////////////////////////////////////////////////////////////
69 // compose a multibyte character literal
71 ///////////////////////////////////////////////////////////////////////////////
72 struct compose_character_literal {
74 template <typename A1, typename A2, typename A3, typename A4>
81 operator()(boost::uint32_t& value, bool long_lit, bool& overflow,
82 boost::uint32_t character) const
84 // The following assumes that wchar_t is max. 32 Bit
85 BOOST_STATIC_ASSERT(sizeof(wchar_t) <= 4);
87 static boost::uint32_t masks[] = {
88 0x000000ff, 0x0000ffff, 0x00ffffff, 0xffffffff
90 static boost::uint32_t overflow_masks[] = {
91 0xff000000, 0xffff0000, 0xffffff00, 0xffffffff
95 // make sure no overflow will occur below
96 if ((value & overflow_masks[sizeof(wchar_t)-1]) != 0) {
100 // calculate the new value (avoiding a warning regarding
101 // shifting count >= size of the type)
102 value <<= CHAR_BIT * (sizeof(wchar_t)-1);
104 value |= character & masks[sizeof(wchar_t)-1];
108 // make sure no overflow will occur below
109 if ((value & overflow_masks[sizeof(char)-1]) != 0) {
113 // calculate the new value
114 value <<= CHAR_BIT * sizeof(char);
115 value |= character & masks[sizeof(char)-1];
120 phoenix::function<compose_character_literal> const compose;
124 ///////////////////////////////////////////////////////////////////////////////
125 // define, whether the rule's should generate some debug output
126 #define TRACE_CHLIT_GRAMMAR \
127 bool(BOOST_SPIRIT_DEBUG_FLAGS_CPP & BOOST_SPIRIT_DEBUG_FLAGS_CHLIT_GRAMMAR) \
130 struct chlit_grammar :
131 public boost::spirit::classic::grammar<chlit_grammar,
132 closures::chlit_closure::context_t>
137 BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME(*this, "chlit_grammar",
138 TRACE_CHLIT_GRAMMAR);
141 // no need for copy constructor/assignment operator
142 chlit_grammar(chlit_grammar const&);
143 chlit_grammar& operator=(chlit_grammar const&);
145 template <typename ScannerT>
148 typedef boost::spirit::classic::rule<
149 ScannerT, closures::chlit_closure::context_t>
154 definition(chlit_grammar const &self)
156 using namespace boost::spirit::classic;
157 namespace phx = phoenix;
159 // special parsers for '\x..' and L'\x....'
161 unsigned int, 16, 1, 2 * sizeof(char)
162 > hex_char_parser_type;
164 unsigned int, 16, 1, 2 * sizeof(wchar_t)
165 > hex_wchar_parser_type;
167 // the rule for a character literal
169 = eps_p[self.value = phx::val(0), self.long_lit = phx::val(false)]
170 >> !ch_p('L')[self.long_lit = phx::val(true)]
174 >> ( ch_p('a') // BEL
176 impl::compose(self.value, self.long_lit,
177 phx::var(self.overflow), phx::val(0x07))
181 impl::compose(self.value, self.long_lit,
182 phx::var(self.overflow), phx::val(0x08))
186 impl::compose(self.value, self.long_lit,
187 phx::var(self.overflow), phx::val(0x09))
191 impl::compose(self.value, self.long_lit,
192 phx::var(self.overflow), phx::val(0x0a))
196 impl::compose(self.value, self.long_lit,
197 phx::var(self.overflow), phx::val(0x0b))
201 impl::compose(self.value, self.long_lit,
202 phx::var(self.overflow), phx::val(0x0c))
206 impl::compose(self.value, self.long_lit,
207 phx::var(self.overflow), phx::val(0x0d))
211 impl::compose(self.value, self.long_lit,
212 phx::var(self.overflow), phx::val('?'))
216 impl::compose(self.value, self.long_lit,
217 phx::var(self.overflow), phx::val('\''))
221 impl::compose(self.value, self.long_lit,
222 phx::var(self.overflow), phx::val('\"'))
226 impl::compose(self.value, self.long_lit,
227 phx::var(self.overflow), phx::val('\\'))
230 >> if_p(self.long_lit)
232 hex_wchar_parser_type()
234 impl::compose(self.value, self.long_lit,
235 phx::var(self.overflow), phx::arg1)
240 hex_char_parser_type()
242 impl::compose(self.value, self.long_lit,
243 phx::var(self.overflow), phx::arg1)
247 >> uint_parser<unsigned int, 16, 4, 4>()
249 impl::compose(self.value, self.long_lit,
250 phx::var(self.overflow), phx::arg1)
253 >> uint_parser<unsigned int, 16, 8, 8>()
255 impl::compose(self.value, self.long_lit,
256 phx::var(self.overflow), phx::arg1)
258 | uint_parser<unsigned int, 8, 1, 3>()
260 impl::compose(self.value, self.long_lit,
261 phx::var(self.overflow), phx::arg1)
265 | ~eps_p(ch_p('\'')) >> anychar_p
267 impl::compose(self.value, self.long_lit,
268 phx::var(self.overflow), phx::arg1)
274 BOOST_SPIRIT_DEBUG_TRACE_RULE(ch_lit, TRACE_CHLIT_GRAMMAR);
277 // start rule of this grammar
278 rule_t const& start() const
282 // flag signaling integer overflow during value composition
283 mutable bool overflow;
286 #undef TRACE_CHLIT_GRAMMAR
288 ///////////////////////////////////////////////////////////////////////////////
290 // The following function is defined here, to allow the separation of
291 // the compilation of the intlit_grammap from the function using it.
293 ///////////////////////////////////////////////////////////////////////////////
295 #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
296 #define BOOST_WAVE_CHLITGRAMMAR_GEN_INLINE
298 #define BOOST_WAVE_CHLITGRAMMAR_GEN_INLINE inline
301 template <typename IntegralResult, typename TokenT>
302 BOOST_WAVE_CHLITGRAMMAR_GEN_INLINE
304 chlit_grammar_gen<IntegralResult, TokenT>::evaluate(TokenT const &token, value_error &status)
306 using namespace boost::spirit::classic;
309 IntegralResult result = 0;
310 typename TokenT::string_type const &token_val = token.get_value();
311 parse_info<typename TokenT::string_type::const_iterator> hit =
312 parse(token_val.begin(), token_val.end(), g[spirit_assign_actor(result)]);
315 BOOST_WAVE_THROW(preprocess_exception, ill_formed_character_literal,
316 token_val.c_str(), token.get_position());
320 if ('L' == token_val[0]) {
321 // recognized wide character
323 result > (IntegralResult)(std::numeric_limits<wchar_t>::max)())
326 status = error_character_overflow;
330 // recognized narrow ('normal') character
332 result > (IntegralResult)(std::numeric_limits<unsigned char>::max)())
335 status = error_character_overflow;
342 #undef BOOST_WAVE_CHLITGRAMMAR_GEN_INLINE
344 ///////////////////////////////////////////////////////////////////////////////
345 } // namespace grammars
349 // the suffix header occurs after all of the code
350 #ifdef BOOST_HAS_ABI_HEADERS
351 #include BOOST_ABI_SUFFIX
354 #endif // !defined(CPP_CHLIT_GRAMMAR_HPP_9527D349_6592_449A_A409_42A001E6C64C_INCLUDED)