cpp_expression_grammar.hpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870
  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(CPP_EXPRESSION_GRAMMAR_HPP_099CD1A4_A6C0_44BE_8F24_0B00F5BE5674_INCLUDED)
  9. #define 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_CHARLIT)
  507. [
  508. constant.val = impl::as_chlit(arg1)
  509. ]
  510. ;
  511. // here follows the same grammar, but without any embedded
  512. // calculations
  513. const_exp_nocalc
  514. = logical_or_exp_nocalc
  515. >> !( ch_p(T_QUESTION_MARK)
  516. >> const_exp_nocalc
  517. >> ch_p(T_COLON)
  518. >> const_exp_nocalc
  519. )
  520. ;
  521. logical_or_exp_nocalc
  522. = logical_and_exp_nocalc
  523. >> *( pattern_p(T_OROR, MainTokenMask)
  524. >> logical_and_exp_nocalc
  525. )
  526. ;
  527. logical_and_exp_nocalc
  528. = inclusive_or_exp_nocalc
  529. >> *( pattern_p(T_ANDAND, MainTokenMask)
  530. >> inclusive_or_exp_nocalc
  531. )
  532. ;
  533. inclusive_or_exp_nocalc
  534. = exclusive_or_exp_nocalc
  535. >> *( pattern_p(T_OR, MainTokenMask)
  536. >> exclusive_or_exp_nocalc
  537. )
  538. ;
  539. exclusive_or_exp_nocalc
  540. = and_exp_nocalc
  541. >> *( pattern_p(T_XOR, MainTokenMask)
  542. >> and_exp_nocalc
  543. )
  544. ;
  545. and_exp_nocalc
  546. = cmp_equality_nocalc
  547. >> *( pattern_p(T_AND, MainTokenMask)
  548. >> cmp_equality_nocalc
  549. )
  550. ;
  551. cmp_equality_nocalc
  552. = cmp_relational_nocalc
  553. >> *( ch_p(T_EQUAL)
  554. >> cmp_relational_nocalc
  555. | pattern_p(T_NOTEQUAL, MainTokenMask)
  556. >> cmp_relational_nocalc
  557. )
  558. ;
  559. cmp_relational_nocalc
  560. = shift_exp_nocalc
  561. >> *( ch_p(T_LESSEQUAL)
  562. >> shift_exp_nocalc
  563. | ch_p(T_GREATEREQUAL)
  564. >> shift_exp_nocalc
  565. | ch_p(T_LESS)
  566. >> shift_exp_nocalc
  567. | ch_p(T_GREATER)
  568. >> shift_exp_nocalc
  569. )
  570. ;
  571. shift_exp_nocalc
  572. = add_exp_nocalc
  573. >> *( ch_p(T_SHIFTLEFT)
  574. >> add_exp_nocalc
  575. | ch_p(T_SHIFTRIGHT)
  576. >> add_exp_nocalc
  577. )
  578. ;
  579. add_exp_nocalc
  580. = multiply_exp_nocalc
  581. >> *( ch_p(T_PLUS)
  582. >> multiply_exp_nocalc
  583. | ch_p(T_MINUS)
  584. >> multiply_exp_nocalc
  585. )
  586. ;
  587. multiply_exp_nocalc
  588. = unary_exp_nocalc
  589. >> *( ch_p(T_STAR)
  590. >> unary_exp_nocalc
  591. | ch_p(T_DIVIDE)
  592. >> unary_exp_nocalc
  593. | ch_p(T_PERCENT)
  594. >> unary_exp_nocalc
  595. )
  596. ;
  597. unary_exp_nocalc
  598. = primary_exp_nocalc
  599. | ch_p(T_PLUS) >> unary_exp_nocalc
  600. | ch_p(T_MINUS) >> unary_exp_nocalc
  601. | pattern_p(T_COMPL, MainTokenMask) >> unary_exp_nocalc
  602. | pattern_p(T_NOT, MainTokenMask) >> unary_exp_nocalc
  603. ;
  604. primary_exp_nocalc
  605. = constant_nocalc
  606. | ch_p(T_LEFTPAREN)
  607. >> const_exp_nocalc
  608. >> ch_p(T_RIGHTPAREN)
  609. ;
  610. constant_nocalc
  611. = ch_p(T_PP_NUMBER)
  612. | ch_p(T_INTLIT)
  613. | ch_p(T_CHARLIT)
  614. ;
  615. BOOST_SPIRIT_DEBUG_TRACE_RULE(pp_expression, TRACE_CPP_EXPR_GRAMMAR);
  616. BOOST_SPIRIT_DEBUG_TRACE_RULE(const_exp, TRACE_CPP_EXPR_GRAMMAR);
  617. BOOST_SPIRIT_DEBUG_TRACE_RULE(logical_or_exp, TRACE_CPP_EXPR_GRAMMAR);
  618. BOOST_SPIRIT_DEBUG_TRACE_RULE(logical_and_exp, TRACE_CPP_EXPR_GRAMMAR);
  619. BOOST_SPIRIT_DEBUG_TRACE_RULE(inclusive_or_exp, TRACE_CPP_EXPR_GRAMMAR);
  620. BOOST_SPIRIT_DEBUG_TRACE_RULE(exclusive_or_exp, TRACE_CPP_EXPR_GRAMMAR);
  621. BOOST_SPIRIT_DEBUG_TRACE_RULE(and_exp, TRACE_CPP_EXPR_GRAMMAR);
  622. BOOST_SPIRIT_DEBUG_TRACE_RULE(cmp_equality, TRACE_CPP_EXPR_GRAMMAR);
  623. BOOST_SPIRIT_DEBUG_TRACE_RULE(cmp_relational, TRACE_CPP_EXPR_GRAMMAR);
  624. BOOST_SPIRIT_DEBUG_TRACE_RULE(shift_exp, TRACE_CPP_EXPR_GRAMMAR);
  625. BOOST_SPIRIT_DEBUG_TRACE_RULE(add_exp, TRACE_CPP_EXPR_GRAMMAR);
  626. BOOST_SPIRIT_DEBUG_TRACE_RULE(multiply_exp, TRACE_CPP_EXPR_GRAMMAR);
  627. BOOST_SPIRIT_DEBUG_TRACE_RULE(unary_exp, TRACE_CPP_EXPR_GRAMMAR);
  628. BOOST_SPIRIT_DEBUG_TRACE_RULE(primary_exp, TRACE_CPP_EXPR_GRAMMAR);
  629. BOOST_SPIRIT_DEBUG_TRACE_RULE(constant, TRACE_CPP_EXPR_GRAMMAR);
  630. BOOST_SPIRIT_DEBUG_TRACE_RULE(const_exp_subrule, TRACE_CPP_EXPR_GRAMMAR);
  631. BOOST_SPIRIT_DEBUG_TRACE_RULE(const_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
  632. BOOST_SPIRIT_DEBUG_TRACE_RULE(logical_or_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
  633. BOOST_SPIRIT_DEBUG_TRACE_RULE(logical_and_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
  634. BOOST_SPIRIT_DEBUG_TRACE_RULE(inclusive_or_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
  635. BOOST_SPIRIT_DEBUG_TRACE_RULE(exclusive_or_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
  636. BOOST_SPIRIT_DEBUG_TRACE_RULE(and_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
  637. BOOST_SPIRIT_DEBUG_TRACE_RULE(cmp_equality_nocalc, TRACE_CPP_EXPR_GRAMMAR);
  638. BOOST_SPIRIT_DEBUG_TRACE_RULE(cmp_relational_nocalc, TRACE_CPP_EXPR_GRAMMAR);
  639. BOOST_SPIRIT_DEBUG_TRACE_RULE(shift_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
  640. BOOST_SPIRIT_DEBUG_TRACE_RULE(add_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
  641. BOOST_SPIRIT_DEBUG_TRACE_RULE(multiply_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
  642. BOOST_SPIRIT_DEBUG_TRACE_RULE(unary_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
  643. BOOST_SPIRIT_DEBUG_TRACE_RULE(primary_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
  644. BOOST_SPIRIT_DEBUG_TRACE_RULE(constant_nocalc, TRACE_CPP_EXPR_GRAMMAR);
  645. }
  646. // start rule of this grammar
  647. simple_rule_t const& start() const
  648. { return pp_expression; }
  649. };
  650. };
  651. ///////////////////////////////////////////////////////////////////////////////
  652. #undef TRACE_CPP_EXPR_GRAMMAR
  653. ///////////////////////////////////////////////////////////////////////////////
  654. //
  655. // The following function is defined here, to allow the separation of
  656. // the compilation of the expression_grammar from the function using it.
  657. //
  658. ///////////////////////////////////////////////////////////////////////////////
  659. #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
  660. #define BOOST_WAVE_EXPRGRAMMAR_GEN_INLINE
  661. #else
  662. #define BOOST_WAVE_EXPRGRAMMAR_GEN_INLINE inline
  663. #endif
  664. template <typename TokenT>
  665. BOOST_WAVE_EXPRGRAMMAR_GEN_INLINE
  666. bool
  667. expression_grammar_gen<TokenT>::evaluate(
  668. typename token_sequence_type::const_iterator const &first,
  669. typename token_sequence_type::const_iterator const &last,
  670. typename token_type::position_type const &act_pos,
  671. bool if_block_status, value_error &status)
  672. {
  673. using namespace boost::spirit::classic;
  674. using namespace boost::wave;
  675. using namespace boost::wave::grammars::closures;
  676. using boost::wave::util::impl::as_string;
  677. typedef typename token_sequence_type::const_iterator iterator_type;
  678. typedef typename token_sequence_type::value_type::string_type string_type;
  679. parse_info<iterator_type> hit(first);
  680. closure_value result; // expression result
  681. #if !defined(BOOST_NO_EXCEPTIONS)
  682. try
  683. #endif
  684. {
  685. expression_grammar g; // expression grammar
  686. hit = parse (first, last, g[spirit_assign_actor(result)],
  687. ch_p(T_SPACE) | ch_p(T_CCOMMENT) | ch_p(T_CPPCOMMENT));
  688. if (!hit.hit) {
  689. // expression is illformed
  690. if (if_block_status) {
  691. string_type expression = as_string<string_type>(first, last);
  692. if (0 == expression.size())
  693. expression = "<empty expression>";
  694. BOOST_WAVE_THROW(preprocess_exception, ill_formed_expression,
  695. expression.c_str(), act_pos);
  696. return false;
  697. }
  698. else {
  699. // as the if_block_status is false no errors will be reported
  700. return false;
  701. }
  702. }
  703. }
  704. #if !defined(BOOST_NO_EXCEPTIONS)
  705. catch (boost::wave::preprocess_exception const& e) {
  706. // expression is illformed
  707. if (if_block_status) {
  708. boost::throw_exception(e);
  709. return false;
  710. }
  711. else {
  712. // as the if_block_status is false no errors will be reported
  713. return false;
  714. }
  715. }
  716. #endif
  717. if (!hit.full) {
  718. // The token list starts with a valid expression, but there remains
  719. // something. If the remainder consists out of whitespace only, the
  720. // expression is still valid.
  721. iterator_type next = hit.stop;
  722. while (next != last) {
  723. switch (token_id(*next)) {
  724. case T_SPACE:
  725. case T_SPACE2:
  726. case T_CCOMMENT:
  727. break; // ok continue
  728. case T_NEWLINE:
  729. case T_EOF:
  730. case T_CPPCOMMENT: // contains newline
  731. return as_bool(result); // expression is valid
  732. default:
  733. // expression is illformed
  734. if (if_block_status) {
  735. string_type expression = as_string<string_type>(first, last);
  736. if (0 == expression.size())
  737. expression = "<empty expression>";
  738. BOOST_WAVE_THROW(preprocess_exception, ill_formed_expression,
  739. expression.c_str(), act_pos);
  740. return false;
  741. }
  742. else {
  743. // as the if_block_status is false no errors will be reported
  744. return false;
  745. }
  746. }
  747. ++next;
  748. }
  749. }
  750. if (error_noerror != result.is_valid()) // division or other error by zero occurred
  751. status = result.is_valid();
  752. // token sequence is a valid expression
  753. return as_bool(result);
  754. }
  755. #undef BOOST_WAVE_EXPRGRAMMAR_GEN_INLINE
  756. ///////////////////////////////////////////////////////////////////////////////
  757. } // namespace grammars
  758. } // namespace wave
  759. } // namespace boost
  760. // the suffix header occurs after all of the code
  761. #ifdef BOOST_HAS_ABI_HEADERS
  762. #include BOOST_ABI_SUFFIX
  763. #endif
  764. #endif // !defined(CPP_EXPRESSION_GRAMMAR_HPP_099CD1A4_A6C0_44BE_8F24_0B00F5BE5674_INCLUDED)