source: NonGTP/Boost/boost/wave/grammars/cpp_expression_grammar.hpp @ 857

Revision 857, 28.8 KB checked in by igarcia, 19 years ago (diff)
Line 
1/*=============================================================================
2    Boost.Wave: A Standard compliant C++ preprocessor library
3
4    http://www.boost.org/
5
6    Copyright (c) 2001-2005 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_EXPRESSION_GRAMMAR_HPP_099CD1A4_A6C0_44BE_8F24_0B00F5BE5674_INCLUDED)
12#define CPP_EXPRESSION_GRAMMAR_HPP_099CD1A4_A6C0_44BE_8F24_0B00F5BE5674_INCLUDED
13
14#include <boost/assert.hpp>
15#include <boost/spirit/core.hpp>
16#include <boost/spirit/attribute/closure.hpp>
17#include <boost/spirit/dynamic/if.hpp>
18#if SPIRIT_VERSION >= 0x1700
19#include <boost/spirit/actor/assign_actor.hpp>
20#include <boost/spirit/actor/push_back_actor.hpp>
21#endif // SPIRIT_VERSION >= 0x1700
22
23#include <boost/spirit/phoenix/functions.hpp>
24#include <boost/spirit/phoenix/operators.hpp>
25#include <boost/spirit/phoenix/primitives.hpp>
26#include <boost/spirit/phoenix/statements.hpp>
27#include <boost/spirit/phoenix/casts.hpp>
28
29#include <boost/wave/wave_config.hpp>
30#include <boost/wave/token_ids.hpp>
31
32#include <boost/wave/cpp_exceptions.hpp>
33#include <boost/wave/grammars/cpp_expression_grammar_gen.hpp>   
34#include <boost/wave/grammars/cpp_literal_grammar_gen.hpp> 
35#include <boost/wave/grammars/cpp_expression_value.hpp>
36#include <boost/wave/util/pattern_parser.hpp>
37#include <boost/wave/util/macro_helpers.hpp>
38
39#if !defined(spirit_append_actor)
40#if SPIRIT_VERSION >= 0x1700
41#define spirit_append_actor(actor) boost::spirit::push_back_a(actor)
42#define spirit_assign_actor(actor) boost::spirit::assign_a(actor)
43#else
44#define spirit_append_actor(actor) boost::spirit::append(actor)
45#define spirit_assign_actor(actor) boost::spirit::assign(actor)
46#endif // SPIRIT_VERSION >= 0x1700
47#endif // !defined(spirit_append_actor)
48
49///////////////////////////////////////////////////////////////////////////////
50//
51//  Encapsulation of the grammar for evaluation of constant preprocessor
52//  expressions
53//
54///////////////////////////////////////////////////////////////////////////////
55namespace boost {
56namespace wave {
57namespace grammars {
58namespace closures {
59
60///////////////////////////////////////////////////////////////////////////////
61//
62//  define the closure type used throughout the C++ expression grammar
63//
64//      Throughout this grammar all literal tokens are stored into a
65//      closure_value variables, which converts the types appropriately, where
66//      required.
67//
68///////////////////////////////////////////////////////////////////////////////
69    struct cpp_expr_closure
70    :   boost::spirit::closure<cpp_expr_closure, closure_value>
71    {
72        member1 val;
73    };
74
75}   // namespace closures
76
77namespace impl {
78
79///////////////////////////////////////////////////////////////////////////////
80//
81//  convert the given tokenvalue (integer literal) to a unsigned long
82//
83///////////////////////////////////////////////////////////////////////////////
84    struct convert_intlit {
85
86        template <typename ArgT>
87        struct result {
88       
89            typedef boost::wave::grammars::closures::closure_value type;
90        };
91
92        template <typename TokenT>
93        boost::wave::grammars::closures::closure_value
94        operator()(TokenT const &token) const
95        {
96            typedef boost::wave::grammars::closures::closure_value return_t;
97            bool is_unsigned = false;
98            unsigned long ul = intlit_grammar_gen<TokenT>::evaluate(token,
99                is_unsigned);
100
101            return is_unsigned ? return_t(ul) : return_t(static_cast<long>(ul));
102        }
103    };
104    phoenix::function<convert_intlit> const as_intlit;
105
106///////////////////////////////////////////////////////////////////////////////
107//
108//  convert the given tokenvalue (character literal) to a unsigned int
109//
110///////////////////////////////////////////////////////////////////////////////
111    struct convert_chlit {
112
113        template <typename ArgT>
114        struct result {
115       
116            typedef boost::wave::grammars::closures::closure_value type;
117        };
118
119        template <typename TokenT>
120        boost::wave::grammars::closures::closure_value
121        operator()(TokenT const &token) const
122        {
123            typedef boost::wave::grammars::closures::closure_value return_t;
124            return return_t(chlit_grammar_gen<TokenT>::evaluate(token));
125        }
126    };
127    phoenix::function<convert_chlit> const as_chlit;
128
129////////////////////////////////////////////////////////////////////////////////
130//
131//  Handle the ?: operator with correct type propagation
132//
133////////////////////////////////////////////////////////////////////////////////
134    struct operator_questionmark {
135   
136        template <typename CondT, typename Arg1T, typename Arg2T>
137        struct result {
138       
139            typedef boost::wave::grammars::closures::closure_value type;
140        };
141
142        template <typename CondT, typename Arg1T, typename Arg2T>
143        boost::wave::grammars::closures::closure_value
144        operator()(CondT const &cond, Arg1T &val1, Arg2T const &val2) const
145        {
146            typedef boost::wave::grammars::closures::closure_value return_t;
147            return return_t(val1.handle_questionmark(cond, val2));
148        }
149    };
150    phoenix::function<operator_questionmark> const questionmark;
151   
152}   // namespace impl
153
154///////////////////////////////////////////////////////////////////////////////
155//  define, whether the rule's should generate some debug output
156#define TRACE_CPP_EXPR_GRAMMAR \
157    bool(BOOST_SPIRIT_DEBUG_FLAGS_CPP & BOOST_SPIRIT_DEBUG_FLAGS_CPP_EXPR_GRAMMAR) \
158    /**/
159
160struct expression_grammar :
161    public boost::spirit::grammar<
162        expression_grammar,
163        closures::cpp_expr_closure::context_t
164    >
165{
166    expression_grammar()
167    {
168        BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME(*this, "expression_grammar",
169            TRACE_CPP_EXPR_GRAMMAR);
170    }
171   
172    template <typename ScannerT>
173    struct definition
174    {
175        typedef closures::cpp_expr_closure closure_type;
176        typedef boost::spirit::rule<ScannerT, closure_type::context_t> rule_t;
177        typedef boost::spirit::rule<ScannerT> simple_rule_t;
178
179        simple_rule_t pp_expression;
180       
181        rule_t const_exp;
182        rule_t logical_or_exp, logical_and_exp;
183        rule_t inclusive_or_exp, exclusive_or_exp, and_exp;
184        rule_t cmp_equality, cmp_relational;
185        rule_t shift_exp;
186        rule_t add_exp, multiply_exp;
187        rule_t unary_exp, primary_exp, constant;
188
189        rule_t const_exp_nocalc;
190        rule_t logical_or_exp_nocalc, logical_and_exp_nocalc;
191        rule_t inclusive_or_exp_nocalc, exclusive_or_exp_nocalc, and_exp_nocalc;
192        rule_t cmp_equality_nocalc, cmp_relational_nocalc;
193        rule_t shift_exp_nocalc;
194        rule_t add_exp_nocalc, multiply_exp_nocalc;
195        rule_t unary_exp_nocalc, primary_exp_nocalc, constant_nocalc;
196
197        boost::spirit::subrule<0, closure_type::context_t> const_exp_subrule;
198
199        definition(expression_grammar const &self)
200        {
201            using namespace boost::spirit;
202            using namespace phoenix;
203            using namespace boost::wave;
204            using boost::wave::util::pattern_p;
205           
206            pp_expression
207                =   const_exp[self.val = arg1]
208                ;
209               
210            const_exp
211                =   logical_or_exp[const_exp.val = arg1]
212                    >> !(const_exp_subrule =
213                            ch_p(T_QUESTION_MARK)
214                            >>  const_exp
215                                [
216                                    const_exp_subrule.val = arg1
217                                ]
218                            >>  ch_p(T_COLON)
219                            >>  const_exp
220                                [
221                                    const_exp_subrule.val =
222                                        impl::questionmark(const_exp.val,
223                                            const_exp_subrule.val, arg1)
224                                ]
225                        )[const_exp.val = arg1]
226                ;
227
228            logical_or_exp
229                =   logical_and_exp[logical_or_exp.val = arg1]
230                    >> *(   if_p(static_cast_<bool>(logical_or_exp.val))
231                            [
232                                // if one of the || operators is true, no more
233                                // evaluation is required
234                                pattern_p(T_OROR, MainTokenMask)
235                                >>  logical_and_exp_nocalc
236                                    [
237                                        logical_or_exp.val =
238                                            static_cast_<bool>(logical_or_exp.val)
239                                    ]
240                            ]
241                            .else_p
242                            [
243                                pattern_p(T_OROR, MainTokenMask)
244                                >>  logical_and_exp
245                                    [
246                                        logical_or_exp.val =
247                                            logical_or_exp.val || arg1
248                                    ]
249                            ]
250                        )
251                ;
252
253            logical_and_exp
254                =   inclusive_or_exp[logical_and_exp.val = arg1]
255                    >> *(   if_p(static_cast_<bool>(logical_and_exp.val))
256                            [
257                                pattern_p(T_ANDAND, MainTokenMask)
258                                >>  inclusive_or_exp
259                                    [
260                                        logical_and_exp.val =
261                                            logical_and_exp.val && arg1
262                                    ]
263                            ]
264                            .else_p
265                            [
266                                // if one of the && operators is false, no more
267                                // evaluation is required
268                                pattern_p(T_ANDAND, MainTokenMask)
269                                >>  inclusive_or_exp_nocalc
270                                    [
271                                        logical_and_exp.val =
272                                            static_cast_<bool>(logical_and_exp.val)
273                                    ]
274                            ]
275                        )
276                ;
277
278            inclusive_or_exp
279                =   exclusive_or_exp[inclusive_or_exp.val = arg1]
280                    >> *(   pattern_p(T_OR, MainTokenMask)
281                            >>  exclusive_or_exp
282                                [
283                                    inclusive_or_exp.val =
284                                          static_cast_<unsigned int>(inclusive_or_exp.val)
285                                      |   static_cast_<unsigned int>(arg1)
286                                ]
287                        )
288                ;
289
290            exclusive_or_exp
291                =   and_exp[exclusive_or_exp.val = arg1]
292                    >> *(   pattern_p(T_XOR, MainTokenMask)
293                            >>  and_exp
294                                [
295                                    exclusive_or_exp.val =
296                                          static_cast_<unsigned int>(exclusive_or_exp.val)
297                                      ^   static_cast_<unsigned int>(arg1)
298                                ]
299                        )
300                ;
301
302            and_exp
303                =   cmp_equality[and_exp.val = arg1]
304                    >> *(   pattern_p(T_AND, MainTokenMask)
305                            >>  cmp_equality
306                                [
307                                    and_exp.val =
308                                          static_cast_<unsigned int>(and_exp.val)
309                                      &   static_cast_<unsigned int>(arg1)
310                                ]
311                        )
312                ;
313
314            cmp_equality
315                =   cmp_relational[cmp_equality.val = arg1]
316                    >> *(   ch_p(T_EQUAL)
317                            >>  cmp_relational
318                                [
319                                    cmp_equality.val =
320                                        cmp_equality.val == arg1
321                                ]
322                        |   pattern_p(T_NOTEQUAL, MainTokenMask)
323                            >>  cmp_relational
324                                [
325                                    cmp_equality.val =
326                                        cmp_equality.val != arg1
327                                ]
328                        )
329                ;
330
331            cmp_relational
332                =   shift_exp[cmp_relational.val = arg1]
333                    >> *(   ch_p(T_LESSEQUAL)
334                            >>  shift_exp
335                                [
336                                    cmp_relational.val =
337                                        cmp_relational.val <= arg1
338                                ]
339                        |   ch_p(T_GREATEREQUAL)
340                            >>  shift_exp
341                                [
342                                    cmp_relational.val =
343                                        cmp_relational.val >= arg1
344                                ]
345                        |   ch_p(T_LESS)
346                            >>  shift_exp
347                                [
348                                    cmp_relational.val =
349                                        cmp_relational.val < arg1
350                                ]
351                        |   ch_p(T_GREATER)
352                            >>  shift_exp
353                                [
354                                    cmp_relational.val =
355                                        cmp_relational.val > arg1
356                                ]
357                        )
358                ;
359
360            shift_exp
361                =   add_exp[shift_exp.val = arg1]
362                    >> *(   ch_p(T_SHIFTLEFT)
363                            >>  add_exp
364                                [
365                                    shift_exp.val <<= arg1
366                                ]
367                        |   ch_p(T_SHIFTRIGHT)
368                            >>  add_exp
369                                [
370                                    shift_exp.val >>= arg1
371                                ]
372                        )
373                ;
374
375            add_exp
376                =   multiply_exp[add_exp.val = arg1]
377                    >> *(   ch_p(T_PLUS)
378                            >>  multiply_exp
379                                [
380                                    add_exp.val += arg1
381                                ]
382                        |   ch_p(T_MINUS)
383                            >>  multiply_exp
384                                [
385                                    add_exp.val -= arg1
386                                ]
387                        )
388                ;
389
390            multiply_exp
391                =   unary_exp[multiply_exp.val = arg1]
392                    >> *(   ch_p(T_STAR)
393                            >>  unary_exp
394                                [
395                                    multiply_exp.val *= arg1
396                                ]
397                        |   ch_p(T_DIVIDE)
398                            >>  unary_exp
399                                [
400                                    multiply_exp.val /= arg1
401                                ]
402                        |   ch_p(T_PERCENT)
403                            >>  unary_exp
404                                [
405                                    multiply_exp.val %= arg1
406                                ]
407                        )
408                ;
409
410            unary_exp
411                =   primary_exp[unary_exp.val = arg1]
412                |   ch_p(T_PLUS) >> unary_exp
413                    [
414                        unary_exp.val = arg1
415                    ]
416                |   ch_p(T_MINUS) >> unary_exp
417                    [
418                        unary_exp.val = -arg1
419                    ]
420                |   pattern_p(T_COMPL, MainTokenMask) >> unary_exp
421                    [
422                        unary_exp.val = ~arg1
423                    ]
424                |   pattern_p(T_NOT, MainTokenMask) >> unary_exp
425                    [
426                        unary_exp.val = !arg1
427                    ]
428                ;
429
430            primary_exp
431                =   constant[primary_exp.val = arg1]
432                |   ch_p(T_LEFTPAREN)
433                    >> const_exp[primary_exp.val = arg1]
434                    >> ch_p(T_RIGHTPAREN)
435                ;
436
437            constant
438                =   ch_p(T_INTLIT)
439                    [
440                        constant.val = impl::as_intlit(arg1)
441                    ]
442                |   ch_p(T_CHARLIT)
443                    [
444                        constant.val = impl::as_chlit(arg1)
445                    ]
446                ;
447             
448            //  here follows the same grammar, but without any embedded
449            //  calculations
450            const_exp_nocalc
451                =   logical_or_exp_nocalc
452                    >> !(   ch_p(T_QUESTION_MARK)
453                            >>  const_exp_nocalc
454                            >>  ch_p(T_COLON)
455                            >>  const_exp_nocalc
456                        )
457                ;
458
459            logical_or_exp_nocalc
460                =   logical_and_exp_nocalc
461                    >> *(   pattern_p(T_OROR, MainTokenMask)
462                            >>  logical_and_exp_nocalc
463                        )
464                ;
465
466            logical_and_exp_nocalc
467                =   inclusive_or_exp_nocalc
468                    >> *(   pattern_p(T_ANDAND, MainTokenMask)
469                            >>  inclusive_or_exp_nocalc
470                        )
471                ;
472
473            inclusive_or_exp_nocalc
474                =   exclusive_or_exp_nocalc
475                    >> *(   pattern_p(T_OR, MainTokenMask)
476                            >>  exclusive_or_exp_nocalc
477                        )
478                ;
479
480            exclusive_or_exp_nocalc
481                =   and_exp_nocalc
482                    >> *(   pattern_p(T_XOR, MainTokenMask)
483                            >>  and_exp_nocalc
484                        )
485                ;
486
487            and_exp_nocalc
488                =   cmp_equality_nocalc
489                    >> *(   pattern_p(T_AND, MainTokenMask)
490                            >>  cmp_equality_nocalc
491                        )
492                ;
493
494            cmp_equality_nocalc
495                =   cmp_relational_nocalc
496                    >> *(   ch_p(T_EQUAL)
497                            >>  cmp_relational_nocalc
498                        |   pattern_p(T_NOTEQUAL, MainTokenMask)
499                            >>  cmp_relational_nocalc
500                        )
501                ;
502
503            cmp_relational_nocalc
504                =   shift_exp_nocalc
505                    >> *(   ch_p(T_LESSEQUAL)
506                            >>  shift_exp_nocalc
507                        |   ch_p(T_GREATEREQUAL)
508                            >>  shift_exp_nocalc
509                        |   ch_p(T_LESS)
510                            >>  shift_exp_nocalc
511                        |   ch_p(T_GREATER)
512                            >>  shift_exp_nocalc
513                        )
514                ;
515
516            shift_exp_nocalc
517                =   add_exp_nocalc
518                    >> *(   ch_p(T_SHIFTLEFT)
519                            >>  add_exp_nocalc
520                        |   ch_p(T_SHIFTRIGHT)
521                            >>  add_exp_nocalc
522                        )
523                ;
524
525            add_exp_nocalc
526                =   multiply_exp_nocalc
527                    >> *(   ch_p(T_PLUS)
528                            >>  multiply_exp_nocalc
529                        |   ch_p(T_MINUS)
530                            >>  multiply_exp_nocalc
531                        )
532                ;
533
534            multiply_exp_nocalc
535                =   unary_exp_nocalc
536                    >> *(   ch_p(T_STAR)
537                            >>  unary_exp_nocalc
538                        |   ch_p(T_DIVIDE)
539                            >>  unary_exp_nocalc
540                        |   ch_p(T_PERCENT)
541                            >>  unary_exp_nocalc
542                        )
543                ;
544
545            unary_exp_nocalc
546                =   primary_exp_nocalc
547                |   ch_p(T_PLUS) >> unary_exp_nocalc
548                |   ch_p(T_MINUS) >> unary_exp_nocalc
549                |   pattern_p(T_COMPL, MainTokenMask) >> unary_exp_nocalc
550                |   pattern_p(T_NOT, MainTokenMask) >> unary_exp_nocalc
551                ;
552
553            primary_exp_nocalc
554                =   constant_nocalc
555                |   ch_p(T_LEFTPAREN)
556                    >> const_exp_nocalc
557                    >> ch_p(T_RIGHTPAREN)
558                ;
559
560            constant_nocalc
561                =   ch_p(T_INTLIT)
562                |   ch_p(T_CHARLIT)
563                ;
564
565            BOOST_SPIRIT_DEBUG_TRACE_RULE(pp_expression, TRACE_CPP_EXPR_GRAMMAR);
566            BOOST_SPIRIT_DEBUG_TRACE_RULE(const_exp, TRACE_CPP_EXPR_GRAMMAR);
567            BOOST_SPIRIT_DEBUG_TRACE_RULE(logical_or_exp, TRACE_CPP_EXPR_GRAMMAR);
568            BOOST_SPIRIT_DEBUG_TRACE_RULE(logical_and_exp, TRACE_CPP_EXPR_GRAMMAR);
569            BOOST_SPIRIT_DEBUG_TRACE_RULE(inclusive_or_exp, TRACE_CPP_EXPR_GRAMMAR);
570            BOOST_SPIRIT_DEBUG_TRACE_RULE(exclusive_or_exp, TRACE_CPP_EXPR_GRAMMAR);
571            BOOST_SPIRIT_DEBUG_TRACE_RULE(and_exp, TRACE_CPP_EXPR_GRAMMAR);
572            BOOST_SPIRIT_DEBUG_TRACE_RULE(cmp_equality, TRACE_CPP_EXPR_GRAMMAR);
573            BOOST_SPIRIT_DEBUG_TRACE_RULE(cmp_relational, TRACE_CPP_EXPR_GRAMMAR);
574            BOOST_SPIRIT_DEBUG_TRACE_RULE(shift_exp, TRACE_CPP_EXPR_GRAMMAR);
575            BOOST_SPIRIT_DEBUG_TRACE_RULE(add_exp, TRACE_CPP_EXPR_GRAMMAR);
576            BOOST_SPIRIT_DEBUG_TRACE_RULE(multiply_exp, TRACE_CPP_EXPR_GRAMMAR);
577            BOOST_SPIRIT_DEBUG_TRACE_RULE(unary_exp, TRACE_CPP_EXPR_GRAMMAR);
578            BOOST_SPIRIT_DEBUG_TRACE_RULE(primary_exp, TRACE_CPP_EXPR_GRAMMAR);
579            BOOST_SPIRIT_DEBUG_TRACE_RULE(constant, TRACE_CPP_EXPR_GRAMMAR);
580            BOOST_SPIRIT_DEBUG_TRACE_RULE(const_exp_subrule, TRACE_CPP_EXPR_GRAMMAR);
581
582            BOOST_SPIRIT_DEBUG_TRACE_RULE(const_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
583            BOOST_SPIRIT_DEBUG_TRACE_RULE(logical_or_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
584            BOOST_SPIRIT_DEBUG_TRACE_RULE(logical_and_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
585            BOOST_SPIRIT_DEBUG_TRACE_RULE(inclusive_or_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
586            BOOST_SPIRIT_DEBUG_TRACE_RULE(exclusive_or_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
587            BOOST_SPIRIT_DEBUG_TRACE_RULE(and_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
588            BOOST_SPIRIT_DEBUG_TRACE_RULE(cmp_equality_nocalc, TRACE_CPP_EXPR_GRAMMAR);
589            BOOST_SPIRIT_DEBUG_TRACE_RULE(cmp_relational_nocalc, TRACE_CPP_EXPR_GRAMMAR);
590            BOOST_SPIRIT_DEBUG_TRACE_RULE(shift_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
591            BOOST_SPIRIT_DEBUG_TRACE_RULE(add_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
592            BOOST_SPIRIT_DEBUG_TRACE_RULE(multiply_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
593            BOOST_SPIRIT_DEBUG_TRACE_RULE(unary_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
594            BOOST_SPIRIT_DEBUG_TRACE_RULE(primary_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
595            BOOST_SPIRIT_DEBUG_TRACE_RULE(constant_nocalc, TRACE_CPP_EXPR_GRAMMAR);
596        }
597
598    // start rule of this grammar
599        simple_rule_t const& start() const
600        { return pp_expression; }
601    };
602};
603
604///////////////////////////////////////////////////////////////////////////////
605#undef TRACE_CPP_EXPR_GRAMMAR
606
607///////////////////////////////////////////////////////////////////////////////
608// 
609//  The following function is defined here, to allow the separation of
610//  the compilation of the expression_grammar from the function using it.
611// 
612///////////////////////////////////////////////////////////////////////////////
613
614#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
615#define BOOST_WAVE_EXPRGRAMMAR_GEN_INLINE
616#else
617#define BOOST_WAVE_EXPRGRAMMAR_GEN_INLINE inline
618#endif
619
620template <typename TokenT>
621BOOST_WAVE_EXPRGRAMMAR_GEN_INLINE
622bool
623expression_grammar_gen<TokenT>::evaluate(
624    typename token_sequence_type::const_iterator const &first,
625    typename token_sequence_type::const_iterator const &last,
626    typename token_type::position_type const &act_pos,
627    bool if_block_status)
628{
629    using namespace boost::spirit;
630    using namespace boost::wave;
631    using namespace boost::wave::grammars::closures;
632   
633    using boost::wave::util::impl::as_string;
634   
635    typedef typename token_sequence_type::const_iterator iterator_type;
636    typedef typename token_sequence_type::value_type::string_type string_type;
637
638    parse_info<iterator_type> hit(first);
639    closure_value result;             // expression result
640   
641    try {
642        expression_grammar g;             // expression grammar
643        hit = parse (first, last, g[spirit_assign_actor(result)],
644                     ch_p(T_SPACE) | ch_p(T_CCOMMENT) | ch_p(T_CPPCOMMENT));
645
646        if (!hit.hit) {
647        // expression is illformed
648            if (if_block_status) {
649                string_type expression = as_string<string_type>(first, last);
650                if (0 == expression.size())
651                    expression = "empty expression";
652                BOOST_WAVE_THROW(preprocess_exception, ill_formed_expression,
653                    expression.c_str(), act_pos);
654            }
655            else {
656            //  as the if_block_status is false no errors will be reported
657                return false;
658            }
659        }
660    }
661    catch (wave::preprocess_exception const& e) {
662    // expression is illformed
663        if (if_block_status) {
664            throw e;
665        }
666        else {
667        //  as the if_block_status is false no errors will be reported
668            return false;
669        }
670    }
671       
672    if (!hit.full) {
673    // The token list starts with a valid expression, but there remains
674    // something. If the remainder consists out of whitespace only, the
675    // expression is still valid.
676    iterator_type next = hit.stop;
677   
678        while (next != last) {
679            switch (static_cast<unsigned int>(token_id(*next))) {
680            case T_SPACE:
681            case T_SPACE2:
682            case T_CCOMMENT:
683                break;                      // ok continue
684               
685            case T_NEWLINE:
686            case T_EOF:
687            case T_CPPCOMMENT:              // contains newline
688                return bool(result);        // expression is valid
689               
690            default:
691            // expression is illformed
692                if (if_block_status) {
693                    string_type expression = as_string<string_type>(first, last);
694                    if (0 == expression.size())
695                        expression = "empty expression";
696                    BOOST_WAVE_THROW(preprocess_exception, ill_formed_expression,
697                        expression.c_str(), act_pos);
698                }
699                else {
700                //  as the if_block_status is false no errors will be reported
701                    return false;
702                }
703            }
704            ++next;
705        }
706    }
707
708    if (closure_value::error_noerror != result.is_valid()) {
709    // division by zero occured
710        string_type expression = as_string<string_type>(first, last);
711        if (0 == expression.size())
712            expression = "empty expression";
713           
714        if (closure_value::error_division_by_zero == result.is_valid()) {
715            BOOST_WAVE_THROW(preprocess_exception, division_by_zero,
716                expression.c_str(), act_pos);
717        }
718        else if (closure_value::error_overflow == result.is_valid()) {
719            BOOST_WAVE_THROW(preprocess_exception, integer_overflow,
720                expression.c_str(), act_pos);
721        }
722    }
723   
724// token sequence is a valid expression
725    return bool(result);
726}
727
728#undef BOOST_WAVE_EXPRGRAMMAR_GEN_INLINE
729
730///////////////////////////////////////////////////////////////////////////////
731}   // namespace grammars
732}   // namespace wave
733}   // namespace boost
734
735#endif // !defined(CPP_EXPRESSION_GRAMMAR_HPP_099CD1A4_A6C0_44BE_8F24_0B00F5BE5674_INCLUDED)
Note: See TracBrowser for help on using the repository browser.