Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/wave/grammars/cpp_chlit_grammar.hpp @ 33

Last change on this file since 33 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

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