• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(BOOST_CPP_CHLIT_GRAMMAR_HPP_9527D349_6592_449A_A409_42A001E6C64C_INCLUDED)
12 #define BOOST_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
operator ()boost::wave::grammars::impl::compose_character_literal81         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 {
chlit_grammarboost::wave::grammars::chlit_grammar134     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 
definitionboost::wave::grammars::chlit_grammar::definition154         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
startboost::wave::grammars::chlit_grammar::definition278         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
evaluate(TokenT const & token,value_error & status)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(BOOST_CPP_CHLIT_GRAMMAR_HPP_9527D349_6592_449A_A409_42A001E6C64C_INCLUDED)
355