]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/wave/include/boost/wave/grammars/cpp_chlit_grammar.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / wave / include / boost / wave / grammars / cpp_chlit_grammar.hpp
1 /*=============================================================================
2 Boost.Wave: A Standard compliant C++ preprocessor library
3
4 http://www.boost.org/
5
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 =============================================================================*/
10
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
13
14 #include <limits> // std::numeric_limits
15 #include <climits> // CHAR_BIT
16
17 #include <boost/wave/wave_config.hpp>
18
19 #include <boost/static_assert.hpp>
20 #include <boost/cstdint.hpp>
21
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>
27
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>
32
33 #include <boost/wave/cpp_exceptions.hpp>
34 #include <boost/wave/grammars/cpp_literal_grammar_gen.hpp>
35
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)
40
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
44 #endif
45
46 ///////////////////////////////////////////////////////////////////////////////
47 //
48 // Reusable grammar to parse a C++ style character literal
49 //
50 ///////////////////////////////////////////////////////////////////////////////
51 namespace boost {
52 namespace wave {
53 namespace grammars {
54
55 namespace closures {
56
57 struct chlit_closure
58 : boost::spirit::classic::closure<chlit_closure, boost::uint32_t, bool>
59 {
60 member1 value;
61 member2 long_lit;
62 };
63 }
64
65 namespace impl {
66
67 ///////////////////////////////////////////////////////////////////////////////
68 //
69 // compose a multibyte character literal
70 //
71 ///////////////////////////////////////////////////////////////////////////////
72 struct compose_character_literal {
73
74 template <typename A1, typename A2, typename A3, typename A4>
75 struct result
76 {
77 typedef void type;
78 };
79
80 void
81 operator()(boost::uint32_t& value, bool long_lit, bool& overflow,
82 boost::uint32_t character) const
83 {
84 // The following assumes that wchar_t is max. 32 Bit
85 BOOST_STATIC_ASSERT(sizeof(wchar_t) <= 4);
86
87 static boost::uint32_t masks[] = {
88 0x000000ff, 0x0000ffff, 0x00ffffff, 0xffffffff
89 };
90 static boost::uint32_t overflow_masks[] = {
91 0xff000000, 0xffff0000, 0xffffff00, 0xffffffff
92 };
93
94 if (long_lit) {
95 // make sure no overflow will occur below
96 if ((value & overflow_masks[sizeof(wchar_t)-1]) != 0) {
97 overflow |= true;
98 }
99 else {
100 // calculate the new value (avoiding a warning regarding
101 // shifting count >= size of the type)
102 value <<= CHAR_BIT * (sizeof(wchar_t)-1);
103 value <<= CHAR_BIT;
104 value |= character & masks[sizeof(wchar_t)-1];
105 }
106 }
107 else {
108 // make sure no overflow will occur below
109 if ((value & overflow_masks[sizeof(char)-1]) != 0) {
110 overflow |= true;
111 }
112 else {
113 // calculate the new value
114 value <<= CHAR_BIT * sizeof(char);
115 value |= character & masks[sizeof(char)-1];
116 }
117 }
118 }
119 };
120 phoenix::function<compose_character_literal> const compose;
121
122 } // namespace impl
123
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) \
128 /**/
129
130 struct chlit_grammar :
131 public boost::spirit::classic::grammar<chlit_grammar,
132 closures::chlit_closure::context_t>
133 {
134 chlit_grammar()
135 : overflow(false)
136 {
137 BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME(*this, "chlit_grammar",
138 TRACE_CHLIT_GRAMMAR);
139 }
140
141 // no need for copy constructor/assignment operator
142 chlit_grammar(chlit_grammar const&);
143 chlit_grammar& operator=(chlit_grammar const&);
144
145 template <typename ScannerT>
146 struct definition
147 {
148 typedef boost::spirit::classic::rule<
149 ScannerT, closures::chlit_closure::context_t>
150 rule_t;
151
152 rule_t ch_lit;
153
154 definition(chlit_grammar const &self)
155 {
156 using namespace boost::spirit::classic;
157 namespace phx = phoenix;
158
159 // special parsers for '\x..' and L'\x....'
160 typedef uint_parser<
161 unsigned int, 16, 1, 2 * sizeof(char)
162 > hex_char_parser_type;
163 typedef uint_parser<
164 unsigned int, 16, 1, 2 * sizeof(wchar_t)
165 > hex_wchar_parser_type;
166
167 // the rule for a character literal
168 ch_lit
169 = eps_p[self.value = phx::val(0), self.long_lit = phx::val(false)]
170 >> !ch_p('L')[self.long_lit = phx::val(true)]
171 >> ch_p('\'')
172 >> +( (
173 ch_p('\\')
174 >> ( ch_p('a') // BEL
175 [
176 impl::compose(self.value, self.long_lit,
177 phx::var(self.overflow), phx::val(0x07))
178 ]
179 | ch_p('b') // BS
180 [
181 impl::compose(self.value, self.long_lit,
182 phx::var(self.overflow), phx::val(0x08))
183 ]
184 | ch_p('t') // HT
185 [
186 impl::compose(self.value, self.long_lit,
187 phx::var(self.overflow), phx::val(0x09))
188 ]
189 | ch_p('n') // NL
190 [
191 impl::compose(self.value, self.long_lit,
192 phx::var(self.overflow), phx::val(0x0a))
193 ]
194 | ch_p('v') // VT
195 [
196 impl::compose(self.value, self.long_lit,
197 phx::var(self.overflow), phx::val(0x0b))
198 ]
199 | ch_p('f') // FF
200 [
201 impl::compose(self.value, self.long_lit,
202 phx::var(self.overflow), phx::val(0x0c))
203 ]
204 | ch_p('r') // CR
205 [
206 impl::compose(self.value, self.long_lit,
207 phx::var(self.overflow), phx::val(0x0d))
208 ]
209 | ch_p('?')
210 [
211 impl::compose(self.value, self.long_lit,
212 phx::var(self.overflow), phx::val('?'))
213 ]
214 | ch_p('\'')
215 [
216 impl::compose(self.value, self.long_lit,
217 phx::var(self.overflow), phx::val('\''))
218 ]
219 | ch_p('\"')
220 [
221 impl::compose(self.value, self.long_lit,
222 phx::var(self.overflow), phx::val('\"'))
223 ]
224 | ch_p('\\')
225 [
226 impl::compose(self.value, self.long_lit,
227 phx::var(self.overflow), phx::val('\\'))
228 ]
229 | ch_p('x')
230 >> if_p(self.long_lit)
231 [
232 hex_wchar_parser_type()
233 [
234 impl::compose(self.value, self.long_lit,
235 phx::var(self.overflow), phx::arg1)
236 ]
237 ]
238 .else_p
239 [
240 hex_char_parser_type()
241 [
242 impl::compose(self.value, self.long_lit,
243 phx::var(self.overflow), phx::arg1)
244 ]
245 ]
246 | ch_p('u')
247 >> uint_parser<unsigned int, 16, 4, 4>()
248 [
249 impl::compose(self.value, self.long_lit,
250 phx::var(self.overflow), phx::arg1)
251 ]
252 | ch_p('U')
253 >> uint_parser<unsigned int, 16, 8, 8>()
254 [
255 impl::compose(self.value, self.long_lit,
256 phx::var(self.overflow), phx::arg1)
257 ]
258 | uint_parser<unsigned int, 8, 1, 3>()
259 [
260 impl::compose(self.value, self.long_lit,
261 phx::var(self.overflow), phx::arg1)
262 ]
263 )
264 )
265 | ~eps_p(ch_p('\'')) >> anychar_p
266 [
267 impl::compose(self.value, self.long_lit,
268 phx::var(self.overflow), phx::arg1)
269 ]
270 )
271 >> ch_p('\'')
272 ;
273
274 BOOST_SPIRIT_DEBUG_TRACE_RULE(ch_lit, TRACE_CHLIT_GRAMMAR);
275 }
276
277 // start rule of this grammar
278 rule_t const& start() const
279 { return ch_lit; }
280 };
281
282 // flag signaling integer overflow during value composition
283 mutable bool overflow;
284 };
285
286 #undef TRACE_CHLIT_GRAMMAR
287
288 ///////////////////////////////////////////////////////////////////////////////
289 //
290 // The following function is defined here, to allow the separation of
291 // the compilation of the intlit_grammap from the function using it.
292 //
293 ///////////////////////////////////////////////////////////////////////////////
294
295 #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
296 #define BOOST_WAVE_CHLITGRAMMAR_GEN_INLINE
297 #else
298 #define BOOST_WAVE_CHLITGRAMMAR_GEN_INLINE inline
299 #endif
300
301 template <typename IntegralResult, typename TokenT>
302 BOOST_WAVE_CHLITGRAMMAR_GEN_INLINE
303 IntegralResult
304 chlit_grammar_gen<IntegralResult, TokenT>::evaluate(TokenT const &token, value_error &status)
305 {
306 using namespace boost::spirit::classic;
307
308 chlit_grammar g;
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)]);
313
314 if (!hit.hit) {
315 BOOST_WAVE_THROW(preprocess_exception, ill_formed_character_literal,
316 token_val.c_str(), token.get_position());
317 }
318 else {
319 // range check
320 if ('L' == token_val[0]) {
321 // recognized wide character
322 if (g.overflow ||
323 result > (IntegralResult)(std::numeric_limits<wchar_t>::max)())
324 {
325 // out of range
326 status = error_character_overflow;
327 }
328 }
329 else {
330 // recognized narrow ('normal') character
331 if (g.overflow ||
332 result > (IntegralResult)(std::numeric_limits<unsigned char>::max)())
333 {
334 // out of range
335 status = error_character_overflow;
336 }
337 }
338 }
339 return result;
340 }
341
342 #undef BOOST_WAVE_CHLITGRAMMAR_GEN_INLINE
343
344 ///////////////////////////////////////////////////////////////////////////////
345 } // namespace grammars
346 } // namespace wave
347 } // namespace boost
348
349 // the suffix header occurs after all of the code
350 #ifdef BOOST_HAS_ABI_HEADERS
351 #include BOOST_ABI_SUFFIX
352 #endif
353
354 #endif // !defined(CPP_CHLIT_GRAMMAR_HPP_9527D349_6592_449A_A409_42A001E6C64C_INCLUDED)