/*============================================================================= Copyright (c) 2001-2010 Joel de Guzman 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 #include #include #include #include #if defined(BOOST_MSVC) # pragma warning(push) # pragma warning(disable: 4804) # pragma warning(disable: 4805) #endif #include #include #include #include #include namespace scheme { struct utree_exception : std::exception {}; struct illegal_arithmetic_operation : utree_exception { virtual const char* what() const throw() { return "utree: Illegal arithmetic operation."; } }; struct illegal_integral_operation : utree_exception { virtual const char* what() const throw() { return "utree: Illegal integral operation."; } }; // 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); // Input and output std::ostream& operator<<(std::ostream& out, utree const& x); std::istream& operator>>(std::istream& in, utree& x); std::ostream& operator<<(std::ostream& out, nil const& x); // 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 bool dispatch(const A&, const B&, boost::mpl::false_) const { return false; // cannot compare different types by default } template bool dispatch(const A& a, const B& b, boost::mpl::true_) const { return a == b; // for arithmetic types } template bool operator()(const A& a, const B& b) const { return dispatch(a, b, boost::mpl::and_< boost::is_arithmetic, boost::is_arithmetic >()); } template bool operator()(const T& a, const T& b) const { // This code works for lists return a == b; } template bool operator()( basic_string const& a, basic_string const& b) const { return static_cast(a) == static_cast(b); } bool operator()(nil, nil) const { return true; } bool operator()(function_base const& a, function_base const& b) const { return false; // just don't allow comparison of functions } }; struct utree_is_less_than { typedef bool result_type; template bool dispatch(const A&, const B&, boost::mpl::false_) const { return false; // cannot compare different types by default } template bool dispatch(const A& a, const B& b, boost::mpl::true_) const { return a < b; // for arithmetic types } template bool operator()(const A& a, const B& b) const { return dispatch(a, b, boost::mpl::and_< boost::is_arithmetic, boost::is_arithmetic >()); } template bool operator()(const T& a, const T& b) const { // This code works for lists return a < b; } template bool operator()( basic_string const& a, basic_string const& b) const { return static_cast(a) < static_cast(b); } bool operator()(nil, nil) const { BOOST_ASSERT(false); return false; // no less than comparison for nil } bool operator()(any_ptr const& a, any_ptr const& b) const { BOOST_ASSERT(false); return false; // no less than comparison for any_ptr } bool operator()(function_base const& a, function_base const& b) const { BOOST_ASSERT(false); return false; // no less than comparison of functions } }; #if !defined(SCHEME_USE_SPIRIT_IO) struct utree_print { typedef void result_type; std::ostream& out; utree_print(std::ostream& out) : out(out) {} void operator()(scheme::nil) const { out << " "; } template void operator()(T val) const { out << val << ' '; } void operator()(bool b) const { out << (b ? "true" : "false") << ' '; } void operator()(binary_range const& b) const { out << "#"; out.width(2); out.fill('0'); typedef binary_range::const_iterator iterator; for (iterator i = b.begin(); i != b.end(); ++i) out << std::hex << int((unsigned char)*i); out << std::dec << "# "; } void operator()(utf8_string_range const& str) const { typedef utf8_string_range::const_iterator iterator; iterator i = str.begin(); out << '"'; for (; i != str.end(); ++i) out << *i; out << "\" "; } void operator()(utf8_symbol_range const& str) const { typedef utf8_symbol_range::const_iterator iterator; iterator i = str.begin(); for (; i != str.end(); ++i) out << *i; } template void operator()(boost::iterator_range const& range) const { typedef typename boost::iterator_range::const_iterator iterator; (*this)('('); for (iterator i = range.begin(); i != range.end(); ++i) { scheme::utree::visit(*i, *this); } (*this)(')'); } void operator()(any_ptr const& p) const { return (*this)(""); } void operator()(function_base const& pf) const { return (*this)(""); } }; #endif template struct logical_function { typedef utree result_type; // In scheme, anything except false is true // binary utree operator()(bool a, bool b) const { return Base::eval(a, b); // for boolean types } // binary template utree operator()(A const& a, bool b) const { return Base::eval(true, b); } // binary template utree operator()(bool a, B const& b) const { return Base::eval(a, true); } // binary template utree operator()(A const& a, B const& b) const { return Base::eval(true, true); } // unary utree operator()(bool a) const { return Base::eval(a); } // unary template utree operator()(A const& a) const { return Base::eval(true); } }; template struct arithmetic_function { typedef utree result_type; template utree dispatch(A const&, B const&, boost::mpl::false_) const { throw illegal_arithmetic_operation(); return utree(); // cannot apply to non-arithmetic types } template utree dispatch(A const& a, B const& b, boost::mpl::true_) const { return Base::eval(a, b); // for arithmetic types } // binary template utree operator()(A const& a, B const& b) const { return dispatch(a, b, boost::mpl::and_< boost::is_arithmetic, boost::is_arithmetic >()); } template utree dispatch(A const&, boost::mpl::false_) const { throw illegal_arithmetic_operation(); return utree(); // cannot apply to non-arithmetic types } template utree dispatch(A const& a, boost::mpl::true_) const { return Base::eval(a); // for arithmetic types } // unary template utree operator()(A const& a) const { return dispatch(a, boost::is_arithmetic()); } }; template struct integral_function { typedef utree result_type; template utree dispatch(A const&, B const&, boost::mpl::false_) const { throw illegal_integral_operation(); return utree(); // cannot apply to non-integral types } template utree dispatch(A const& a, B const& b, boost::mpl::true_) const { return Base::eval(a, b); // for integral types } // binary template utree operator()(A const& a, B const& b) const { return dispatch(a, b, boost::mpl::and_< boost::is_integral, boost::is_integral >()); } template utree dispatch(A const&, boost::mpl::false_) const { throw illegal_integral_operation(); return utree(); // cannot apply to non-integral types } template utree dispatch(A const& a, boost::mpl::true_) const { return Base::eval(a); // for integral types } // unary template utree operator()(A const& a) const { return dispatch(a, boost::is_integral()); } }; #define SCHEME_CREATE_FUNCTION(name, expr, base) \ struct BOOST_PP_CAT(function_impl_, name) \ { \ template \ static utree eval(A const& a, B const& b) \ { \ return utree(expr); \ } \ template \ static utree eval(A const& a) \ { \ static int b; \ (void) b; \ return utree(expr); \ } \ }; \ base const \ BOOST_PP_CAT(base, BOOST_PP_CAT(_, name)) = {}; \ /***/ #define SCHEME_CREATE_ARITHMETIC_FUNCTION(name, expr) \ SCHEME_CREATE_FUNCTION(name, expr, arithmetic_function) \ /***/ #define SCHEME_CREATE_INTEGRAL_FUNCTION(name, expr) \ SCHEME_CREATE_FUNCTION(name, expr, integral_function) \ /***/ #define SCHEME_CREATE_LOGICAL_FUNCTION(name, expr) \ SCHEME_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(SCHEME_USE_SPIRIT_IO) inline std::ostream& operator<<(std::ostream& out, utree const& x) { utree::visit(x, utree_print(out)); return out; } #endif inline std::ostream& operator<<(std::ostream& out, nil const& x) { return out; } SCHEME_CREATE_LOGICAL_FUNCTION(and_, a&&b); SCHEME_CREATE_LOGICAL_FUNCTION(or_, a||b); SCHEME_CREATE_LOGICAL_FUNCTION(not_, !a); SCHEME_CREATE_ARITHMETIC_FUNCTION(plus, a+b); SCHEME_CREATE_ARITHMETIC_FUNCTION(minus, a-b); SCHEME_CREATE_ARITHMETIC_FUNCTION(times, a*b); SCHEME_CREATE_ARITHMETIC_FUNCTION(divides, a/b); SCHEME_CREATE_INTEGRAL_FUNCTION(modulus, a%b); SCHEME_CREATE_ARITHMETIC_FUNCTION(negate, -a); SCHEME_CREATE_INTEGRAL_FUNCTION(bitand_, a&b); SCHEME_CREATE_INTEGRAL_FUNCTION(bitor_, a|b); SCHEME_CREATE_INTEGRAL_FUNCTION(bitxor_, a^b); SCHEME_CREATE_INTEGRAL_FUNCTION(shift_left, a<>b); SCHEME_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) { return utree::visit(a, b, arithmetic_function_plus); } inline utree operator-(utree const& a, utree const& b) { return utree::visit(a, b, arithmetic_function_minus); } inline utree operator*(utree const& a, utree const& b) { return utree::visit(a, b, arithmetic_function_times); } inline utree operator/(utree const& a, utree const& b) { return utree::visit(a, b, arithmetic_function_divides); } inline utree operator%(utree const& a, utree const& b) { return utree::visit(a, b, integral_function_modulus); } inline utree operator-(utree const& a) { return utree::visit(a, arithmetic_function_negate); } inline utree operator&(utree const& a, utree const& b) { return utree::visit(a, b, integral_function_bitand_); } inline utree operator|(utree const& a, utree const& b) { return utree::visit(a, b, integral_function_bitor_); } inline utree operator^(utree const& a, utree const& b) { return utree::visit(a, b, integral_function_bitxor_); } inline utree operator<<(utree const& a, utree const& b) { return utree::visit(a, b, integral_function_shift_left); } inline utree operator>>(utree const& a, utree const& b) { return utree::visit(a, b, integral_function_shift_right); } inline utree operator~(utree const& a) { return utree::visit(a, integral_function_invert); } } #if defined(BOOST_MSVC) # pragma warning(pop) #endif #endif