1 /*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 Copyright (c) 2001-2011 Hartmut Kaiser
4 Copyright (c) 2011 Bryce Lelbach
6 Distributed under the Boost Software License, Version 1.0. (See accompanying
7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9 #if !defined(BOOST_SPIRIT_UTREE_OPERATORS)
10 #define BOOST_SPIRIT_UTREE_OPERATORS
12 #if defined(BOOST_MSVC)
13 # pragma warning(push)
14 # pragma warning(disable: 4804)
15 # pragma warning(disable: 4805)
19 #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO)
21 #include <boost/io/ios_state.hpp>
23 #include <boost/spirit/home/support/utree/utree.hpp>
24 #include <boost/preprocessor/cat.hpp>
25 #include <boost/throw_exception.hpp>
26 #include <boost/type_traits/is_arithmetic.hpp>
27 #include <boost/type_traits/is_integral.hpp>
29 namespace boost { namespace spirit
31 // Relational operators
32 bool operator==(utree const& a, utree const& b);
33 bool operator<(utree const& a, utree const& b);
34 bool operator!=(utree const& a, utree const& b);
35 bool operator>(utree const& a, utree const& b);
36 bool operator<=(utree const& a, utree const& b);
37 bool operator>=(utree const& a, utree const& b);
39 #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO)
41 std::ostream& operator<<(std::ostream& out, utree const& x);
42 std::ostream& operator<<(std::ostream& out, utree::invalid_type const& x);
43 std::ostream& operator<<(std::ostream& out, utree::nil_type const& x);
47 utree operator&&(utree const& a, utree const& b);
48 utree operator||(utree const& a, utree const& b);
49 utree operator!(utree const& a);
51 // Arithmetic 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);
60 utree operator&(utree const& a, utree const& b);
61 utree operator|(utree const& a, utree const& b);
62 utree operator^(utree const& a, utree const& b);
63 utree operator<<(utree const& a, utree const& b);
64 utree operator>>(utree const& a, utree const& b);
65 utree operator~(utree const& a);
70 typedef bool result_type;
72 template <typename A, typename B>
73 bool dispatch(const A&, const B&, boost::mpl::false_) const
75 return false; // cannot compare different types by default
78 template <typename A, typename B>
79 bool dispatch(const A& a, const B& b, boost::mpl::true_) const
81 return a == b; // for arithmetic types
84 template <typename A, typename B>
85 bool operator()(const A& a, const B& b) const
89 boost::is_arithmetic<A>,
90 boost::is_arithmetic<B> >());
94 bool operator()(const T& a, const T& b) const
96 // This code works for lists
100 template <typename Base, utree_type::info type_>
102 basic_string<Base, type_> const& a,
103 basic_string<Base, type_> const& b) const
105 return static_cast<Base const&>(a) == static_cast<Base const&>(b);
108 bool operator()(utree::invalid_type, utree::invalid_type) const
113 bool operator()(utree::nil_type, utree::nil_type) const
118 bool operator()(function_base const&, function_base const&) const
120 return false; // just don't allow comparison of functions
124 struct utree_is_less_than
126 typedef bool result_type;
128 template <typename A, typename B>
129 bool dispatch(const A&, const B&, boost::mpl::false_) const
131 return false; // cannot compare different types by default
134 template <typename A, typename B>
135 bool dispatch(const A& a, const B& b, boost::mpl::true_) const
137 return a < b; // for arithmetic types
140 template <typename A, typename B>
141 bool operator()(const A& a, const B& b) const
143 return dispatch(a, b,
145 boost::is_arithmetic<A>,
146 boost::is_arithmetic<B> >());
149 template <typename T>
150 bool operator()(const T& a, const T& b) const
152 // This code works for lists
156 template <typename Base, utree_type::info type_>
158 basic_string<Base, type_> const& a,
159 basic_string<Base, type_> const& b) const
161 return static_cast<Base const&>(a) < static_cast<Base const&>(b);
164 bool operator()(utree::invalid_type, utree::invalid_type) const
166 BOOST_THROW_EXCEPTION(bad_type_exception
167 ("no less-than comparison for this utree type",
168 utree_type::invalid_type));
169 return false; // no less than comparison for nil
172 bool operator()(utree::nil_type, utree::nil_type) const
174 BOOST_THROW_EXCEPTION(bad_type_exception
175 ("no less-than comparison for this utree type",
176 utree_type::nil_type));
177 return false; // no less than comparison for nil
180 bool operator()(any_ptr const&, any_ptr const&) const
182 BOOST_THROW_EXCEPTION(bad_type_exception
183 ("no less-than comparison for this utree type",
184 utree_type::any_type));
185 return false; // no less than comparison for any_ptr
188 bool operator()(function_base const&, function_base const&) const
190 BOOST_THROW_EXCEPTION(bad_type_exception
191 ("no less-than comparison for this utree type",
192 utree_type::function_type));
193 return false; // no less than comparison of functions
197 #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO)
200 typedef void result_type;
203 utree_print(std::ostream& out) : out(out) {}
205 void operator()(utree::invalid_type) const
210 void operator()(utree::nil_type) const
215 template <typename T>
216 void operator()(T val) const
221 void operator()(bool b) const
223 out << (b ? "true" : "false") << ' ';
226 void operator()(binary_range_type const& b) const
228 boost::io::ios_all_saver saver(out);
233 typedef binary_range_type::const_iterator iterator;
234 for (iterator i = b.begin(); i != b.end(); ++i)
235 out << std::hex << int((unsigned char)*i);
239 void operator()(utf8_string_range_type const& str) const
241 typedef utf8_string_range_type::const_iterator iterator;
242 iterator i = str.begin();
244 for (; i != str.end(); ++i)
249 void operator()(utf8_symbol_range_type const& str) const
251 typedef utf8_symbol_range_type::const_iterator iterator;
252 iterator i = str.begin();
253 for (; i != str.end(); ++i)
258 template <typename Iterator>
259 void operator()(boost::iterator_range<Iterator> const& range) const
261 typedef typename boost::iterator_range<Iterator>::const_iterator iterator;
263 for (iterator i = range.begin(); i != range.end(); ++i)
265 boost::spirit::utree::visit(*i, *this);
270 void operator()(any_ptr const&) const
272 return (*this)("<pointer>");
275 void operator()(function_base const&) const
277 return (*this)("<function>");
282 template <typename Base>
283 struct logical_function
285 typedef utree result_type;
287 // We assume anything except false is true
290 template <typename A, typename B>
291 utree operator()(A const& a, B const& b) const
294 , boost::is_arithmetic<A>()
295 , boost::is_arithmetic<B>());
299 template <typename A, typename B>
300 utree dispatch(A const& a, B const& b, mpl::true_, mpl::true_) const
302 return Base::eval(a, b); // for arithmetic types
306 template <typename A, typename B>
307 utree dispatch(A const&, B const& b, mpl::false_, mpl::true_) const
309 return Base::eval(true, b);
313 template <typename A, typename B>
314 utree dispatch(A const& a, B const&, mpl::true_, mpl::false_) const
316 return Base::eval(a, true);
320 template <typename A, typename B>
321 utree dispatch(A const&, B const&, mpl::false_, mpl::false_) const
323 return Base::eval(true, true);
327 template <typename A>
328 utree operator()(A const& a) const
330 return dispatch(a, boost::is_arithmetic<A>());
334 template <typename A>
335 utree dispatch(A const& a, mpl::true_) const
337 return Base::eval(a);
341 template <typename A>
342 utree dispatch(A const&, mpl::false_) const
344 return Base::eval(true);
348 template <typename Base>
349 struct arithmetic_function
351 typedef utree result_type;
353 template <typename A, typename B>
354 utree dispatch(A const&, B const&, boost::mpl::false_) const
356 return utree(); // cannot apply to non-arithmetic types
359 template <typename A, typename B>
360 utree dispatch(A const& a, B const& b, boost::mpl::true_) const
362 return Base::eval(a, b); // for arithmetic types
366 template <typename A, typename B>
367 utree operator()(A const& a, B const& b) const
369 return dispatch(a, b,
371 boost::is_arithmetic<A>,
372 boost::is_arithmetic<B> >());
375 template <typename A>
376 utree dispatch(A const&, boost::mpl::false_) const
378 return utree(); // cannot apply to non-arithmetic types
381 template <typename A>
382 utree dispatch(A const& a, boost::mpl::true_) const
384 return Base::eval(a); // for arithmetic types
388 template <typename A>
389 utree operator()(A const& a) const
391 return dispatch(a, boost::is_arithmetic<A>());
395 template <typename Base>
396 struct integral_function
398 typedef utree result_type;
400 template <typename A, typename B>
401 utree dispatch(A const&, B const&, boost::mpl::false_) const
403 return utree(); // cannot apply to non-integral types
406 template <typename A, typename B>
407 utree dispatch(A const& a, B const& b, boost::mpl::true_) const
409 return Base::eval(a, b); // for integral types
413 template <typename A, typename B>
414 utree operator()(A const& a, B const& b) const
416 return dispatch(a, b,
418 boost::is_integral<A>,
419 boost::is_integral<B> >());
422 template <typename A>
423 utree dispatch(A const&, boost::mpl::false_) const
425 return utree(); // cannot apply to non-integral types
428 template <typename A>
429 utree dispatch(A const& a, boost::mpl::true_) const
431 return Base::eval(a); // for integral types
435 template <typename A>
436 utree operator()(A const& a) const
438 return dispatch(a, boost::is_integral<A>());
442 #define BOOST_SPIRIT_UTREE_CREATE_FUNCTION_BINARY \
443 template <typename Lhs, typename Rhs> \
444 static utree eval(Lhs const& a, Rhs const& b) \
447 #define BOOST_SPIRIT_UTREE_CREATE_FUNCTION_UNARY \
448 template <typename Operand> \
449 static utree eval(Operand const& a) \
452 #define BOOST_SPIRIT_UTREE_CREATE_FUNCTION(arity, name, expr, base) \
453 struct BOOST_PP_CAT(function_impl_, name) \
455 BOOST_SPIRIT_UTREE_CREATE_FUNCTION_##arity \
457 return utree(expr); \
460 base<BOOST_PP_CAT(function_impl_, name)> const \
461 BOOST_PP_CAT(base, BOOST_PP_CAT(_, name)) = {}; \
464 #define BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(arity, name, expr) \
465 BOOST_SPIRIT_UTREE_CREATE_FUNCTION(arity, name, expr, arithmetic_function)\
468 #define BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(arity, name, expr) \
469 BOOST_SPIRIT_UTREE_CREATE_FUNCTION(arity, name, expr, integral_function) \
472 #define BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(arity, name, expr) \
473 BOOST_SPIRIT_UTREE_CREATE_FUNCTION(arity, name, expr, logical_function) \
476 inline bool operator==(utree const& a, utree const& b)
478 return utree::visit(a, b, utree_is_equal());
481 inline bool operator<(utree const& a, utree const& b)
483 return utree::visit(a, b, utree_is_less_than());
486 inline bool operator!=(utree const& a, utree const& b)
491 inline bool operator>(utree const& a, utree const& b)
496 inline bool operator<=(utree const& a, utree const& b)
501 inline bool operator>=(utree const& a, utree const& b)
506 #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO)
507 inline std::ostream& operator<<(std::ostream& out, utree const& x)
509 utree::visit(x, utree_print(out));
513 inline std::ostream& operator<<(std::ostream& out, utree::invalid_type const&)
518 inline std::ostream& operator<<(std::ostream& out, utree::nil_type const&)
524 BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(BINARY, and_, a&&b)
525 BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(BINARY, or_, a||b)
526 BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(UNARY, not_, !a)
528 BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(BINARY, plus, a+b)
529 BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(BINARY, minus, a-b)
530 BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(BINARY, times, a*b)
531 BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(BINARY, divides, a/b)
532 BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION (BINARY, modulus, a%b)
533 BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(UNARY, negate, -a)
535 BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(BINARY, bitand_, a&b)
536 BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(BINARY, bitor_, a|b)
537 BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(BINARY, bitxor_, a^b)
538 BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(BINARY, shift_left, a<<b)
539 BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(BINARY, shift_right, a>>b)
540 BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(UNARY, invert, ~a)
542 // avoid `'~' on an expression of type bool` warning
543 template <> utree function_impl_invert::eval<bool>(bool const& a)
548 #undef BOOST_SPIRIT_UTREE_CREATE_FUNCTION_BINARY
549 #undef BOOST_SPIRIT_UTREE_CREATE_FUNCTION_UNARY
550 #undef BOOST_SPIRIT_UTREE_CREATE_FUNCTION
551 #undef BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION
552 #undef BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION
553 #undef BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION
555 inline utree operator&&(utree const& a, utree const& b)
557 return utree::visit(a, b, logical_function_and_);
560 inline utree operator||(utree const& a, utree const& b)
562 return utree::visit(a, b, logical_function_or_);
565 inline utree operator!(utree const& a)
567 return utree::visit(a, logical_function_not_);
570 inline utree operator+(utree const& a, utree const& b)
572 utree r = utree::visit(a, b, arithmetic_function_plus);
573 if (r.which() == utree_type::invalid_type)
575 BOOST_THROW_EXCEPTION(bad_type_exception
576 ("addition performed on non-arithmetic utree types",
577 a.which(), b.which()));
582 inline utree operator-(utree const& a, utree const& b)
584 utree r = utree::visit(a, b, arithmetic_function_minus);
585 if (r.which() == utree_type::invalid_type)
587 BOOST_THROW_EXCEPTION(bad_type_exception
588 ("subtraction performed on non-arithmetic utree types",
589 a.which(), b.which()));
594 inline utree operator*(utree const& a, utree const& b)
596 utree r = utree::visit(a, b, arithmetic_function_times);
597 if (r.which() == utree_type::invalid_type)
599 BOOST_THROW_EXCEPTION(bad_type_exception
600 ("multiplication performed on non-arithmetic utree types",
601 a.which(), b.which()));
606 inline utree operator/(utree const& a, utree const& b)
608 utree r = utree::visit(a, b, arithmetic_function_divides);
609 if (r.which() == utree_type::invalid_type)
611 BOOST_THROW_EXCEPTION(bad_type_exception
612 ("division performed on non-arithmetic utree types",
613 a.which(), b.which()));
618 inline utree operator%(utree const& a, utree const& b)
620 utree r = utree::visit(a, b, integral_function_modulus);
621 if (r.which() == utree_type::invalid_type)
623 BOOST_THROW_EXCEPTION(bad_type_exception
624 ("modulos performed on non-integral utree types",
625 a.which(), b.which()));
630 inline utree operator-(utree const& a)
632 utree r = utree::visit(a, arithmetic_function_negate);
633 if (r.which() == utree_type::invalid_type)
635 BOOST_THROW_EXCEPTION(bad_type_exception
636 ("negation performed on non-arithmetic utree type",
642 inline utree operator&(utree const& a, utree const& b)
644 utree r = utree::visit(a, b, integral_function_bitand_);
645 if (r.which() == utree_type::invalid_type)
647 BOOST_THROW_EXCEPTION(bad_type_exception
648 ("bitwise and performed on non-integral utree types",
649 a.which(), b.which()));
654 inline utree operator|(utree const& a, utree const& b)
656 utree r = utree::visit(a, b, integral_function_bitor_);
657 if (r.which() == utree_type::invalid_type)
659 BOOST_THROW_EXCEPTION(bad_type_exception
660 ("bitwise or performed on non-integral utree types",
661 a.which(), b.which()));
666 inline utree operator^(utree const& a, utree const& b)
668 utree r = utree::visit(a, b, integral_function_bitxor_);
669 if (r.which() == utree_type::invalid_type)
671 BOOST_THROW_EXCEPTION(bad_type_exception
672 ("bitwise xor performed on non-integral utree types",
673 a.which(), b.which()));
678 inline utree operator<<(utree const& a, utree const& b)
680 utree r = utree::visit(a, b, integral_function_shift_left);
681 if (r.which() == utree_type::invalid_type)
683 BOOST_THROW_EXCEPTION(bad_type_exception
684 ("left shift performed on non-integral utree types",
685 a.which(), b.which()));
690 inline utree operator>>(utree const& a, utree const& b)
692 utree r = utree::visit(a, b, integral_function_shift_right);
693 if (r.which() == utree_type::invalid_type)
695 BOOST_THROW_EXCEPTION(bad_type_exception
696 ("right shift performed on non-integral utree types",
697 a.which(), b.which()));
702 inline utree operator~(utree const& a)
704 utree r = utree::visit(a, integral_function_invert);
705 if (r.which() == utree_type::invalid_type)
707 BOOST_THROW_EXCEPTION(bad_type_exception
708 ("inversion performed on non-integral utree type",
715 #if defined(BOOST_MSVC)
716 # pragma warning(pop)