Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/wave/grammars/cpp_chlit_grammar.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
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) |