]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/wave/grammars/cpp_expression_grammar.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / wave / grammars / cpp_expression_grammar.hpp
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
93 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
121 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
164 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
186 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
210 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 {
295 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
332 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
734 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
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 (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)