| /*============================================================================= |
| Copyright (c) 2001-2011 Joel de Guzman |
| Copyright (c) 2001-2011 Hartmut Kaiser |
| Copyright (c) 2011 Bryce Lelbach |
| |
| Distributed under the Boost Software License, Version 1.0. (See accompanying |
| file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| =============================================================================*/ |
| #if !defined(BOOST_SPIRIT_UTREE_OPERATORS) |
| #define BOOST_SPIRIT_UTREE_OPERATORS |
| |
| #if defined(BOOST_MSVC) |
| # pragma warning(push) |
| # pragma warning(disable: 4804) |
| # pragma warning(disable: 4805) |
| #endif |
| |
| #include <exception> |
| #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO) |
| #include <ios> |
| #include <boost/io/ios_state.hpp> |
| #endif |
| #include <boost/spirit/home/support/utree/utree.hpp> |
| #include <boost/preprocessor/cat.hpp> |
| #include <boost/throw_exception.hpp> |
| #include <boost/type_traits/is_arithmetic.hpp> |
| #include <boost/type_traits/is_integral.hpp> |
| |
| namespace boost { namespace spirit |
| { |
| // Relational operators |
| bool operator==(utree const& a, utree const& b); |
| bool operator<(utree const& a, utree const& b); |
| bool operator!=(utree const& a, utree const& b); |
| bool operator>(utree const& a, utree const& b); |
| bool operator<=(utree const& a, utree const& b); |
| bool operator>=(utree const& a, utree const& b); |
| |
| #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO) |
| // output |
| std::ostream& operator<<(std::ostream& out, utree const& x); |
| std::ostream& operator<<(std::ostream& out, utree::invalid_type const& x); |
| std::ostream& operator<<(std::ostream& out, utree::nil_type const& x); |
| #endif |
| |
| // Logical operators |
| utree operator&&(utree const& a, utree const& b); |
| utree operator||(utree const& a, utree const& b); |
| utree operator!(utree const& a); |
| |
| // Arithmetic operators |
| utree operator+(utree const& a, utree const& b); |
| utree operator-(utree const& a, utree const& b); |
| utree operator*(utree const& a, utree const& b); |
| utree operator/(utree const& a, utree const& b); |
| utree operator%(utree const& a, utree const& b); |
| utree operator-(utree const& a); |
| |
| // Bitwise operators |
| utree operator&(utree const& a, utree const& b); |
| utree operator|(utree const& a, utree const& b); |
| utree operator^(utree const& a, utree const& b); |
| utree operator<<(utree const& a, utree const& b); |
| utree operator>>(utree const& a, utree const& b); |
| utree operator~(utree const& a); |
| |
| // Implementation |
| struct utree_is_equal |
| { |
| typedef bool result_type; |
| |
| template <typename A, typename B> |
| bool dispatch(const A&, const B&, boost::mpl::false_) const |
| { |
| return false; // cannot compare different types by default |
| } |
| |
| template <typename A, typename B> |
| bool dispatch(const A& a, const B& b, boost::mpl::true_) const |
| { |
| return a == b; // for arithmetic types |
| } |
| |
| template <typename A, typename B> |
| bool operator()(const A& a, const B& b) const |
| { |
| return dispatch(a, b, |
| boost::mpl::and_< |
| boost::is_arithmetic<A>, |
| boost::is_arithmetic<B> >()); |
| } |
| |
| template <typename T> |
| bool operator()(const T& a, const T& b) const |
| { |
| // This code works for lists |
| return a == b; |
| } |
| |
| template <typename Base, utree_type::info type_> |
| bool operator()( |
| basic_string<Base, type_> const& a, |
| basic_string<Base, type_> const& b) const |
| { |
| return static_cast<Base const&>(a) == static_cast<Base const&>(b); |
| } |
| |
| bool operator()(utree::invalid_type, utree::invalid_type) const |
| { |
| return true; |
| } |
| |
| bool operator()(utree::nil_type, utree::nil_type) const |
| { |
| return true; |
| } |
| |
| bool operator()(function_base const&, function_base const&) const |
| { |
| return false; // just don't allow comparison of functions |
| } |
| }; |
| |
| struct utree_is_less_than |
| { |
| typedef bool result_type; |
| |
| template <typename A, typename B> |
| bool dispatch(const A&, const B&, boost::mpl::false_) const |
| { |
| return false; // cannot compare different types by default |
| } |
| |
| template <typename A, typename B> |
| bool dispatch(const A& a, const B& b, boost::mpl::true_) const |
| { |
| return a < b; // for arithmetic types |
| } |
| |
| template <typename A, typename B> |
| bool operator()(const A& a, const B& b) const |
| { |
| return dispatch(a, b, |
| boost::mpl::and_< |
| boost::is_arithmetic<A>, |
| boost::is_arithmetic<B> >()); |
| } |
| |
| template <typename T> |
| bool operator()(const T& a, const T& b) const |
| { |
| // This code works for lists |
| return a < b; |
| } |
| |
| template <typename Base, utree_type::info type_> |
| bool operator()( |
| basic_string<Base, type_> const& a, |
| basic_string<Base, type_> const& b) const |
| { |
| return static_cast<Base const&>(a) < static_cast<Base const&>(b); |
| } |
| |
| bool operator()(utree::invalid_type, utree::invalid_type) const |
| { |
| BOOST_THROW_EXCEPTION(bad_type_exception |
| ("no less-than comparison for this utree type", |
| utree_type::invalid_type)); |
| return false; // no less than comparison for nil |
| } |
| |
| bool operator()(utree::nil_type, utree::nil_type) const |
| { |
| BOOST_THROW_EXCEPTION(bad_type_exception |
| ("no less-than comparison for this utree type", |
| utree_type::nil_type)); |
| return false; // no less than comparison for nil |
| } |
| |
| bool operator()(any_ptr const&, any_ptr const&) const |
| { |
| BOOST_THROW_EXCEPTION(bad_type_exception |
| ("no less-than comparison for this utree type", |
| utree_type::any_type)); |
| return false; // no less than comparison for any_ptr |
| } |
| |
| bool operator()(function_base const&, function_base const&) const |
| { |
| BOOST_THROW_EXCEPTION(bad_type_exception |
| ("no less-than comparison for this utree type", |
| utree_type::function_type)); |
| return false; // no less than comparison of functions |
| } |
| }; |
| |
| #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO) |
| struct utree_print |
| { |
| typedef void result_type; |
| |
| std::ostream& out; |
| utree_print(std::ostream& out) : out(out) {} |
| |
| void operator()(utree::invalid_type) const |
| { |
| out << "<invalid> "; |
| } |
| |
| void operator()(utree::nil_type) const |
| { |
| out << "<nil> "; |
| } |
| |
| template <typename T> |
| void operator()(T val) const |
| { |
| out << val << ' '; |
| } |
| |
| void operator()(bool b) const |
| { |
| out << (b ? "true" : "false") << ' '; |
| } |
| |
| void operator()(binary_range_type const& b) const |
| { |
| boost::io::ios_all_saver saver(out); |
| out << "#"; |
| out.width(2); |
| out.fill('0'); |
| |
| typedef binary_range_type::const_iterator iterator; |
| for (iterator i = b.begin(); i != b.end(); ++i) |
| out << std::hex << int((unsigned char)*i); |
| out << "# "; |
| } |
| |
| void operator()(utf8_string_range_type const& str) const |
| { |
| typedef utf8_string_range_type::const_iterator iterator; |
| iterator i = str.begin(); |
| out << '"'; |
| for (; i != str.end(); ++i) |
| out << *i; |
| out << "\" "; |
| } |
| |
| void operator()(utf8_symbol_range_type const& str) const |
| { |
| typedef utf8_symbol_range_type::const_iterator iterator; |
| iterator i = str.begin(); |
| for (; i != str.end(); ++i) |
| out << *i; |
| out << ' '; |
| } |
| |
| template <typename Iterator> |
| void operator()(boost::iterator_range<Iterator> const& range) const |
| { |
| typedef typename boost::iterator_range<Iterator>::const_iterator iterator; |
| (*this)('('); |
| for (iterator i = range.begin(); i != range.end(); ++i) |
| { |
| boost::spirit::utree::visit(*i, *this); |
| } |
| (*this)(')'); |
| } |
| |
| void operator()(any_ptr const&) const |
| { |
| return (*this)("<pointer>"); |
| } |
| |
| void operator()(function_base const&) const |
| { |
| return (*this)("<function>"); |
| } |
| }; |
| #endif |
| |
| template <typename Base> |
| struct logical_function |
| { |
| typedef utree result_type; |
| |
| // We assume anything except false is true |
| |
| // binary |
| template <typename A, typename B> |
| utree operator()(A const& a, B const& b) const |
| { |
| return dispatch(a, b |
| , boost::is_arithmetic<A>() |
| , boost::is_arithmetic<B>()); |
| } |
| |
| // binary |
| template <typename A, typename B> |
| utree dispatch(A const& a, B const& b, mpl::true_, mpl::true_) const |
| { |
| return Base::eval(a, b); // for arithmetic types |
| } |
| |
| // binary |
| template <typename A, typename B> |
| utree dispatch(A const&, B const& b, mpl::false_, mpl::true_) const |
| { |
| return Base::eval(true, b); |
| } |
| |
| // binary |
| template <typename A, typename B> |
| utree dispatch(A const& a, B const&, mpl::true_, mpl::false_) const |
| { |
| return Base::eval(a, true); |
| } |
| |
| // binary |
| template <typename A, typename B> |
| utree dispatch(A const&, B const&, mpl::false_, mpl::false_) const |
| { |
| return Base::eval(true, true); |
| } |
| |
| // unary |
| template <typename A> |
| utree operator()(A const& a) const |
| { |
| return dispatch(a, boost::is_arithmetic<A>()); |
| } |
| |
| // unary |
| template <typename A> |
| utree dispatch(A const& a, mpl::true_) const |
| { |
| return Base::eval(a); |
| } |
| |
| // unary |
| template <typename A> |
| utree dispatch(A const&, mpl::false_) const |
| { |
| return Base::eval(true); |
| } |
| }; |
| |
| template <typename Base> |
| struct arithmetic_function |
| { |
| typedef utree result_type; |
| |
| template <typename A, typename B> |
| utree dispatch(A const&, B const&, boost::mpl::false_) const |
| { |
| return utree(); // cannot apply to non-arithmetic types |
| } |
| |
| template <typename A, typename B> |
| utree dispatch(A const& a, B const& b, boost::mpl::true_) const |
| { |
| return Base::eval(a, b); // for arithmetic types |
| } |
| |
| // binary |
| template <typename A, typename B> |
| utree operator()(A const& a, B const& b) const |
| { |
| return dispatch(a, b, |
| boost::mpl::and_< |
| boost::is_arithmetic<A>, |
| boost::is_arithmetic<B> >()); |
| } |
| |
| template <typename A> |
| utree dispatch(A const&, boost::mpl::false_) const |
| { |
| return utree(); // cannot apply to non-arithmetic types |
| } |
| |
| template <typename A> |
| utree dispatch(A const& a, boost::mpl::true_) const |
| { |
| return Base::eval(a); // for arithmetic types |
| } |
| |
| // unary |
| template <typename A> |
| utree operator()(A const& a) const |
| { |
| return dispatch(a, boost::is_arithmetic<A>()); |
| } |
| }; |
| |
| template <typename Base> |
| struct integral_function |
| { |
| typedef utree result_type; |
| |
| template <typename A, typename B> |
| utree dispatch(A const&, B const&, boost::mpl::false_) const |
| { |
| return utree(); // cannot apply to non-integral types |
| } |
| |
| template <typename A, typename B> |
| utree dispatch(A const& a, B const& b, boost::mpl::true_) const |
| { |
| return Base::eval(a, b); // for integral types |
| } |
| |
| // binary |
| template <typename A, typename B> |
| utree operator()(A const& a, B const& b) const |
| { |
| return dispatch(a, b, |
| boost::mpl::and_< |
| boost::is_integral<A>, |
| boost::is_integral<B> >()); |
| } |
| |
| template <typename A> |
| utree dispatch(A const&, boost::mpl::false_) const |
| { |
| return utree(); // cannot apply to non-integral types |
| } |
| |
| template <typename A> |
| utree dispatch(A const& a, boost::mpl::true_) const |
| { |
| return Base::eval(a); // for integral types |
| } |
| |
| // unary |
| template <typename A> |
| utree operator()(A const& a) const |
| { |
| return dispatch(a, boost::is_integral<A>()); |
| } |
| }; |
| |
| #define BOOST_SPIRIT_UTREE_CREATE_FUNCTION(name, expr, base) \ |
| struct BOOST_PP_CAT(function_impl_, name) \ |
| { \ |
| template <typename A, typename B> \ |
| static utree eval(A const& a, B const& b) \ |
| { \ |
| return utree(expr); \ |
| } \ |
| template <typename A> \ |
| static utree eval(A const& a) \ |
| { \ |
| static int b; \ |
| (void) b; \ |
| return utree(expr); \ |
| } \ |
| }; \ |
| base<BOOST_PP_CAT(function_impl_, name)> const \ |
| BOOST_PP_CAT(base, BOOST_PP_CAT(_, name)) = {}; \ |
| /***/ |
| |
| #define BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(name, expr) \ |
| BOOST_SPIRIT_UTREE_CREATE_FUNCTION(name, expr, arithmetic_function) \ |
| /***/ |
| |
| #define BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(name, expr) \ |
| BOOST_SPIRIT_UTREE_CREATE_FUNCTION(name, expr, integral_function) \ |
| /***/ |
| |
| #define BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(name, expr) \ |
| BOOST_SPIRIT_UTREE_CREATE_FUNCTION(name, expr, logical_function) \ |
| /***/ |
| |
| inline bool operator==(utree const& a, utree const& b) |
| { |
| return utree::visit(a, b, utree_is_equal()); |
| } |
| |
| inline bool operator<(utree const& a, utree const& b) |
| { |
| return utree::visit(a, b, utree_is_less_than()); |
| } |
| |
| inline bool operator!=(utree const& a, utree const& b) |
| { |
| return !(a == b); |
| } |
| |
| inline bool operator>(utree const& a, utree const& b) |
| { |
| return b < a; |
| } |
| |
| inline bool operator<=(utree const& a, utree const& b) |
| { |
| return !(b < a); |
| } |
| |
| inline bool operator>=(utree const& a, utree const& b) |
| { |
| return !(a < b); |
| } |
| |
| #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO) |
| inline std::ostream& operator<<(std::ostream& out, utree const& x) |
| { |
| utree::visit(x, utree_print(out)); |
| return out; |
| } |
| |
| inline std::ostream& operator<<(std::ostream& out, utree::invalid_type const&) |
| { |
| return out; |
| } |
| |
| inline std::ostream& operator<<(std::ostream& out, utree::nil_type const&) |
| { |
| return out; |
| } |
| #endif |
| |
| BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(and_, a&&b) |
| BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(or_, a||b) |
| BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(not_, !a) |
| |
| BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(plus, a+b) |
| BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(minus, a-b) |
| BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(times, a*b) |
| BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(divides, a/b) |
| BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(modulus, a%b) |
| BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(negate, -a) |
| |
| BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(bitand_, a&b) |
| BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(bitor_, a|b) |
| BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(bitxor_, a^b) |
| BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(shift_left, a<<b) |
| BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(shift_right, a>>b) |
| BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(invert, ~a) |
| |
| inline utree operator&&(utree const& a, utree const& b) |
| { |
| return utree::visit(a, b, logical_function_and_); |
| } |
| |
| inline utree operator||(utree const& a, utree const& b) |
| { |
| return utree::visit(a, b, logical_function_or_); |
| } |
| |
| inline utree operator!(utree const& a) |
| { |
| return utree::visit(a, logical_function_not_); |
| } |
| |
| inline utree operator+(utree const& a, utree const& b) |
| { |
| utree r = utree::visit(a, b, arithmetic_function_plus); |
| if (r.which() == utree_type::invalid_type) |
| { |
| BOOST_THROW_EXCEPTION(bad_type_exception |
| ("addition performed on non-arithmetic utree types", |
| a.which(), b.which())); |
| } |
| return r; |
| } |
| |
| inline utree operator-(utree const& a, utree const& b) |
| { |
| utree r = utree::visit(a, b, arithmetic_function_minus); |
| if (r.which() == utree_type::invalid_type) |
| { |
| BOOST_THROW_EXCEPTION(bad_type_exception |
| ("subtraction performed on non-arithmetic utree types", |
| a.which(), b.which())); |
| } |
| return r; |
| } |
| |
| inline utree operator*(utree const& a, utree const& b) |
| { |
| utree r = utree::visit(a, b, arithmetic_function_times); |
| if (r.which() == utree_type::invalid_type) |
| { |
| BOOST_THROW_EXCEPTION(bad_type_exception |
| ("multiplication performed on non-arithmetic utree types", |
| a.which(), b.which())); |
| } |
| return r; |
| } |
| |
| inline utree operator/(utree const& a, utree const& b) |
| { |
| utree r = utree::visit(a, b, arithmetic_function_divides); |
| if (r.which() == utree_type::invalid_type) |
| { |
| BOOST_THROW_EXCEPTION(bad_type_exception |
| ("division performed on non-arithmetic utree types", |
| a.which(), b.which())); |
| } |
| return r; |
| } |
| |
| inline utree operator%(utree const& a, utree const& b) |
| { |
| utree r = utree::visit(a, b, integral_function_modulus); |
| if (r.which() == utree_type::invalid_type) |
| { |
| BOOST_THROW_EXCEPTION(bad_type_exception |
| ("modulos performed on non-integral utree types", |
| a.which(), b.which())); |
| } |
| return r; |
| } |
| |
| inline utree operator-(utree const& a) |
| { |
| utree r = utree::visit(a, arithmetic_function_negate); |
| if (r.which() == utree_type::invalid_type) |
| { |
| BOOST_THROW_EXCEPTION(bad_type_exception |
| ("negation performed on non-arithmetic utree type", |
| a.which())); |
| } |
| return r; |
| } |
| |
| inline utree operator&(utree const& a, utree const& b) |
| { |
| utree r = utree::visit(a, b, integral_function_bitand_); |
| if (r.which() == utree_type::invalid_type) |
| { |
| BOOST_THROW_EXCEPTION(bad_type_exception |
| ("bitwise and performed on non-integral utree types", |
| a.which(), b.which())); |
| } |
| return r; |
| } |
| |
| inline utree operator|(utree const& a, utree const& b) |
| { |
| utree r = utree::visit(a, b, integral_function_bitor_); |
| if (r.which() == utree_type::invalid_type) |
| { |
| BOOST_THROW_EXCEPTION(bad_type_exception |
| ("bitwise or performed on non-integral utree types", |
| a.which(), b.which())); |
| } |
| return r; |
| } |
| |
| inline utree operator^(utree const& a, utree const& b) |
| { |
| utree r = utree::visit(a, b, integral_function_bitxor_); |
| if (r.which() == utree_type::invalid_type) |
| { |
| BOOST_THROW_EXCEPTION(bad_type_exception |
| ("bitwise xor performed on non-integral utree types", |
| a.which(), b.which())); |
| } |
| return r; |
| } |
| |
| inline utree operator<<(utree const& a, utree const& b) |
| { |
| utree r = utree::visit(a, b, integral_function_shift_left); |
| if (r.which() == utree_type::invalid_type) |
| { |
| BOOST_THROW_EXCEPTION(bad_type_exception |
| ("left shift performed on non-integral utree types", |
| a.which(), b.which())); |
| } |
| return r; |
| } |
| |
| inline utree operator>>(utree const& a, utree const& b) |
| { |
| utree r = utree::visit(a, b, integral_function_shift_right); |
| if (r.which() == utree_type::invalid_type) |
| { |
| BOOST_THROW_EXCEPTION(bad_type_exception |
| ("right shift performed on non-integral utree types", |
| a.which(), b.which())); |
| } |
| return r; |
| } |
| |
| inline utree operator~(utree const& a) |
| { |
| utree r = utree::visit(a, integral_function_invert); |
| if (r.which() == utree_type::invalid_type) |
| { |
| BOOST_THROW_EXCEPTION(bad_type_exception |
| ("inversion performed on non-integral utree type", |
| a.which())); |
| } |
| return r; |
| } |
| }} |
| |
| #if defined(BOOST_MSVC) |
| # pragma warning(pop) |
| #endif |
| |
| #endif |