]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 (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) |