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_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/wave/wave_config.hpp>
15 
16 #include <boost/assert.hpp>
17 #include <boost/spirit/include/classic_core.hpp>
18 #include <boost/spirit/include/classic_closure.hpp>
19 #include <boost/spirit/include/classic_if.hpp>
20 #include <boost/spirit/include/classic_assign_actor.hpp>
21 #include <boost/spirit/include/classic_push_back_actor.hpp>
22 
23 #include <boost/spirit/include/phoenix1_functions.hpp>
24 #include <boost/spirit/include/phoenix1_operators.hpp>
25 #include <boost/spirit/include/phoenix1_primitives.hpp>
26 #include <boost/spirit/include/phoenix1_statements.hpp>
27 #include <boost/spirit/include/phoenix1_casts.hpp>
28 
29 #include <boost/wave/token_ids.hpp>
30 
31 #include <boost/wave/cpp_exceptions.hpp>
32 #include <boost/wave/grammars/cpp_expression_grammar_gen.hpp>
33 #include <boost/wave/grammars/cpp_literal_grammar_gen.hpp>
34 #include <boost/wave/grammars/cpp_expression_value.hpp>
35 #include <boost/wave/util/pattern_parser.hpp>
36 #include <boost/wave/util/macro_helpers.hpp>
37 
38 #if !defined(spirit_append_actor)
39 #define spirit_append_actor(actor) boost::spirit::classic::push_back_a(actor)
40 #define spirit_assign_actor(actor) boost::spirit::classic::assign_a(actor)
41 #endif // !defined(spirit_append_actor)
42 
43 // this must occur after all of the includes and before any code appears
44 #ifdef BOOST_HAS_ABI_HEADERS
45 #include BOOST_ABI_PREFIX
46 #endif
47 
48 ///////////////////////////////////////////////////////////////////////////////
49 //
50 //  Encapsulation of the grammar for evaluation of constant preprocessor
51 //  expressions
52 //
53 ///////////////////////////////////////////////////////////////////////////////
54 namespace boost {
55 namespace wave {
56 namespace grammars {
57 namespace closures {
58 
59 ///////////////////////////////////////////////////////////////////////////////
60 //
61 //  define the closure type used throughout the C++ expression grammar
62 //
63 //      Throughout this grammar all literal tokens are stored into a
64 //      closure_value variables, which converts the types appropriately, where
65 //      required.
66 //
67 ///////////////////////////////////////////////////////////////////////////////
68     struct cpp_expr_closure
69     :   boost::spirit::classic::closure<cpp_expr_closure, closure_value>
70     {
71         member1 val;
72     };
73 
74 }   // namespace closures
75 
76 namespace impl {
77 
78 ///////////////////////////////////////////////////////////////////////////////
79 //
80 //  convert the given token value (integer literal) to a unsigned long
81 //
82 ///////////////////////////////////////////////////////////////////////////////
83     struct convert_intlit {
84 
85         template <typename ArgT>
86         struct result {
87 
88             typedef boost::wave::grammars::closures::closure_value type;
89         };
90 
91         template <typename TokenT>
92         boost::wave::grammars::closures::closure_value
operator ()boost::wave::grammars::impl::convert_intlit93         operator()(TokenT const &token) const
94         {
95             typedef boost::wave::grammars::closures::closure_value return_type;
96             bool is_unsigned = false;
97             uint_literal_type ul = intlit_grammar_gen<TokenT>::evaluate(token,
98                 is_unsigned);
99 
100             return is_unsigned ?
101                 return_type(ul) : return_type(static_cast<int_literal_type>(ul));
102         }
103     };
104     phoenix::function<convert_intlit> const as_intlit;
105 
106 ///////////////////////////////////////////////////////////////////////////////
107 //
108 //  Convert the given token value (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
operator ()boost::wave::grammars::impl::convert_chlit121         operator()(TokenT const &token) const
122         {
123             typedef boost::wave::grammars::closures::closure_value return_type;
124             value_error status = error_noerror;
125 
126             //  If the literal is a wchar_t and wchar_t is represented by a
127             //  signed integral type, then the created value will be signed as
128             //  well, otherwise we assume unsigned values.
129 #if BOOST_WAVE_WCHAR_T_SIGNEDNESS == BOOST_WAVE_WCHAR_T_AUTOSELECT
130             if ('L' == token.get_value()[0] && std::numeric_limits<wchar_t>::is_signed)
131             {
132                 int value = chlit_grammar_gen<int, TokenT>::evaluate(token, status);
133                 return return_type(value, status);
134             }
135 #elif BOOST_WAVE_WCHAR_T_SIGNEDNESS == BOOST_WAVE_WCHAR_T_FORCE_SIGNED
136             if ('L' == token.get_value()[0])
137             {
138                 int value = chlit_grammar_gen<int, TokenT>::evaluate(token, status);
139                 return return_type(value, status);
140             }
141 #endif
142 
143             unsigned int value = chlit_grammar_gen<unsigned int, TokenT>::evaluate(token, status);
144             return return_type(value, status);
145         }
146     };
147     phoenix::function<convert_chlit> const as_chlit;
148 
149 ////////////////////////////////////////////////////////////////////////////////
150 //
151 //  Handle the ?: operator with correct type and error propagation
152 //
153 ////////////////////////////////////////////////////////////////////////////////
154     struct operator_questionmark {
155 
156         template <typename CondT, typename Arg1T, typename Arg2T>
157         struct result {
158 
159             typedef boost::wave::grammars::closures::closure_value type;
160         };
161 
162         template <typename CondT, typename Arg1T, typename Arg2T>
163         boost::wave::grammars::closures::closure_value
operator ()boost::wave::grammars::impl::operator_questionmark164         operator()(CondT const &cond, Arg1T &val1, Arg2T const &val2) const
165         {
166             return val1.handle_questionmark(cond, val2);
167         }
168     };
169     phoenix::function<operator_questionmark> const questionmark;
170 
171 ///////////////////////////////////////////////////////////////////////////////
172 //
173 //  Handle type conversion conserving error conditions
174 //
175 ///////////////////////////////////////////////////////////////////////////////
176     struct operator_to_bool {
177 
178         template <typename ArgT>
179         struct result {
180 
181             typedef boost::wave::grammars::closures::closure_value type;
182         };
183 
184         template <typename ArgT>
185         boost::wave::grammars::closures::closure_value
operator ()boost::wave::grammars::impl::operator_to_bool186         operator()(ArgT &val) const
187         {
188             typedef boost::wave::grammars::closures::closure_value return_type;
189             return return_type(
190                 boost::wave::grammars::closures::as_bool(val), val.is_valid());
191         }
192     };
193     phoenix::function<operator_to_bool> const to_bool;
194 
195 ///////////////////////////////////////////////////////////////////////////////
196 //
197 //  Handle explicit type conversion
198 //
199 ///////////////////////////////////////////////////////////////////////////////
200     struct operator_as_bool {
201 
202         template <typename ArgT>
203         struct result {
204 
205             typedef bool type;
206         };
207 
208         template <typename ArgT>
209         bool
operator ()boost::wave::grammars::impl::operator_as_bool210         operator()(ArgT &val) const
211         {
212             return boost::wave::grammars::closures::as_bool(val);
213         }
214     };
215     phoenix::function<operator_as_bool> const as_bool;
216 
217 ///////////////////////////////////////////////////////////////////////////////
218 //
219 //  Handle closure value operators with proper error propagation
220 //
221 ///////////////////////////////////////////////////////////////////////////////
222 #define BOOST_WAVE_BINARYOP(op, optok)                                        \
223     struct operator_binary_ ## op {                                           \
224                                                                               \
225         template <typename Arg1T, typename Arg2T>                             \
226         struct result {                                                       \
227                                                                               \
228             typedef boost::wave::grammars::closures::closure_value type;      \
229         };                                                                    \
230                                                                               \
231         template <typename Arg1T, typename Arg2T>                             \
232         boost::wave::grammars::closures::closure_value                        \
233         operator()(Arg1T &val1, Arg2T &val2) const                            \
234         {                                                                     \
235             return val1 optok val2;                                           \
236         }                                                                     \
237     };                                                                        \
238     phoenix::function<operator_binary_ ## op> const binary_ ## op             \
239     /**/
240 
241     BOOST_WAVE_BINARYOP(and, &&);
242     BOOST_WAVE_BINARYOP(or, ||);
243 
244     BOOST_WAVE_BINARYOP(bitand, &);
245     BOOST_WAVE_BINARYOP(bitor, |);
246     BOOST_WAVE_BINARYOP(bitxor, ^);
247 
248     BOOST_WAVE_BINARYOP(lesseq, <=);
249     BOOST_WAVE_BINARYOP(less, <);
250     BOOST_WAVE_BINARYOP(greater, >);
251     BOOST_WAVE_BINARYOP(greateq, >=);
252     BOOST_WAVE_BINARYOP(eq, ==);
253     BOOST_WAVE_BINARYOP(ne, !=);
254 
255 #undef BOOST_WAVE_BINARYOP
256 
257 ///////////////////////////////////////////////////////////////////////////////
258 #define BOOST_WAVE_UNARYOP(op, optok)                                         \
259     struct operator_unary_ ## op {                                            \
260                                                                               \
261         template <typename ArgT>                                              \
262         struct result {                                                       \
263                                                                               \
264             typedef boost::wave::grammars::closures::closure_value type;      \
265         };                                                                    \
266                                                                               \
267         template <typename ArgT>                                              \
268         boost::wave::grammars::closures::closure_value                        \
269         operator()(ArgT &val) const                                           \
270         {                                                                     \
271             return optok val;                                                 \
272         }                                                                     \
273     };                                                                        \
274     phoenix::function<operator_unary_ ## op> const unary_ ## op               \
275     /**/
276 
277     BOOST_WAVE_UNARYOP(neg, !);
278 
279 #undef BOOST_WAVE_UNARYOP
280 
281 }   // namespace impl
282 
283 ///////////////////////////////////////////////////////////////////////////////
284 //  define, whether the rule's should generate some debug output
285 #define TRACE_CPP_EXPR_GRAMMAR \
286     bool(BOOST_SPIRIT_DEBUG_FLAGS_CPP & BOOST_SPIRIT_DEBUG_FLAGS_CPP_EXPR_GRAMMAR) \
287     /**/
288 
289 struct expression_grammar :
290     public boost::spirit::classic::grammar<
291         expression_grammar,
292         closures::cpp_expr_closure::context_t
293     >
294 {
expression_grammarboost::wave::grammars::expression_grammar295     expression_grammar()
296     {
297         BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME(*this, "expression_grammar",
298             TRACE_CPP_EXPR_GRAMMAR);
299     }
300 
301     // no need for copy constructor/assignment operator
302     expression_grammar(expression_grammar const&);
303     expression_grammar& operator= (expression_grammar const&);
304 
305     template <typename ScannerT>
306     struct definition
307     {
308         typedef closures::cpp_expr_closure closure_type;
309         typedef boost::spirit::classic::rule<ScannerT, closure_type::context_t> rule_t;
310         typedef boost::spirit::classic::rule<ScannerT> simple_rule_t;
311 
312         simple_rule_t pp_expression;
313 
314         rule_t const_exp;
315         rule_t logical_or_exp, logical_and_exp;
316         rule_t inclusive_or_exp, exclusive_or_exp, and_exp;
317         rule_t cmp_equality, cmp_relational;
318         rule_t shift_exp;
319         rule_t add_exp, multiply_exp;
320         rule_t unary_exp, primary_exp, constant;
321 
322         rule_t const_exp_nocalc;
323         rule_t logical_or_exp_nocalc, logical_and_exp_nocalc;
324         rule_t inclusive_or_exp_nocalc, exclusive_or_exp_nocalc, and_exp_nocalc;
325         rule_t cmp_equality_nocalc, cmp_relational_nocalc;
326         rule_t shift_exp_nocalc;
327         rule_t add_exp_nocalc, multiply_exp_nocalc;
328         rule_t unary_exp_nocalc, primary_exp_nocalc, constant_nocalc;
329 
330         boost::spirit::classic::subrule<0, closure_type::context_t> const_exp_subrule;
331 
definitionboost::wave::grammars::expression_grammar::definition332         definition(expression_grammar const &self)
333         {
334             using namespace boost::spirit::classic;
335             using namespace phoenix;
336             using namespace boost::wave;
337             using boost::wave::util::pattern_p;
338 
339             pp_expression
340                 =   const_exp[self.val = arg1]
341                 ;
342 
343             const_exp
344                 =   logical_or_exp[const_exp.val = arg1]
345                     >> !(const_exp_subrule =
346                             ch_p(T_QUESTION_MARK)
347                             >>  const_exp
348                                 [
349                                     const_exp_subrule.val = arg1
350                                 ]
351                             >>  ch_p(T_COLON)
352                             >>  const_exp
353                                 [
354                                     const_exp_subrule.val =
355                                         impl::questionmark(const_exp.val,
356                                             const_exp_subrule.val, arg1)
357                                 ]
358                         )[const_exp.val = arg1]
359                 ;
360 
361             logical_or_exp
362                 =   logical_and_exp[logical_or_exp.val = arg1]
363                     >> *(   if_p(impl::as_bool(logical_or_exp.val))
364                             [
365                                 // if one of the || operators is true, no more
366                                 // evaluation is required
367                                 pattern_p(T_OROR, MainTokenMask)
368                                 >>  logical_and_exp_nocalc
369                                     [
370                                         logical_or_exp.val =
371                                             impl::to_bool(logical_or_exp.val)
372                                     ]
373                             ]
374                             .else_p
375                             [
376                                 pattern_p(T_OROR, MainTokenMask)
377                                 >>  logical_and_exp
378                                     [
379                                         logical_or_exp.val =
380                                             impl::binary_or(logical_or_exp.val, arg1)
381                                     ]
382                             ]
383                         )
384                 ;
385 
386             logical_and_exp
387                 =   inclusive_or_exp[logical_and_exp.val = arg1]
388                     >> *(   if_p(impl::as_bool(logical_and_exp.val))
389                             [
390                                 pattern_p(T_ANDAND, MainTokenMask)
391                                 >>  inclusive_or_exp
392                                     [
393                                         logical_and_exp.val =
394                                             impl::binary_and(logical_and_exp.val, arg1)
395                                     ]
396                             ]
397                             .else_p
398                             [
399                                 // if one of the && operators is false, no more
400                                 // evaluation is required
401                                 pattern_p(T_ANDAND, MainTokenMask)
402                                 >>  inclusive_or_exp_nocalc
403                                     [
404                                         logical_and_exp.val =
405                                             impl::to_bool(logical_and_exp.val)
406                                     ]
407                             ]
408                         )
409                 ;
410 
411             inclusive_or_exp
412                 =   exclusive_or_exp[inclusive_or_exp.val = arg1]
413                     >> *(   pattern_p(T_OR, MainTokenMask)
414                             >>  exclusive_or_exp
415                                 [
416                                     inclusive_or_exp.val =
417                                         impl::binary_bitor(inclusive_or_exp.val, arg1)
418                                 ]
419                         )
420                 ;
421 
422             exclusive_or_exp
423                 =   and_exp[exclusive_or_exp.val = arg1]
424                     >> *(   pattern_p(T_XOR, MainTokenMask)
425                             >>  and_exp
426                                 [
427                                     exclusive_or_exp.val =
428                                         impl::binary_bitxor(exclusive_or_exp.val, arg1)
429                                 ]
430                         )
431                 ;
432 
433             and_exp
434                 =   cmp_equality[and_exp.val = arg1]
435                     >> *(   pattern_p(T_AND, MainTokenMask)
436                             >>  cmp_equality
437                                 [
438                                     and_exp.val =
439                                         impl::binary_bitand(and_exp.val, arg1)
440                                 ]
441                         )
442                 ;
443 
444             cmp_equality
445                 =   cmp_relational[cmp_equality.val = arg1]
446                     >> *(   ch_p(T_EQUAL)
447                             >>  cmp_relational
448                                 [
449                                     cmp_equality.val =
450                                         impl::binary_eq(cmp_equality.val, arg1)
451                                 ]
452                         |   pattern_p(T_NOTEQUAL, MainTokenMask)
453                             >>  cmp_relational
454                                 [
455                                     cmp_equality.val =
456                                         impl::binary_ne(cmp_equality.val, arg1)
457                                 ]
458                         )
459                 ;
460 
461             cmp_relational
462                 =   shift_exp[cmp_relational.val = arg1]
463                     >> *(   ch_p(T_LESSEQUAL)
464                             >>  shift_exp
465                                 [
466                                     cmp_relational.val =
467                                         impl::binary_lesseq(cmp_relational.val, arg1)
468                                 ]
469                         |   ch_p(T_GREATEREQUAL)
470                             >>  shift_exp
471                                 [
472                                     cmp_relational.val =
473                                         impl::binary_greateq(cmp_relational.val, arg1)
474                                 ]
475                         |   ch_p(T_LESS)
476                             >>  shift_exp
477                                 [
478                                     cmp_relational.val =
479                                         impl::binary_less(cmp_relational.val, arg1)
480                                 ]
481                         |   ch_p(T_GREATER)
482                             >>  shift_exp
483                                 [
484                                     cmp_relational.val =
485                                         impl::binary_greater(cmp_relational.val, arg1)
486                                 ]
487                         )
488                 ;
489 
490             shift_exp
491                 =   add_exp[shift_exp.val = arg1]
492                     >> *(   ch_p(T_SHIFTLEFT)
493                             >>  add_exp
494                                 [
495                                     shift_exp.val <<= arg1
496                                 ]
497                         |   ch_p(T_SHIFTRIGHT)
498                             >>  add_exp
499                                 [
500                                     shift_exp.val >>= arg1
501                                 ]
502                         )
503                 ;
504 
505             add_exp
506                 =   multiply_exp[add_exp.val = arg1]
507                     >> *(   ch_p(T_PLUS)
508                             >>  multiply_exp
509                                 [
510                                     add_exp.val += arg1
511                                 ]
512                         |   ch_p(T_MINUS)
513                             >>  multiply_exp
514                                 [
515                                     add_exp.val -= arg1
516                                 ]
517                         )
518                 ;
519 
520             multiply_exp
521                 =   unary_exp[multiply_exp.val = arg1]
522                     >> *(   ch_p(T_STAR)
523                             >>  unary_exp
524                                 [
525                                     multiply_exp.val *= arg1
526                                 ]
527                         |   ch_p(T_DIVIDE)
528                             >>  unary_exp
529                                 [
530                                     multiply_exp.val /= arg1
531                                 ]
532                         |   ch_p(T_PERCENT)
533                             >>  unary_exp
534                                 [
535                                     multiply_exp.val %= arg1
536                                 ]
537                         )
538                 ;
539 
540             unary_exp
541                 =   primary_exp[unary_exp.val = arg1]
542                 |   ch_p(T_PLUS) >> unary_exp
543                     [
544                         unary_exp.val = arg1
545                     ]
546                 |   ch_p(T_MINUS) >> unary_exp
547                     [
548                         unary_exp.val = -arg1
549                     ]
550                 |   pattern_p(T_COMPL, MainTokenMask) >> unary_exp
551                     [
552                         unary_exp.val = ~arg1
553                     ]
554                 |   pattern_p(T_NOT, MainTokenMask) >> unary_exp
555                     [
556                         unary_exp.val = impl::unary_neg(arg1)
557                     ]
558                 ;
559 
560             primary_exp
561                 =   constant[primary_exp.val = arg1]
562                 |   ch_p(T_LEFTPAREN)
563                     >> const_exp[primary_exp.val = arg1]
564                     >> ch_p(T_RIGHTPAREN)
565                 ;
566 
567             constant
568                 =   ch_p(T_PP_NUMBER)
569                     [
570                         constant.val = impl::as_intlit(arg1)
571                     ]
572                 |   ch_p(T_INTLIT)
573                     [
574                         constant.val = impl::as_intlit(arg1)
575                     ]
576                 |   ch_p(T_CHARLIT)
577                     [
578                         constant.val = impl::as_chlit(arg1)
579                     ]
580                 ;
581 
582             //  here follows the same grammar, but without any embedded
583             //  calculations
584             const_exp_nocalc
585                 =   logical_or_exp_nocalc
586                     >> !(   ch_p(T_QUESTION_MARK)
587                             >>  const_exp_nocalc
588                             >>  ch_p(T_COLON)
589                             >>  const_exp_nocalc
590                         )
591                 ;
592 
593             logical_or_exp_nocalc
594                 =   logical_and_exp_nocalc
595                     >> *(   pattern_p(T_OROR, MainTokenMask)
596                             >>  logical_and_exp_nocalc
597                         )
598                 ;
599 
600             logical_and_exp_nocalc
601                 =   inclusive_or_exp_nocalc
602                     >> *(   pattern_p(T_ANDAND, MainTokenMask)
603                             >>  inclusive_or_exp_nocalc
604                         )
605                 ;
606 
607             inclusive_or_exp_nocalc
608                 =   exclusive_or_exp_nocalc
609                     >> *(   pattern_p(T_OR, MainTokenMask)
610                             >>  exclusive_or_exp_nocalc
611                         )
612                 ;
613 
614             exclusive_or_exp_nocalc
615                 =   and_exp_nocalc
616                     >> *(   pattern_p(T_XOR, MainTokenMask)
617                             >>  and_exp_nocalc
618                         )
619                 ;
620 
621             and_exp_nocalc
622                 =   cmp_equality_nocalc
623                     >> *(   pattern_p(T_AND, MainTokenMask)
624                             >>  cmp_equality_nocalc
625                         )
626                 ;
627 
628             cmp_equality_nocalc
629                 =   cmp_relational_nocalc
630                     >> *(   ch_p(T_EQUAL)
631                             >>  cmp_relational_nocalc
632                         |   pattern_p(T_NOTEQUAL, MainTokenMask)
633                             >>  cmp_relational_nocalc
634                         )
635                 ;
636 
637             cmp_relational_nocalc
638                 =   shift_exp_nocalc
639                     >> *(   ch_p(T_LESSEQUAL)
640                             >>  shift_exp_nocalc
641                         |   ch_p(T_GREATEREQUAL)
642                             >>  shift_exp_nocalc
643                         |   ch_p(T_LESS)
644                             >>  shift_exp_nocalc
645                         |   ch_p(T_GREATER)
646                             >>  shift_exp_nocalc
647                         )
648                 ;
649 
650             shift_exp_nocalc
651                 =   add_exp_nocalc
652                     >> *(   ch_p(T_SHIFTLEFT)
653                             >>  add_exp_nocalc
654                         |   ch_p(T_SHIFTRIGHT)
655                             >>  add_exp_nocalc
656                         )
657                 ;
658 
659             add_exp_nocalc
660                 =   multiply_exp_nocalc
661                     >> *(   ch_p(T_PLUS)
662                             >>  multiply_exp_nocalc
663                         |   ch_p(T_MINUS)
664                             >>  multiply_exp_nocalc
665                         )
666                 ;
667 
668             multiply_exp_nocalc
669                 =   unary_exp_nocalc
670                     >> *(   ch_p(T_STAR)
671                             >>  unary_exp_nocalc
672                         |   ch_p(T_DIVIDE)
673                             >>  unary_exp_nocalc
674                         |   ch_p(T_PERCENT)
675                             >>  unary_exp_nocalc
676                         )
677                 ;
678 
679             unary_exp_nocalc
680                 =   primary_exp_nocalc
681                 |   ch_p(T_PLUS) >> unary_exp_nocalc
682                 |   ch_p(T_MINUS) >> unary_exp_nocalc
683                 |   pattern_p(T_COMPL, MainTokenMask) >> unary_exp_nocalc
684                 |   pattern_p(T_NOT, MainTokenMask) >> unary_exp_nocalc
685                 ;
686 
687             primary_exp_nocalc
688                 =   constant_nocalc
689                 |   ch_p(T_LEFTPAREN)
690                     >> const_exp_nocalc
691                     >> ch_p(T_RIGHTPAREN)
692                 ;
693 
694             constant_nocalc
695                 =   ch_p(T_PP_NUMBER)
696                 |   ch_p(T_INTLIT)
697                 |   ch_p(T_CHARLIT)
698                 ;
699 
700             BOOST_SPIRIT_DEBUG_TRACE_RULE(pp_expression, TRACE_CPP_EXPR_GRAMMAR);
701             BOOST_SPIRIT_DEBUG_TRACE_RULE(const_exp, TRACE_CPP_EXPR_GRAMMAR);
702             BOOST_SPIRIT_DEBUG_TRACE_RULE(logical_or_exp, TRACE_CPP_EXPR_GRAMMAR);
703             BOOST_SPIRIT_DEBUG_TRACE_RULE(logical_and_exp, TRACE_CPP_EXPR_GRAMMAR);
704             BOOST_SPIRIT_DEBUG_TRACE_RULE(inclusive_or_exp, TRACE_CPP_EXPR_GRAMMAR);
705             BOOST_SPIRIT_DEBUG_TRACE_RULE(exclusive_or_exp, TRACE_CPP_EXPR_GRAMMAR);
706             BOOST_SPIRIT_DEBUG_TRACE_RULE(and_exp, TRACE_CPP_EXPR_GRAMMAR);
707             BOOST_SPIRIT_DEBUG_TRACE_RULE(cmp_equality, TRACE_CPP_EXPR_GRAMMAR);
708             BOOST_SPIRIT_DEBUG_TRACE_RULE(cmp_relational, TRACE_CPP_EXPR_GRAMMAR);
709             BOOST_SPIRIT_DEBUG_TRACE_RULE(shift_exp, TRACE_CPP_EXPR_GRAMMAR);
710             BOOST_SPIRIT_DEBUG_TRACE_RULE(add_exp, TRACE_CPP_EXPR_GRAMMAR);
711             BOOST_SPIRIT_DEBUG_TRACE_RULE(multiply_exp, TRACE_CPP_EXPR_GRAMMAR);
712             BOOST_SPIRIT_DEBUG_TRACE_RULE(unary_exp, TRACE_CPP_EXPR_GRAMMAR);
713             BOOST_SPIRIT_DEBUG_TRACE_RULE(primary_exp, TRACE_CPP_EXPR_GRAMMAR);
714             BOOST_SPIRIT_DEBUG_TRACE_RULE(constant, TRACE_CPP_EXPR_GRAMMAR);
715             BOOST_SPIRIT_DEBUG_TRACE_RULE(const_exp_subrule, TRACE_CPP_EXPR_GRAMMAR);
716 
717             BOOST_SPIRIT_DEBUG_TRACE_RULE(const_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
718             BOOST_SPIRIT_DEBUG_TRACE_RULE(logical_or_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
719             BOOST_SPIRIT_DEBUG_TRACE_RULE(logical_and_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
720             BOOST_SPIRIT_DEBUG_TRACE_RULE(inclusive_or_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
721             BOOST_SPIRIT_DEBUG_TRACE_RULE(exclusive_or_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
722             BOOST_SPIRIT_DEBUG_TRACE_RULE(and_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
723             BOOST_SPIRIT_DEBUG_TRACE_RULE(cmp_equality_nocalc, TRACE_CPP_EXPR_GRAMMAR);
724             BOOST_SPIRIT_DEBUG_TRACE_RULE(cmp_relational_nocalc, TRACE_CPP_EXPR_GRAMMAR);
725             BOOST_SPIRIT_DEBUG_TRACE_RULE(shift_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
726             BOOST_SPIRIT_DEBUG_TRACE_RULE(add_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
727             BOOST_SPIRIT_DEBUG_TRACE_RULE(multiply_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
728             BOOST_SPIRIT_DEBUG_TRACE_RULE(unary_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
729             BOOST_SPIRIT_DEBUG_TRACE_RULE(primary_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
730             BOOST_SPIRIT_DEBUG_TRACE_RULE(constant_nocalc, TRACE_CPP_EXPR_GRAMMAR);
731         }
732 
733     // start rule of this grammar
startboost::wave::grammars::expression_grammar::definition734         simple_rule_t const& start() const
735         { return pp_expression; }
736     };
737 };
738 
739 ///////////////////////////////////////////////////////////////////////////////
740 #undef TRACE_CPP_EXPR_GRAMMAR
741 
742 ///////////////////////////////////////////////////////////////////////////////
743 //
744 //  The following function is defined here, to allow the separation of
745 //  the compilation of the expression_grammar from the function using it.
746 //
747 ///////////////////////////////////////////////////////////////////////////////
748 
749 #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
750 #define BOOST_WAVE_EXPRGRAMMAR_GEN_INLINE
751 #else
752 #define BOOST_WAVE_EXPRGRAMMAR_GEN_INLINE inline
753 #endif
754 
755 template <typename TokenT>
756 BOOST_WAVE_EXPRGRAMMAR_GEN_INLINE
757 bool
evaluate(typename token_sequence_type::const_iterator const & first,typename token_sequence_type::const_iterator const & last,typename token_type::position_type const & act_pos,bool if_block_status,value_error & status)758 expression_grammar_gen<TokenT>::evaluate(
759     typename token_sequence_type::const_iterator const &first,
760     typename token_sequence_type::const_iterator const &last,
761     typename token_type::position_type const &act_pos,
762     bool if_block_status, value_error &status)
763 {
764     using namespace boost::spirit::classic;
765     using namespace boost::wave;
766     using namespace boost::wave::grammars::closures;
767 
768     using boost::wave::util::impl::as_string;
769 
770     typedef typename token_sequence_type::const_iterator iterator_type;
771     typedef typename token_sequence_type::value_type::string_type string_type;
772 
773     parse_info<iterator_type> hit(first);
774     closure_value result;             // expression result
775 
776 #if !defined(BOOST_NO_EXCEPTIONS)
777     try
778 #endif
779     {
780         expression_grammar g;             // expression grammar
781         hit = parse (first, last, g[spirit_assign_actor(result)],
782                      ch_p(T_SPACE) | ch_p(T_CCOMMENT) | ch_p(T_CPPCOMMENT));
783 
784         if (!hit.hit) {
785         // expression is illformed
786             if (if_block_status) {
787                 string_type expression = as_string<string_type>(first, last);
788                 if (0 == expression.size())
789                     expression = "<empty expression>";
790                 BOOST_WAVE_THROW(preprocess_exception, ill_formed_expression,
791                     expression.c_str(), act_pos);
792                 return false;
793             }
794             else {
795             //  as the if_block_status is false no errors will be reported
796                 return false;
797             }
798         }
799     }
800 #if !defined(BOOST_NO_EXCEPTIONS)
801     catch (boost::wave::preprocess_exception const& e) {
802     // expression is illformed
803         if (if_block_status) {
804             boost::throw_exception(e);
805             return false;
806         }
807         else         {
808         //  as the if_block_status is false no errors will be reported
809             return false;
810         }
811     }
812 #endif
813 
814     if (!hit.full) {
815     // The token list starts with a valid expression, but there remains
816     // something. If the remainder consists out of whitespace only, the
817     // expression is still valid.
818     iterator_type next = hit.stop;
819 
820         while (next != last) {
821             switch (static_cast<unsigned int>(token_id(*next))) {
822             case T_SPACE:
823             case T_SPACE2:
824             case T_CCOMMENT:
825                 break;                      // ok continue
826 
827             case T_NEWLINE:
828             case T_EOF:
829             case T_CPPCOMMENT:              // contains newline
830                 return as_bool(result);     // expression is valid
831 
832             default:
833             // expression is illformed
834                 if (if_block_status) {
835                     string_type expression = as_string<string_type>(first, last);
836                     if (0 == expression.size())
837                         expression = "<empty expression>";
838                     BOOST_WAVE_THROW(preprocess_exception, ill_formed_expression,
839                         expression.c_str(), act_pos);
840                     return false;
841                 }
842                 else {
843                 //  as the if_block_status is false no errors will be reported
844                     return false;
845                 }
846             }
847             ++next;
848         }
849     }
850 
851     if (error_noerror != result.is_valid()) // division or other error by zero occurred
852         status = result.is_valid();
853 
854 // token sequence is a valid expression
855     return as_bool(result);
856 }
857 
858 #undef BOOST_WAVE_EXPRGRAMMAR_GEN_INLINE
859 
860 ///////////////////////////////////////////////////////////////////////////////
861 }   // namespace grammars
862 }   // namespace wave
863 }   // namespace boost
864 
865 // the suffix header occurs after all of the code
866 #ifdef BOOST_HAS_ABI_HEADERS
867 #include BOOST_ABI_SUFFIX
868 #endif
869 
870 #endif // !defined(CPP_EXPRESSION_GRAMMAR_HPP_099CD1A4_A6C0_44BE_8F24_0B00F5BE5674_INCLUDED)
871