cpp_expression_value.hpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883
  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_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED)
  9. #define CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED
  10. #if defined (BOOST_SPIRIT_DEBUG)
  11. #include <iostream>
  12. #endif // defined(BOOST_SPIRIT_DEBUG)
  13. #include <boost/wave/wave_config.hpp>
  14. #include <boost/wave/grammars/cpp_value_error.hpp> // value_error
  15. // this must occur after all of the includes and before any code appears
  16. #ifdef BOOST_HAS_ABI_HEADERS
  17. #include BOOST_ABI_PREFIX
  18. #endif
  19. ///////////////////////////////////////////////////////////////////////////////
  20. namespace boost {
  21. namespace wave {
  22. namespace grammars {
  23. namespace closures {
  24. class closure_value;
  25. inline bool as_bool(closure_value const& v);
  26. ///////////////////////////////////////////////////////////////////////////////
  27. //
  28. // The closure_value class represents the closure type, which is used for the
  29. // expression grammar.
  30. //
  31. // This class was introduced to allow the expression grammar to respect
  32. // the numeric type of a numeric literal or expression result.
  33. //
  34. ///////////////////////////////////////////////////////////////////////////////
  35. class closure_value {
  36. public:
  37. enum value_type {
  38. is_int = 1,
  39. is_uint = 2,
  40. is_bool = 3
  41. };
  42. closure_value(value_error valid_ = error_noerror)
  43. : type(is_int), valid(valid_)
  44. { value.i = 0; }
  45. explicit closure_value(int i, value_error valid_ = error_noerror)
  46. : type(is_int), valid(valid_)
  47. { value.i = i; }
  48. explicit closure_value(unsigned int ui, value_error valid_ = error_noerror)
  49. : type(is_uint), valid(valid_)
  50. { value.ui = ui; }
  51. explicit closure_value(int_literal_type i, value_error valid_ = error_noerror)
  52. : type(is_int), valid(valid_)
  53. { value.i = i; }
  54. explicit closure_value(uint_literal_type ui, value_error valid_ = error_noerror)
  55. : type(is_uint), valid(valid_)
  56. { value.ui = ui; }
  57. explicit closure_value(bool b, value_error valid_ = error_noerror)
  58. : type(is_bool), valid(valid_)
  59. { value.b = b; }
  60. value_type get_type() const { return type; }
  61. value_error is_valid() const { return valid; }
  62. // explicit conversion
  63. friend int_literal_type as_int(closure_value const& v)
  64. {
  65. switch (v.type) {
  66. case is_uint: return v.value.ui;
  67. case is_bool: return v.value.b ? 1 : 0;
  68. case is_int: break;
  69. }
  70. return v.value.i;
  71. }
  72. friend uint_literal_type as_uint(closure_value const& v)
  73. {
  74. switch (v.type) {
  75. case is_uint: return v.value.ui;
  76. case is_bool: return v.value.b ? 1 : 0;
  77. case is_int: break;
  78. }
  79. return v.value.i;
  80. }
  81. friend int_literal_type as_long(closure_value const& v)
  82. {
  83. switch (v.type) {
  84. case is_uint: return v.value.ui;
  85. case is_bool: return v.value.b ? 1 : 0;
  86. case is_int: break;
  87. }
  88. return v.value.i;
  89. }
  90. friend uint_literal_type as_ulong(closure_value const& v)
  91. {
  92. switch (v.type) {
  93. case is_uint: return v.value.ui;
  94. case is_bool: return v.value.b ? 1 : 0;
  95. case is_int: break;
  96. }
  97. return v.value.i;
  98. }
  99. friend bool as_bool(closure_value const& v)
  100. {
  101. switch (v.type) {
  102. case is_uint: return v.value.ui != 0;
  103. case is_bool: return v.value.b;
  104. case is_int: break;
  105. }
  106. return v.value.i != 0.0;
  107. }
  108. // assignment
  109. closure_value &operator= (closure_value const &rhs)
  110. {
  111. switch (rhs.get_type()) {
  112. case is_int:
  113. value.i = as_long(rhs);
  114. type = is_int;
  115. break;
  116. case is_uint:
  117. value.ui = as_ulong(rhs);
  118. type = is_uint;
  119. break;
  120. case is_bool:
  121. value.b = as_bool(rhs);
  122. type = is_bool;
  123. break;
  124. }
  125. valid = rhs.valid;
  126. return *this;
  127. }
  128. closure_value &operator= (int rhs)
  129. {
  130. type = is_int;
  131. value.i = rhs;
  132. valid = error_noerror;
  133. return *this;
  134. }
  135. closure_value &operator= (unsigned int rhs)
  136. {
  137. type = is_uint;
  138. value.ui = rhs;
  139. valid = error_noerror;
  140. return *this;
  141. }
  142. closure_value &operator= (int_literal_type rhs)
  143. {
  144. type = is_int;
  145. value.i = rhs;
  146. valid = error_noerror;
  147. return *this;
  148. }
  149. closure_value &operator= (uint_literal_type rhs)
  150. {
  151. type = is_uint;
  152. value.ui = rhs;
  153. valid = error_noerror;
  154. return *this;
  155. }
  156. closure_value &operator= (bool rhs)
  157. {
  158. type = is_bool;
  159. value.b = rhs;
  160. valid = error_noerror;
  161. return *this;
  162. }
  163. // arithmetics
  164. closure_value &operator+= (closure_value const &rhs)
  165. {
  166. switch (type) {
  167. case is_int:
  168. switch(rhs.type) {
  169. case is_bool:
  170. {
  171. int_literal_type result = value.i + as_long(rhs);
  172. if ((rhs.value.i > 0L && value.i > result) ||
  173. (rhs.value.i < 0L && value.i < result))
  174. {
  175. valid = error_integer_overflow;
  176. }
  177. else {
  178. value.i = result;
  179. }
  180. }
  181. break;
  182. case is_int:
  183. {
  184. int_literal_type result = value.i + rhs.value.i;
  185. if ((rhs.value.i > 0L && value.i > result) ||
  186. (rhs.value.i < 0L && value.i < result))
  187. {
  188. valid = error_integer_overflow;
  189. }
  190. else {
  191. value.i = result;
  192. }
  193. }
  194. break;
  195. case is_uint:
  196. {
  197. uint_literal_type result = value.ui + rhs.value.ui;
  198. if (result < value.ui) {
  199. valid = error_integer_overflow;
  200. }
  201. else {
  202. value.ui = result;
  203. type = is_uint;
  204. }
  205. }
  206. break;
  207. }
  208. break;
  209. case is_uint:
  210. {
  211. uint_literal_type result = value.ui + as_ulong(rhs);
  212. if (result < value.ui) {
  213. valid = error_integer_overflow;
  214. }
  215. else {
  216. value.ui = result;
  217. }
  218. }
  219. break;
  220. case is_bool:
  221. value.i = value.b + as_bool(rhs);
  222. type = is_int;
  223. }
  224. valid = (value_error)(valid | rhs.valid);
  225. return *this;
  226. }
  227. closure_value &operator-= (closure_value const &rhs)
  228. {
  229. switch (type) {
  230. case is_int:
  231. switch(rhs.type) {
  232. case is_bool:
  233. {
  234. int_literal_type result = value.i - as_long(rhs);
  235. if ((rhs.value.i > 0L && result > value.i) ||
  236. (rhs.value.i < 0L && result < value.i))
  237. {
  238. valid = error_integer_overflow;
  239. }
  240. else {
  241. value.i = result;
  242. }
  243. }
  244. break;
  245. case is_int:
  246. {
  247. int_literal_type result = value.i - rhs.value.i;
  248. if ((rhs.value.i > 0L && result > value.i) ||
  249. (rhs.value.i < 0L && result < value.i))
  250. {
  251. valid = error_integer_overflow;
  252. }
  253. else {
  254. value.i = result;
  255. }
  256. }
  257. break;
  258. case is_uint:
  259. {
  260. uint_literal_type result = value.ui - rhs.value.ui;
  261. if (result > value.ui) {
  262. valid = error_integer_overflow;
  263. }
  264. else {
  265. value.ui = result;
  266. type = is_uint;
  267. }
  268. }
  269. break;
  270. }
  271. break;
  272. case is_uint:
  273. switch(rhs.type) {
  274. case is_bool:
  275. {
  276. uint_literal_type result = value.ui - as_ulong(rhs);
  277. if (result > value.ui)
  278. {
  279. valid = error_integer_overflow;
  280. }
  281. else {
  282. value.ui = result;
  283. }
  284. }
  285. break;
  286. case is_int:
  287. {
  288. uint_literal_type result = value.ui - rhs.value.i;
  289. if ((rhs.value.i > 0L && result > value.ui) ||
  290. (rhs.value.i < 0L && result < value.ui))
  291. {
  292. valid = error_integer_overflow;
  293. }
  294. else {
  295. value.ui = result;
  296. }
  297. }
  298. break;
  299. case is_uint:
  300. {
  301. uint_literal_type result = value.ui - rhs.value.ui;
  302. if (result > value.ui) {
  303. valid = error_integer_overflow;
  304. }
  305. else {
  306. value.ui = result;
  307. }
  308. }
  309. break;
  310. }
  311. break;
  312. case is_bool:
  313. value.i = value.b - as_bool(rhs);
  314. type = is_int;
  315. }
  316. valid = (value_error)(valid | rhs.valid);
  317. return *this;
  318. }
  319. closure_value &operator*= (closure_value const &rhs)
  320. {
  321. switch (type) {
  322. case is_int:
  323. switch(rhs.type) {
  324. case is_bool: value.i *= as_long(rhs); break;
  325. case is_int:
  326. {
  327. int_literal_type result = value.i * rhs.value.i;
  328. if (0 != value.i && 0 != rhs.value.i &&
  329. (result / value.i != rhs.value.i ||
  330. result / rhs.value.i != value.i)
  331. )
  332. {
  333. valid = error_integer_overflow;
  334. }
  335. else {
  336. value.i = result;
  337. }
  338. }
  339. break;
  340. case is_uint:
  341. {
  342. uint_literal_type result = value.ui * rhs.value.ui;
  343. if (0 != value.ui && 0 != rhs.value.ui &&
  344. (result / value.ui != rhs.value.ui ||
  345. result / rhs.value.ui != value.ui)
  346. )
  347. {
  348. valid = error_integer_overflow;
  349. }
  350. else {
  351. value.ui = result;
  352. type = is_uint;
  353. }
  354. }
  355. break;
  356. }
  357. break;
  358. case is_uint:
  359. {
  360. uint_literal_type rhs_val = as_ulong(rhs);
  361. uint_literal_type result = value.ui * rhs_val;
  362. if (0 != value.ui && 0 != rhs_val &&
  363. (result / value.ui != rhs_val ||
  364. result / rhs_val != value.ui)
  365. )
  366. {
  367. valid = error_integer_overflow;
  368. }
  369. else {
  370. value.ui = result;
  371. type = is_uint;
  372. }
  373. }
  374. break;
  375. case is_bool:
  376. switch (rhs.type) {
  377. case is_int:
  378. value.i = (value.b ? 1 : 0) * rhs.value.i;
  379. type = is_int;
  380. break;
  381. case is_uint:
  382. value.ui = (value.b ? 1 : 0) * rhs.value.ui;
  383. type = is_uint;
  384. break;
  385. case is_bool:
  386. value.b = 0 != ((value.b ? 1 : 0) * (rhs.value.b ? 1 : 0));
  387. break;
  388. }
  389. }
  390. valid = (value_error)(valid | rhs.valid);
  391. return *this;
  392. }
  393. closure_value &operator/= (closure_value const &rhs)
  394. {
  395. switch (type) {
  396. case is_int:
  397. switch(rhs.type) {
  398. case is_bool:
  399. case is_int:
  400. if (as_long(rhs) != 0) {
  401. if (value.i == -value.i && -1 == rhs.value.i) {
  402. // LONG_MIN / -1 on two's complement
  403. valid = error_integer_overflow;
  404. }
  405. else {
  406. value.i /= as_long(rhs);
  407. }
  408. }
  409. else {
  410. valid = error_division_by_zero; // division by zero
  411. }
  412. break;
  413. case is_uint:
  414. if (rhs.value.ui != 0) {
  415. value.ui /= rhs.value.ui;
  416. type = is_uint;
  417. }
  418. else {
  419. valid = error_division_by_zero; // division by zero
  420. }
  421. break;
  422. }
  423. break;
  424. case is_uint:
  425. if (as_ulong(rhs) != 0)
  426. value.ui /= as_ulong(rhs);
  427. else
  428. valid = error_division_by_zero; // division by zero
  429. break;
  430. case is_bool:
  431. if (as_bool(rhs)) {
  432. switch(rhs.type) {
  433. case is_int:
  434. value.i = (value.b ? 1 : 0) / rhs.value.i;
  435. type = is_int;
  436. break;
  437. case is_uint:
  438. value.i = (value.b ? 1 : 0) / rhs.value.ui;
  439. type = is_int;
  440. break;
  441. case is_bool:
  442. break;
  443. }
  444. }
  445. else {
  446. valid = error_division_by_zero; // division by zero
  447. }
  448. }
  449. return *this;
  450. }
  451. closure_value &operator%= (closure_value const &rhs)
  452. {
  453. switch (type) {
  454. case is_int:
  455. switch(rhs.type) {
  456. case is_bool:
  457. case is_int:
  458. if (as_long(rhs) != 0) {
  459. if (value.i == -value.i && -1 == rhs.value.i) {
  460. // LONG_MIN % -1 on two's complement
  461. valid = error_integer_overflow;
  462. }
  463. else {
  464. value.i %= as_long(rhs);
  465. }
  466. }
  467. else {
  468. valid = error_division_by_zero; // division by zero
  469. }
  470. break;
  471. case is_uint:
  472. if (rhs.value.ui != 0) {
  473. value.ui %= rhs.value.ui;
  474. type = is_uint;
  475. }
  476. else {
  477. valid = error_division_by_zero; // division by zero
  478. }
  479. break;
  480. }
  481. break;
  482. case is_uint:
  483. if (as_ulong(rhs) != 0)
  484. value.ui %= as_ulong(rhs);
  485. else
  486. valid = error_division_by_zero; // division by zero
  487. break;
  488. case is_bool:
  489. if (as_bool(rhs)) {
  490. switch(rhs.type) {
  491. case is_int:
  492. value.i = (value.b ? 1 : 0) % rhs.value.i;
  493. type = is_int;
  494. break;
  495. case is_uint:
  496. value.i = (value.b ? 1 : 0) % rhs.value.ui;
  497. type = is_int;
  498. break;
  499. case is_bool:
  500. break;
  501. }
  502. }
  503. else {
  504. valid = error_division_by_zero; // division by zero
  505. }
  506. }
  507. return *this;
  508. }
  509. friend closure_value
  510. operator- (closure_value const &rhs)
  511. {
  512. switch (rhs.type) {
  513. case is_int:
  514. {
  515. int_literal_type value = as_long(rhs);
  516. if (value != 0 && value == -value)
  517. return closure_value(-value, error_integer_overflow);
  518. return closure_value(-value, rhs.valid);
  519. }
  520. case is_bool: return closure_value(-as_long(rhs), rhs.valid);
  521. case is_uint: break;
  522. }
  523. int_literal_type value = as_ulong(rhs);
  524. if (value != 0 && value == -value)
  525. return closure_value(-value, error_integer_overflow);
  526. return closure_value(-value, rhs.valid);
  527. }
  528. friend closure_value
  529. operator~ (closure_value const &rhs)
  530. {
  531. return closure_value(~as_ulong(rhs), rhs.valid);
  532. }
  533. friend closure_value
  534. operator! (closure_value const &rhs)
  535. {
  536. switch (rhs.type) {
  537. case is_int: return closure_value(!as_long(rhs), rhs.valid);
  538. case is_bool: return closure_value(!as_bool(rhs), rhs.valid);
  539. case is_uint: break;
  540. }
  541. return closure_value(!as_ulong(rhs), rhs.valid);
  542. }
  543. // comparison
  544. friend closure_value
  545. operator== (closure_value const &lhs, closure_value const &rhs)
  546. {
  547. bool cmp = false;
  548. switch (lhs.type) {
  549. case is_int:
  550. switch(rhs.type) {
  551. case is_bool: cmp = as_bool(lhs) == rhs.value.b; break;
  552. case is_int: cmp = lhs.value.i == rhs.value.i; break;
  553. case is_uint: cmp = lhs.value.ui == rhs.value.ui; break;
  554. }
  555. break;
  556. case is_uint: cmp = lhs.value.ui == as_ulong(rhs); break;
  557. case is_bool: cmp = lhs.value.b == as_bool(rhs); break;
  558. }
  559. return closure_value(cmp, (value_error)(lhs.valid | rhs.valid));
  560. }
  561. friend closure_value
  562. operator!= (closure_value const &lhs, closure_value const &rhs)
  563. {
  564. return closure_value(!as_bool(lhs == rhs), (value_error)(lhs.valid | rhs.valid));
  565. }
  566. friend closure_value
  567. operator> (closure_value const &lhs, closure_value const &rhs)
  568. {
  569. bool cmp = false;
  570. switch (lhs.type) {
  571. case is_int:
  572. switch(rhs.type) {
  573. case is_bool: cmp = lhs.value.i > as_long(rhs); break;
  574. case is_int: cmp = lhs.value.i > rhs.value.i; break;
  575. case is_uint: cmp = lhs.value.ui > rhs.value.ui; break;
  576. }
  577. break;
  578. case is_uint: cmp = lhs.value.ui > as_ulong(rhs); break;
  579. case is_bool: cmp = lhs.value.b > as_bool(rhs); break;
  580. }
  581. return closure_value(cmp, (value_error)(lhs.valid | rhs.valid));
  582. }
  583. friend closure_value
  584. operator< (closure_value const &lhs, closure_value const &rhs)
  585. {
  586. bool cmp = false;
  587. switch (lhs.type) {
  588. case is_int:
  589. switch(rhs.type) {
  590. case is_bool: cmp = lhs.value.i < as_long(rhs); break;
  591. case is_int: cmp = lhs.value.i < rhs.value.i; break;
  592. case is_uint: cmp = lhs.value.ui < rhs.value.ui; break;
  593. }
  594. break;
  595. case is_uint: cmp = lhs.value.ui < as_ulong(rhs); break;
  596. case is_bool: cmp = as_bool(lhs) < as_bool(rhs); break;
  597. }
  598. return closure_value(cmp, (value_error)(lhs.valid | rhs.valid));
  599. }
  600. friend closure_value
  601. operator<= (closure_value const &lhs, closure_value const &rhs)
  602. {
  603. return closure_value(!as_bool(lhs > rhs), (value_error)(lhs.valid | rhs.valid));
  604. }
  605. friend closure_value
  606. operator>= (closure_value const &lhs, closure_value const &rhs)
  607. {
  608. return closure_value(!as_bool(lhs < rhs), (value_error)(lhs.valid | rhs.valid));
  609. }
  610. closure_value &
  611. operator<<= (closure_value const &rhs)
  612. {
  613. switch (type) {
  614. case is_bool:
  615. case is_int:
  616. switch (rhs.type) {
  617. case is_bool:
  618. case is_int:
  619. {
  620. int_literal_type shift_by = as_long(rhs);
  621. if (shift_by > 64)
  622. shift_by = 64;
  623. else if (shift_by < -64)
  624. shift_by = -64;
  625. value.i <<= shift_by;
  626. }
  627. break;
  628. case is_uint:
  629. {
  630. uint_literal_type shift_by = as_ulong(rhs);
  631. if (shift_by > 64)
  632. shift_by = 64;
  633. value.ui <<= shift_by;
  634. // Note: The usual arithmetic conversions are not performed on
  635. // bit shift operations.
  636. }
  637. break;
  638. }
  639. break;
  640. case is_uint:
  641. switch (rhs.type) {
  642. case is_bool:
  643. case is_int:
  644. {
  645. int_literal_type shift_by = as_long(rhs);
  646. if (shift_by > 64)
  647. shift_by = 64;
  648. else if (shift_by < -64)
  649. shift_by = -64;
  650. value.ui <<= shift_by;
  651. }
  652. break;
  653. case is_uint:
  654. {
  655. uint_literal_type shift_by = as_ulong(rhs);
  656. if (shift_by > 64)
  657. shift_by = 64;
  658. value.ui <<= shift_by;
  659. }
  660. break;
  661. }
  662. }
  663. valid = (value_error)(valid | rhs.valid);
  664. return *this;
  665. }
  666. closure_value &
  667. operator>>= (closure_value const &rhs)
  668. {
  669. switch (type) {
  670. case is_bool:
  671. case is_int:
  672. switch (rhs.type) {
  673. case is_bool:
  674. case is_int:
  675. {
  676. int_literal_type shift_by = as_long(rhs);
  677. if (shift_by > 64)
  678. shift_by = 64;
  679. else if (shift_by < -64)
  680. shift_by = -64;
  681. value.i >>= shift_by;
  682. }
  683. break;
  684. case is_uint:
  685. {
  686. uint_literal_type shift_by = as_ulong(rhs);
  687. if (shift_by > 64)
  688. shift_by = 64;
  689. value.ui >>= shift_by;
  690. // Note: The usual arithmetic conversions are not performed on
  691. // bit shift operations.
  692. }
  693. break;
  694. }
  695. break;
  696. case is_uint:
  697. switch (rhs.type) {
  698. case is_bool:
  699. case is_int:
  700. {
  701. int_literal_type shift_by = as_long(rhs);
  702. if (shift_by > 64)
  703. shift_by = 64;
  704. else if (shift_by < -64)
  705. shift_by = -64;
  706. value.ui >>= shift_by;
  707. }
  708. break;
  709. case is_uint:
  710. {
  711. uint_literal_type shift_by = as_ulong(rhs);
  712. if (shift_by > 64)
  713. shift_by = 64;
  714. value.ui >>= shift_by;
  715. }
  716. break;
  717. }
  718. break;
  719. }
  720. valid = (value_error)(valid | rhs.valid);
  721. return *this;
  722. }
  723. friend closure_value
  724. operator|| (closure_value const &lhs, closure_value const &rhs)
  725. {
  726. bool result = as_bool(lhs) || as_bool(rhs);
  727. return closure_value(result, (value_error)(lhs.valid | rhs.valid));
  728. }
  729. friend closure_value
  730. operator&& (closure_value const &lhs, closure_value const &rhs)
  731. {
  732. bool result = as_bool(lhs) && as_bool(rhs);
  733. return closure_value(result, (value_error)(lhs.valid | rhs.valid));
  734. }
  735. friend closure_value
  736. operator| (closure_value const &lhs, closure_value const &rhs)
  737. {
  738. uint_literal_type result = as_ulong(lhs) | as_ulong(rhs);
  739. return closure_value(result, (value_error)(lhs.valid | rhs.valid));
  740. }
  741. friend closure_value
  742. operator& (closure_value const &lhs, closure_value const &rhs)
  743. {
  744. uint_literal_type result = as_ulong(lhs) & as_ulong(rhs);
  745. return closure_value(result, (value_error)(lhs.valid | rhs.valid));
  746. }
  747. friend closure_value
  748. operator^ (closure_value const &lhs, closure_value const &rhs)
  749. {
  750. uint_literal_type result = as_ulong(lhs) ^ as_ulong(rhs);
  751. return closure_value(result, (value_error)(lhs.valid | rhs.valid));
  752. }
  753. // handle the ?: operator
  754. closure_value &
  755. handle_questionmark(closure_value const &cond, closure_value const &val2)
  756. {
  757. switch (type) {
  758. case is_int:
  759. switch (val2.type) {
  760. case is_bool: value.b = as_bool(cond) ? value.b : as_bool(val2); break;
  761. case is_int: value.i = as_bool(cond) ? value.i : as_long(val2); break;
  762. case is_uint:
  763. value.ui = as_bool(cond) ? value.ui : as_ulong(val2);
  764. type = is_uint; // changing type!
  765. break;
  766. }
  767. break;
  768. case is_uint: value.ui = as_bool(cond) ? value.ui : as_ulong(val2); break;
  769. case is_bool: value.b = as_bool(cond) ? value.b : as_bool(val2); break;
  770. }
  771. valid = as_bool(cond) ? valid : val2.valid;
  772. return *this;
  773. }
  774. #if defined (BOOST_SPIRIT_DEBUG)
  775. friend std::ostream&
  776. operator<< (std::ostream &o, closure_value const &val)
  777. {
  778. switch (val.type) {
  779. case is_int: o << "int(" << as_long(val) << ")"; break;
  780. case is_uint: o << "unsigned int(" << as_ulong(val) << ")"; break;
  781. case is_bool: o << "bool(" << as_bool(val) << ")"; break;
  782. }
  783. return o;
  784. }
  785. #endif // defined(BOOST_SPIRIT_DEBUG)
  786. private:
  787. value_type type;
  788. union {
  789. int_literal_type i;
  790. uint_literal_type ui;
  791. bool b;
  792. } value;
  793. value_error valid;
  794. };
  795. ///////////////////////////////////////////////////////////////////////////////
  796. } // namespace closures
  797. } // namespace grammars
  798. } // namespace wave
  799. } // namespace boost
  800. // the suffix header occurs after all of the code
  801. #ifdef BOOST_HAS_ABI_HEADERS
  802. #include BOOST_ABI_SUFFIX
  803. #endif
  804. #endif // !defined(CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED)