cpp_expression_grammar.hpp 34 KB

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