annotate DEPENDENCIES/generic/include/boost/wave/grammars/cpp_expression_grammar.hpp @ 125:34e428693f5d vext

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