operators.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Copyright (c) 2001-2011 Hartmut Kaiser
  4. Copyright (c) 2011 Bryce Lelbach
  5. Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. =============================================================================*/
  8. #if !defined(BOOST_SPIRIT_UTREE_OPERATORS)
  9. #define BOOST_SPIRIT_UTREE_OPERATORS
  10. #if defined(BOOST_MSVC)
  11. # pragma warning(push)
  12. # pragma warning(disable: 4804)
  13. # pragma warning(disable: 4805)
  14. #endif
  15. #include <exception>
  16. #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO)
  17. #include <ios>
  18. #include <boost/io/ios_state.hpp>
  19. #endif
  20. #include <boost/spirit/home/support/utree/utree.hpp>
  21. #include <boost/preprocessor/cat.hpp>
  22. #include <boost/throw_exception.hpp>
  23. #include <boost/type_traits/is_arithmetic.hpp>
  24. #include <boost/type_traits/is_integral.hpp>
  25. namespace boost { namespace spirit
  26. {
  27. // Relational operators
  28. bool operator==(utree const& a, utree const& b);
  29. bool operator<(utree const& a, utree const& b);
  30. bool operator!=(utree const& a, utree const& b);
  31. bool operator>(utree const& a, utree const& b);
  32. bool operator<=(utree const& a, utree const& b);
  33. bool operator>=(utree const& a, utree const& b);
  34. #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO)
  35. // output
  36. std::ostream& operator<<(std::ostream& out, utree const& x);
  37. std::ostream& operator<<(std::ostream& out, utree::invalid_type const& x);
  38. std::ostream& operator<<(std::ostream& out, utree::nil_type const& x);
  39. #endif
  40. // Logical operators
  41. utree operator&&(utree const& a, utree const& b);
  42. utree operator||(utree const& a, utree const& b);
  43. utree operator!(utree const& a);
  44. // Arithmetic operators
  45. utree operator+(utree const& a, utree const& b);
  46. utree operator-(utree const& a, utree const& b);
  47. utree operator*(utree const& a, utree const& b);
  48. utree operator/(utree const& a, utree const& b);
  49. utree operator%(utree const& a, utree const& b);
  50. utree operator-(utree const& a);
  51. // Bitwise operators
  52. utree operator&(utree const& a, utree const& b);
  53. utree operator|(utree const& a, utree const& b);
  54. utree operator^(utree const& a, utree const& b);
  55. utree operator<<(utree const& a, utree const& b);
  56. utree operator>>(utree const& a, utree const& b);
  57. utree operator~(utree const& a);
  58. // Implementation
  59. struct utree_is_equal
  60. {
  61. typedef bool result_type;
  62. template <typename A, typename B>
  63. bool dispatch(const A&, const B&, boost::mpl::false_) const
  64. {
  65. return false; // cannot compare different types by default
  66. }
  67. template <typename A, typename B>
  68. bool dispatch(const A& a, const B& b, boost::mpl::true_) const
  69. {
  70. return a == b; // for arithmetic types
  71. }
  72. template <typename A, typename B>
  73. bool operator()(const A& a, const B& b) const
  74. {
  75. return dispatch(a, b,
  76. boost::mpl::and_<
  77. boost::is_arithmetic<A>,
  78. boost::is_arithmetic<B> >());
  79. }
  80. template <typename T>
  81. bool operator()(const T& a, const T& b) const
  82. {
  83. // This code works for lists
  84. return a == b;
  85. }
  86. template <typename Base, utree_type::info type_>
  87. bool operator()(
  88. basic_string<Base, type_> const& a,
  89. basic_string<Base, type_> const& b) const
  90. {
  91. return static_cast<Base const&>(a) == static_cast<Base const&>(b);
  92. }
  93. bool operator()(utree::invalid_type, utree::invalid_type) const
  94. {
  95. return true;
  96. }
  97. bool operator()(utree::nil_type, utree::nil_type) const
  98. {
  99. return true;
  100. }
  101. bool operator()(function_base const&, function_base const&) const
  102. {
  103. return false; // just don't allow comparison of functions
  104. }
  105. };
  106. struct utree_is_less_than
  107. {
  108. typedef bool result_type;
  109. template <typename A, typename B>
  110. bool dispatch(const A&, const B&, boost::mpl::false_) const
  111. {
  112. return false; // cannot compare different types by default
  113. }
  114. template <typename A, typename B>
  115. bool dispatch(const A& a, const B& b, boost::mpl::true_) const
  116. {
  117. return a < b; // for arithmetic types
  118. }
  119. template <typename A, typename B>
  120. bool operator()(const A& a, const B& b) const
  121. {
  122. return dispatch(a, b,
  123. boost::mpl::and_<
  124. boost::is_arithmetic<A>,
  125. boost::is_arithmetic<B> >());
  126. }
  127. template <typename T>
  128. bool operator()(const T& a, const T& b) const
  129. {
  130. // This code works for lists
  131. return a < b;
  132. }
  133. template <typename Base, utree_type::info type_>
  134. bool operator()(
  135. basic_string<Base, type_> const& a,
  136. basic_string<Base, type_> const& b) const
  137. {
  138. return static_cast<Base const&>(a) < static_cast<Base const&>(b);
  139. }
  140. bool operator()(utree::invalid_type, utree::invalid_type) const
  141. {
  142. BOOST_THROW_EXCEPTION(bad_type_exception
  143. ("no less-than comparison for this utree type",
  144. utree_type::invalid_type));
  145. return false; // no less than comparison for nil
  146. }
  147. bool operator()(utree::nil_type, utree::nil_type) const
  148. {
  149. BOOST_THROW_EXCEPTION(bad_type_exception
  150. ("no less-than comparison for this utree type",
  151. utree_type::nil_type));
  152. return false; // no less than comparison for nil
  153. }
  154. bool operator()(any_ptr const&, any_ptr const&) const
  155. {
  156. BOOST_THROW_EXCEPTION(bad_type_exception
  157. ("no less-than comparison for this utree type",
  158. utree_type::any_type));
  159. return false; // no less than comparison for any_ptr
  160. }
  161. bool operator()(function_base const&, function_base const&) const
  162. {
  163. BOOST_THROW_EXCEPTION(bad_type_exception
  164. ("no less-than comparison for this utree type",
  165. utree_type::function_type));
  166. return false; // no less than comparison of functions
  167. }
  168. };
  169. #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO)
  170. struct utree_print
  171. {
  172. typedef void result_type;
  173. std::ostream& out;
  174. utree_print(std::ostream& out) : out(out) {}
  175. void operator()(utree::invalid_type) const
  176. {
  177. out << "<invalid> ";
  178. }
  179. void operator()(utree::nil_type) const
  180. {
  181. out << "<nil> ";
  182. }
  183. template <typename T>
  184. void operator()(T val) const
  185. {
  186. out << val << ' ';
  187. }
  188. void operator()(bool b) const
  189. {
  190. out << (b ? "true" : "false") << ' ';
  191. }
  192. void operator()(binary_range_type const& b) const
  193. {
  194. boost::io::ios_all_saver saver(out);
  195. out << "#";
  196. out.width(2);
  197. out.fill('0');
  198. typedef binary_range_type::const_iterator iterator;
  199. for (iterator i = b.begin(); i != b.end(); ++i)
  200. out << std::hex << int((unsigned char)*i);
  201. out << "# ";
  202. }
  203. void operator()(utf8_string_range_type const& str) const
  204. {
  205. typedef utf8_string_range_type::const_iterator iterator;
  206. iterator i = str.begin();
  207. out << '"';
  208. for (; i != str.end(); ++i)
  209. out << *i;
  210. out << "\" ";
  211. }
  212. void operator()(utf8_symbol_range_type const& str) const
  213. {
  214. typedef utf8_symbol_range_type::const_iterator iterator;
  215. iterator i = str.begin();
  216. for (; i != str.end(); ++i)
  217. out << *i;
  218. out << ' ';
  219. }
  220. template <typename Iterator>
  221. void operator()(boost::iterator_range<Iterator> const& range) const
  222. {
  223. typedef typename boost::iterator_range<Iterator>::const_iterator iterator;
  224. (*this)('(');
  225. for (iterator i = range.begin(); i != range.end(); ++i)
  226. {
  227. boost::spirit::utree::visit(*i, *this);
  228. }
  229. (*this)(')');
  230. }
  231. void operator()(any_ptr const&) const
  232. {
  233. return (*this)("<pointer>");
  234. }
  235. void operator()(function_base const&) const
  236. {
  237. return (*this)("<function>");
  238. }
  239. };
  240. #endif
  241. template <typename Base>
  242. struct logical_function
  243. {
  244. typedef utree result_type;
  245. // We assume anything except false is true
  246. // binary
  247. template <typename A, typename B>
  248. utree operator()(A const& a, B const& b) const
  249. {
  250. return dispatch(a, b
  251. , boost::is_arithmetic<A>()
  252. , boost::is_arithmetic<B>());
  253. }
  254. // binary
  255. template <typename A, typename B>
  256. utree dispatch(A const& a, B const& b, mpl::true_, mpl::true_) const
  257. {
  258. return Base::eval(a, b); // for arithmetic types
  259. }
  260. // binary
  261. template <typename A, typename B>
  262. utree dispatch(A const&, B const& b, mpl::false_, mpl::true_) const
  263. {
  264. return Base::eval(true, b);
  265. }
  266. // binary
  267. template <typename A, typename B>
  268. utree dispatch(A const& a, B const&, mpl::true_, mpl::false_) const
  269. {
  270. return Base::eval(a, true);
  271. }
  272. // binary
  273. template <typename A, typename B>
  274. utree dispatch(A const&, B const&, mpl::false_, mpl::false_) const
  275. {
  276. return Base::eval(true, true);
  277. }
  278. // unary
  279. template <typename A>
  280. utree operator()(A const& a) const
  281. {
  282. return dispatch(a, boost::is_arithmetic<A>());
  283. }
  284. // unary
  285. template <typename A>
  286. utree dispatch(A const& a, mpl::true_) const
  287. {
  288. return Base::eval(a);
  289. }
  290. // unary
  291. template <typename A>
  292. utree dispatch(A const&, mpl::false_) const
  293. {
  294. return Base::eval(true);
  295. }
  296. };
  297. template <typename Base>
  298. struct arithmetic_function
  299. {
  300. typedef utree result_type;
  301. template <typename A, typename B>
  302. utree dispatch(A const&, B const&, boost::mpl::false_) const
  303. {
  304. return utree(); // cannot apply to non-arithmetic types
  305. }
  306. template <typename A, typename B>
  307. utree dispatch(A const& a, B const& b, boost::mpl::true_) const
  308. {
  309. return Base::eval(a, b); // for arithmetic types
  310. }
  311. // binary
  312. template <typename A, typename B>
  313. utree operator()(A const& a, B const& b) const
  314. {
  315. return dispatch(a, b,
  316. boost::mpl::and_<
  317. boost::is_arithmetic<A>,
  318. boost::is_arithmetic<B> >());
  319. }
  320. template <typename A>
  321. utree dispatch(A const&, boost::mpl::false_) const
  322. {
  323. return utree(); // cannot apply to non-arithmetic types
  324. }
  325. template <typename A>
  326. utree dispatch(A const& a, boost::mpl::true_) const
  327. {
  328. return Base::eval(a); // for arithmetic types
  329. }
  330. // unary
  331. template <typename A>
  332. utree operator()(A const& a) const
  333. {
  334. return dispatch(a, boost::is_arithmetic<A>());
  335. }
  336. };
  337. template <typename Base>
  338. struct integral_function
  339. {
  340. typedef utree result_type;
  341. template <typename A, typename B>
  342. utree dispatch(A const&, B const&, boost::mpl::false_) const
  343. {
  344. return utree(); // cannot apply to non-integral types
  345. }
  346. template <typename A, typename B>
  347. utree dispatch(A const& a, B const& b, boost::mpl::true_) const
  348. {
  349. return Base::eval(a, b); // for integral types
  350. }
  351. // binary
  352. template <typename A, typename B>
  353. utree operator()(A const& a, B const& b) const
  354. {
  355. return dispatch(a, b,
  356. boost::mpl::and_<
  357. boost::is_integral<A>,
  358. boost::is_integral<B> >());
  359. }
  360. template <typename A>
  361. utree dispatch(A const&, boost::mpl::false_) const
  362. {
  363. return utree(); // cannot apply to non-integral types
  364. }
  365. template <typename A>
  366. utree dispatch(A const& a, boost::mpl::true_) const
  367. {
  368. return Base::eval(a); // for integral types
  369. }
  370. // unary
  371. template <typename A>
  372. utree operator()(A const& a) const
  373. {
  374. return dispatch(a, boost::is_integral<A>());
  375. }
  376. };
  377. #define BOOST_SPIRIT_UTREE_CREATE_FUNCTION(name, expr, base) \
  378. struct BOOST_PP_CAT(function_impl_, name) \
  379. { \
  380. template <typename A, typename B> \
  381. static utree eval(A const& a, B const& b) \
  382. { \
  383. return utree(expr); \
  384. } \
  385. template <typename A> \
  386. static utree eval(A const& a) \
  387. { \
  388. static int b; \
  389. (void) b; \
  390. return utree(expr); \
  391. } \
  392. }; \
  393. base<BOOST_PP_CAT(function_impl_, name)> const \
  394. BOOST_PP_CAT(base, BOOST_PP_CAT(_, name)) = {}; \
  395. /***/
  396. #define BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(name, expr) \
  397. BOOST_SPIRIT_UTREE_CREATE_FUNCTION(name, expr, arithmetic_function) \
  398. /***/
  399. #define BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(name, expr) \
  400. BOOST_SPIRIT_UTREE_CREATE_FUNCTION(name, expr, integral_function) \
  401. /***/
  402. #define BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(name, expr) \
  403. BOOST_SPIRIT_UTREE_CREATE_FUNCTION(name, expr, logical_function) \
  404. /***/
  405. inline bool operator==(utree const& a, utree const& b)
  406. {
  407. return utree::visit(a, b, utree_is_equal());
  408. }
  409. inline bool operator<(utree const& a, utree const& b)
  410. {
  411. return utree::visit(a, b, utree_is_less_than());
  412. }
  413. inline bool operator!=(utree const& a, utree const& b)
  414. {
  415. return !(a == b);
  416. }
  417. inline bool operator>(utree const& a, utree const& b)
  418. {
  419. return b < a;
  420. }
  421. inline bool operator<=(utree const& a, utree const& b)
  422. {
  423. return !(b < a);
  424. }
  425. inline bool operator>=(utree const& a, utree const& b)
  426. {
  427. return !(a < b);
  428. }
  429. #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO)
  430. inline std::ostream& operator<<(std::ostream& out, utree const& x)
  431. {
  432. utree::visit(x, utree_print(out));
  433. return out;
  434. }
  435. inline std::ostream& operator<<(std::ostream& out, utree::invalid_type const&)
  436. {
  437. return out;
  438. }
  439. inline std::ostream& operator<<(std::ostream& out, utree::nil_type const&)
  440. {
  441. return out;
  442. }
  443. #endif
  444. BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(and_, a&&b)
  445. BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(or_, a||b)
  446. BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(not_, !a)
  447. BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(plus, a+b)
  448. BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(minus, a-b)
  449. BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(times, a*b)
  450. BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(divides, a/b)
  451. BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(modulus, a%b)
  452. BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(negate, -a)
  453. BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(bitand_, a&b)
  454. BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(bitor_, a|b)
  455. BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(bitxor_, a^b)
  456. BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(shift_left, a<<b)
  457. BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(shift_right, a>>b)
  458. #if defined(__GNUC__) && (__GNUC__ >= 7)
  459. # pragma GCC diagnostic push
  460. # pragma GCC diagnostic ignored "-Wbool-operation" // '~' on an expression of type bool
  461. #endif
  462. BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(invert, ~a)
  463. #if defined(__GNUC__) && (__GNUC__ >= 7)
  464. # pragma GCC diagnostic pop
  465. #endif
  466. inline utree operator&&(utree const& a, utree const& b)
  467. {
  468. return utree::visit(a, b, logical_function_and_);
  469. }
  470. inline utree operator||(utree const& a, utree const& b)
  471. {
  472. return utree::visit(a, b, logical_function_or_);
  473. }
  474. inline utree operator!(utree const& a)
  475. {
  476. return utree::visit(a, logical_function_not_);
  477. }
  478. inline utree operator+(utree const& a, utree const& b)
  479. {
  480. utree r = utree::visit(a, b, arithmetic_function_plus);
  481. if (r.which() == utree_type::invalid_type)
  482. {
  483. BOOST_THROW_EXCEPTION(bad_type_exception
  484. ("addition performed on non-arithmetic utree types",
  485. a.which(), b.which()));
  486. }
  487. return r;
  488. }
  489. inline utree operator-(utree const& a, utree const& b)
  490. {
  491. utree r = utree::visit(a, b, arithmetic_function_minus);
  492. if (r.which() == utree_type::invalid_type)
  493. {
  494. BOOST_THROW_EXCEPTION(bad_type_exception
  495. ("subtraction performed on non-arithmetic utree types",
  496. a.which(), b.which()));
  497. }
  498. return r;
  499. }
  500. inline utree operator*(utree const& a, utree const& b)
  501. {
  502. utree r = utree::visit(a, b, arithmetic_function_times);
  503. if (r.which() == utree_type::invalid_type)
  504. {
  505. BOOST_THROW_EXCEPTION(bad_type_exception
  506. ("multiplication performed on non-arithmetic utree types",
  507. a.which(), b.which()));
  508. }
  509. return r;
  510. }
  511. inline utree operator/(utree const& a, utree const& b)
  512. {
  513. utree r = utree::visit(a, b, arithmetic_function_divides);
  514. if (r.which() == utree_type::invalid_type)
  515. {
  516. BOOST_THROW_EXCEPTION(bad_type_exception
  517. ("division performed on non-arithmetic utree types",
  518. a.which(), b.which()));
  519. }
  520. return r;
  521. }
  522. inline utree operator%(utree const& a, utree const& b)
  523. {
  524. utree r = utree::visit(a, b, integral_function_modulus);
  525. if (r.which() == utree_type::invalid_type)
  526. {
  527. BOOST_THROW_EXCEPTION(bad_type_exception
  528. ("modulos performed on non-integral utree types",
  529. a.which(), b.which()));
  530. }
  531. return r;
  532. }
  533. inline utree operator-(utree const& a)
  534. {
  535. utree r = utree::visit(a, arithmetic_function_negate);
  536. if (r.which() == utree_type::invalid_type)
  537. {
  538. BOOST_THROW_EXCEPTION(bad_type_exception
  539. ("negation performed on non-arithmetic utree type",
  540. a.which()));
  541. }
  542. return r;
  543. }
  544. inline utree operator&(utree const& a, utree const& b)
  545. {
  546. utree r = utree::visit(a, b, integral_function_bitand_);
  547. if (r.which() == utree_type::invalid_type)
  548. {
  549. BOOST_THROW_EXCEPTION(bad_type_exception
  550. ("bitwise and performed on non-integral utree types",
  551. a.which(), b.which()));
  552. }
  553. return r;
  554. }
  555. inline utree operator|(utree const& a, utree const& b)
  556. {
  557. utree r = utree::visit(a, b, integral_function_bitor_);
  558. if (r.which() == utree_type::invalid_type)
  559. {
  560. BOOST_THROW_EXCEPTION(bad_type_exception
  561. ("bitwise or performed on non-integral utree types",
  562. a.which(), b.which()));
  563. }
  564. return r;
  565. }
  566. inline utree operator^(utree const& a, utree const& b)
  567. {
  568. utree r = utree::visit(a, b, integral_function_bitxor_);
  569. if (r.which() == utree_type::invalid_type)
  570. {
  571. BOOST_THROW_EXCEPTION(bad_type_exception
  572. ("bitwise xor performed on non-integral utree types",
  573. a.which(), b.which()));
  574. }
  575. return r;
  576. }
  577. inline utree operator<<(utree const& a, utree const& b)
  578. {
  579. utree r = utree::visit(a, b, integral_function_shift_left);
  580. if (r.which() == utree_type::invalid_type)
  581. {
  582. BOOST_THROW_EXCEPTION(bad_type_exception
  583. ("left shift performed on non-integral utree types",
  584. a.which(), b.which()));
  585. }
  586. return r;
  587. }
  588. inline utree operator>>(utree const& a, utree const& b)
  589. {
  590. utree r = utree::visit(a, b, integral_function_shift_right);
  591. if (r.which() == utree_type::invalid_type)
  592. {
  593. BOOST_THROW_EXCEPTION(bad_type_exception
  594. ("right shift performed on non-integral utree types",
  595. a.which(), b.which()));
  596. }
  597. return r;
  598. }
  599. inline utree operator~(utree const& a)
  600. {
  601. utree r = utree::visit(a, integral_function_invert);
  602. if (r.which() == utree_type::invalid_type)
  603. {
  604. BOOST_THROW_EXCEPTION(bad_type_exception
  605. ("inversion performed on non-integral utree type",
  606. a.which()));
  607. }
  608. return r;
  609. }
  610. }}
  611. #if defined(BOOST_MSVC)
  612. # pragma warning(pop)
  613. #endif
  614. #endif