File indexing completed on 2025-01-19 09:47:52
0001
0002
0003
0004
0005
0006
0007
0008
0009 #if !defined(BOOST_SPIRIT_UTREE_OPERATORS)
0010 #define BOOST_SPIRIT_UTREE_OPERATORS
0011
0012 #if defined(BOOST_MSVC)
0013 # pragma warning(push)
0014 # pragma warning(disable: 4804)
0015 # pragma warning(disable: 4805)
0016 #endif
0017
0018 #include <exception>
0019 #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO)
0020 #include <ios>
0021 #include <boost/io/ios_state.hpp>
0022 #endif
0023 #include <boost/spirit/home/support/utree/utree.hpp>
0024 #include <boost/preprocessor/cat.hpp>
0025 #include <boost/throw_exception.hpp>
0026 #include <boost/type_traits/is_arithmetic.hpp>
0027 #include <boost/type_traits/is_integral.hpp>
0028
0029 namespace boost { namespace spirit
0030 {
0031
0032 bool operator==(utree const& a, utree const& b);
0033 bool operator<(utree const& a, utree const& b);
0034 bool operator!=(utree const& a, utree const& b);
0035 bool operator>(utree const& a, utree const& b);
0036 bool operator<=(utree const& a, utree const& b);
0037 bool operator>=(utree const& a, utree const& b);
0038
0039 #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO)
0040
0041 std::ostream& operator<<(std::ostream& out, utree const& x);
0042 std::ostream& operator<<(std::ostream& out, utree::invalid_type const& x);
0043 std::ostream& operator<<(std::ostream& out, utree::nil_type const& x);
0044 #endif
0045
0046
0047 utree operator&&(utree const& a, utree const& b);
0048 utree operator||(utree const& a, utree const& b);
0049 utree operator!(utree const& a);
0050
0051
0052 utree operator+(utree const& a, utree const& b);
0053 utree operator-(utree const& a, utree const& b);
0054 utree operator*(utree const& a, utree const& b);
0055 utree operator/(utree const& a, utree const& b);
0056 utree operator%(utree const& a, utree const& b);
0057 utree operator-(utree const& a);
0058
0059
0060 utree operator&(utree const& a, utree const& b);
0061 utree operator|(utree const& a, utree const& b);
0062 utree operator^(utree const& a, utree const& b);
0063 utree operator<<(utree const& a, utree const& b);
0064 utree operator>>(utree const& a, utree const& b);
0065 utree operator~(utree const& a);
0066
0067
0068 struct utree_is_equal
0069 {
0070 typedef bool result_type;
0071
0072 template <typename A, typename B>
0073 bool dispatch(const A&, const B&, boost::mpl::false_) const
0074 {
0075 return false;
0076 }
0077
0078 template <typename A, typename B>
0079 bool dispatch(const A& a, const B& b, boost::mpl::true_) const
0080 {
0081 return a == b;
0082 }
0083
0084 template <typename A, typename B>
0085 bool operator()(const A& a, const B& b) const
0086 {
0087 return dispatch(a, b,
0088 boost::mpl::and_<
0089 boost::is_arithmetic<A>,
0090 boost::is_arithmetic<B> >());
0091 }
0092
0093 template <typename T>
0094 bool operator()(const T& a, const T& b) const
0095 {
0096
0097 return a == b;
0098 }
0099
0100 template <typename Base, utree_type::info type_>
0101 bool operator()(
0102 basic_string<Base, type_> const& a,
0103 basic_string<Base, type_> const& b) const
0104 {
0105 return static_cast<Base const&>(a) == static_cast<Base const&>(b);
0106 }
0107
0108 bool operator()(utree::invalid_type, utree::invalid_type) const
0109 {
0110 return true;
0111 }
0112
0113 bool operator()(utree::nil_type, utree::nil_type) const
0114 {
0115 return true;
0116 }
0117
0118 bool operator()(function_base const&, function_base const&) const
0119 {
0120 return false;
0121 }
0122 };
0123
0124 struct utree_is_less_than
0125 {
0126 typedef bool result_type;
0127
0128 template <typename A, typename B>
0129 bool dispatch(const A&, const B&, boost::mpl::false_) const
0130 {
0131 return false;
0132 }
0133
0134 template <typename A, typename B>
0135 bool dispatch(const A& a, const B& b, boost::mpl::true_) const
0136 {
0137 return a < b;
0138 }
0139
0140 template <typename A, typename B>
0141 bool operator()(const A& a, const B& b) const
0142 {
0143 return dispatch(a, b,
0144 boost::mpl::and_<
0145 boost::is_arithmetic<A>,
0146 boost::is_arithmetic<B> >());
0147 }
0148
0149 template <typename T>
0150 bool operator()(const T& a, const T& b) const
0151 {
0152
0153 return a < b;
0154 }
0155
0156 template <typename Base, utree_type::info type_>
0157 bool operator()(
0158 basic_string<Base, type_> const& a,
0159 basic_string<Base, type_> const& b) const
0160 {
0161 return static_cast<Base const&>(a) < static_cast<Base const&>(b);
0162 }
0163
0164 bool operator()(utree::invalid_type, utree::invalid_type) const
0165 {
0166 BOOST_THROW_EXCEPTION(bad_type_exception
0167 ("no less-than comparison for this utree type",
0168 utree_type::invalid_type));
0169 BOOST_UNREACHABLE_RETURN(false)
0170 }
0171
0172 bool operator()(utree::nil_type, utree::nil_type) const
0173 {
0174 BOOST_THROW_EXCEPTION(bad_type_exception
0175 ("no less-than comparison for this utree type",
0176 utree_type::nil_type));
0177 BOOST_UNREACHABLE_RETURN(false)
0178 }
0179
0180 bool operator()(any_ptr const&, any_ptr const&) const
0181 {
0182 BOOST_THROW_EXCEPTION(bad_type_exception
0183 ("no less-than comparison for this utree type",
0184 utree_type::any_type));
0185 BOOST_UNREACHABLE_RETURN(false)
0186 }
0187
0188 bool operator()(function_base const&, function_base const&) const
0189 {
0190 BOOST_THROW_EXCEPTION(bad_type_exception
0191 ("no less-than comparison for this utree type",
0192 utree_type::function_type));
0193 BOOST_UNREACHABLE_RETURN(false)
0194 }
0195 };
0196
0197 #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO)
0198 struct utree_print
0199 {
0200 typedef void result_type;
0201
0202 std::ostream& out;
0203 utree_print(std::ostream& out) : out(out) {}
0204
0205 void operator()(utree::invalid_type) const
0206 {
0207 out << "<invalid> ";
0208 }
0209
0210 void operator()(utree::nil_type) const
0211 {
0212 out << "<nil> ";
0213 }
0214
0215 template <typename T>
0216 void operator()(T val) const
0217 {
0218 out << val << ' ';
0219 }
0220
0221 void operator()(bool b) const
0222 {
0223 out << (b ? "true" : "false") << ' ';
0224 }
0225
0226 void operator()(binary_range_type const& b) const
0227 {
0228 boost::io::ios_all_saver saver(out);
0229 out << "#";
0230 out.width(2);
0231 out.fill('0');
0232
0233 typedef binary_range_type::const_iterator iterator;
0234 for (iterator i = b.begin(); i != b.end(); ++i)
0235 out << std::hex << int((unsigned char)*i);
0236 out << "# ";
0237 }
0238
0239 void operator()(utf8_string_range_type const& str) const
0240 {
0241 typedef utf8_string_range_type::const_iterator iterator;
0242 iterator i = str.begin();
0243 out << '"';
0244 for (; i != str.end(); ++i)
0245 out << *i;
0246 out << "\" ";
0247 }
0248
0249 void operator()(utf8_symbol_range_type const& str) const
0250 {
0251 typedef utf8_symbol_range_type::const_iterator iterator;
0252 iterator i = str.begin();
0253 for (; i != str.end(); ++i)
0254 out << *i;
0255 out << ' ';
0256 }
0257
0258 template <typename Iterator>
0259 void operator()(boost::iterator_range<Iterator> const& range) const
0260 {
0261 typedef typename boost::iterator_range<Iterator>::const_iterator iterator;
0262 (*this)('(');
0263 for (iterator i = range.begin(); i != range.end(); ++i)
0264 {
0265 boost::spirit::utree::visit(*i, *this);
0266 }
0267 (*this)(')');
0268 }
0269
0270 void operator()(any_ptr const&) const
0271 {
0272 return (*this)("<pointer>");
0273 }
0274
0275 void operator()(function_base const&) const
0276 {
0277 return (*this)("<function>");
0278 }
0279 };
0280 #endif
0281
0282 template <typename Base>
0283 struct logical_function
0284 {
0285 typedef utree result_type;
0286
0287
0288
0289
0290 template <typename A, typename B>
0291 utree operator()(A const& a, B const& b) const
0292 {
0293 return dispatch(a, b
0294 , boost::is_arithmetic<A>()
0295 , boost::is_arithmetic<B>());
0296 }
0297
0298
0299 template <typename A, typename B>
0300 utree dispatch(A const& a, B const& b, mpl::true_, mpl::true_) const
0301 {
0302 return Base::eval(a, b);
0303 }
0304
0305
0306 template <typename A, typename B>
0307 utree dispatch(A const&, B const& b, mpl::false_, mpl::true_) const
0308 {
0309 return Base::eval(true, b);
0310 }
0311
0312
0313 template <typename A, typename B>
0314 utree dispatch(A const& a, B const&, mpl::true_, mpl::false_) const
0315 {
0316 return Base::eval(a, true);
0317 }
0318
0319
0320 template <typename A, typename B>
0321 utree dispatch(A const&, B const&, mpl::false_, mpl::false_) const
0322 {
0323 return Base::eval(true, true);
0324 }
0325
0326
0327 template <typename A>
0328 utree operator()(A const& a) const
0329 {
0330 return dispatch(a, boost::is_arithmetic<A>());
0331 }
0332
0333
0334 template <typename A>
0335 utree dispatch(A const& a, mpl::true_) const
0336 {
0337 return Base::eval(a);
0338 }
0339
0340
0341 template <typename A>
0342 utree dispatch(A const&, mpl::false_) const
0343 {
0344 return Base::eval(true);
0345 }
0346 };
0347
0348 template <typename Base>
0349 struct arithmetic_function
0350 {
0351 typedef utree result_type;
0352
0353 template <typename A, typename B>
0354 utree dispatch(A const&, B const&, boost::mpl::false_) const
0355 {
0356 return utree();
0357 }
0358
0359 template <typename A, typename B>
0360 utree dispatch(A const& a, B const& b, boost::mpl::true_) const
0361 {
0362 return Base::eval(a, b);
0363 }
0364
0365
0366 template <typename A, typename B>
0367 utree operator()(A const& a, B const& b) const
0368 {
0369 return dispatch(a, b,
0370 boost::mpl::and_<
0371 boost::is_arithmetic<A>,
0372 boost::is_arithmetic<B> >());
0373 }
0374
0375 template <typename A>
0376 utree dispatch(A const&, boost::mpl::false_) const
0377 {
0378 return utree();
0379 }
0380
0381 template <typename A>
0382 utree dispatch(A const& a, boost::mpl::true_) const
0383 {
0384 return Base::eval(a);
0385 }
0386
0387
0388 template <typename A>
0389 utree operator()(A const& a) const
0390 {
0391 return dispatch(a, boost::is_arithmetic<A>());
0392 }
0393 };
0394
0395 template <typename Base>
0396 struct integral_function
0397 {
0398 typedef utree result_type;
0399
0400 template <typename A, typename B>
0401 utree dispatch(A const&, B const&, boost::mpl::false_) const
0402 {
0403 return utree();
0404 }
0405
0406 template <typename A, typename B>
0407 utree dispatch(A const& a, B const& b, boost::mpl::true_) const
0408 {
0409 return Base::eval(a, b);
0410 }
0411
0412
0413 template <typename A, typename B>
0414 utree operator()(A const& a, B const& b) const
0415 {
0416 return dispatch(a, b,
0417 boost::mpl::and_<
0418 boost::is_integral<A>,
0419 boost::is_integral<B> >());
0420 }
0421
0422 template <typename A>
0423 utree dispatch(A const&, boost::mpl::false_) const
0424 {
0425 return utree();
0426 }
0427
0428 template <typename A>
0429 utree dispatch(A const& a, boost::mpl::true_) const
0430 {
0431 return Base::eval(a);
0432 }
0433
0434
0435 template <typename A>
0436 utree operator()(A const& a) const
0437 {
0438 return dispatch(a, boost::is_integral<A>());
0439 }
0440 };
0441
0442 #define BOOST_SPIRIT_UTREE_CREATE_FUNCTION_BINARY \
0443 template <typename Lhs, typename Rhs> \
0444 static utree eval(Lhs const& a, Rhs const& b) \
0445
0446
0447 #define BOOST_SPIRIT_UTREE_CREATE_FUNCTION_UNARY \
0448 template <typename Operand> \
0449 static utree eval(Operand const& a) \
0450
0451
0452 #define BOOST_SPIRIT_UTREE_CREATE_FUNCTION(arity, name, expr, base) \
0453 struct BOOST_PP_CAT(function_impl_, name) \
0454 { \
0455 BOOST_SPIRIT_UTREE_CREATE_FUNCTION_##arity \
0456 { \
0457 return utree(expr); \
0458 } \
0459 }; \
0460 base<BOOST_PP_CAT(function_impl_, name)> const \
0461 BOOST_PP_CAT(base, BOOST_PP_CAT(_, name)) = {}; \
0462
0463
0464 #define BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(arity, name, expr) \
0465 BOOST_SPIRIT_UTREE_CREATE_FUNCTION(arity, name, expr, arithmetic_function)\
0466
0467
0468 #define BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(arity, name, expr) \
0469 BOOST_SPIRIT_UTREE_CREATE_FUNCTION(arity, name, expr, integral_function) \
0470
0471
0472 #define BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(arity, name, expr) \
0473 BOOST_SPIRIT_UTREE_CREATE_FUNCTION(arity, name, expr, logical_function) \
0474
0475
0476 inline bool operator==(utree const& a, utree const& b)
0477 {
0478 return utree::visit(a, b, utree_is_equal());
0479 }
0480
0481 inline bool operator<(utree const& a, utree const& b)
0482 {
0483 return utree::visit(a, b, utree_is_less_than());
0484 }
0485
0486 inline bool operator!=(utree const& a, utree const& b)
0487 {
0488 return !(a == b);
0489 }
0490
0491 inline bool operator>(utree const& a, utree const& b)
0492 {
0493 return b < a;
0494 }
0495
0496 inline bool operator<=(utree const& a, utree const& b)
0497 {
0498 return !(b < a);
0499 }
0500
0501 inline bool operator>=(utree const& a, utree const& b)
0502 {
0503 return !(a < b);
0504 }
0505
0506 #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO)
0507 inline std::ostream& operator<<(std::ostream& out, utree const& x)
0508 {
0509 utree::visit(x, utree_print(out));
0510 return out;
0511 }
0512
0513 inline std::ostream& operator<<(std::ostream& out, utree::invalid_type const&)
0514 {
0515 return out;
0516 }
0517
0518 inline std::ostream& operator<<(std::ostream& out, utree::nil_type const&)
0519 {
0520 return out;
0521 }
0522 #endif
0523
0524 BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(BINARY, and_, a&&b)
0525 BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(BINARY, or_, a||b)
0526 BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(UNARY, not_, !a)
0527
0528 BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(BINARY, plus, a+b)
0529 BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(BINARY, minus, a-b)
0530 BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(BINARY, times, a*b)
0531 BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(BINARY, divides, a/b)
0532 BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION (BINARY, modulus, a%b)
0533 BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(UNARY, negate, -a)
0534
0535 BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(BINARY, bitand_, a&b)
0536 BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(BINARY, bitor_, a|b)
0537 BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(BINARY, bitxor_, a^b)
0538 BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(BINARY, shift_left, a<<b)
0539 BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(BINARY, shift_right, a>>b)
0540 BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(UNARY, invert, ~a)
0541
0542
0543 template <> inline utree function_impl_invert::eval<bool>(bool const& a)
0544 {
0545 return utree(!a);
0546 }
0547
0548 #undef BOOST_SPIRIT_UTREE_CREATE_FUNCTION_BINARY
0549 #undef BOOST_SPIRIT_UTREE_CREATE_FUNCTION_UNARY
0550 #undef BOOST_SPIRIT_UTREE_CREATE_FUNCTION
0551 #undef BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION
0552 #undef BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION
0553 #undef BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION
0554
0555 inline utree operator&&(utree const& a, utree const& b)
0556 {
0557 return utree::visit(a, b, logical_function_and_);
0558 }
0559
0560 inline utree operator||(utree const& a, utree const& b)
0561 {
0562 return utree::visit(a, b, logical_function_or_);
0563 }
0564
0565 inline utree operator!(utree const& a)
0566 {
0567 return utree::visit(a, logical_function_not_);
0568 }
0569
0570 inline utree operator+(utree const& a, utree const& b)
0571 {
0572 utree r = utree::visit(a, b, arithmetic_function_plus);
0573 if (r.which() == utree_type::invalid_type)
0574 {
0575 BOOST_THROW_EXCEPTION(bad_type_exception
0576 ("addition performed on non-arithmetic utree types",
0577 a.which(), b.which()));
0578 }
0579 return r;
0580 }
0581
0582 inline utree operator-(utree const& a, utree const& b)
0583 {
0584 utree r = utree::visit(a, b, arithmetic_function_minus);
0585 if (r.which() == utree_type::invalid_type)
0586 {
0587 BOOST_THROW_EXCEPTION(bad_type_exception
0588 ("subtraction performed on non-arithmetic utree types",
0589 a.which(), b.which()));
0590 }
0591 return r;
0592 }
0593
0594 inline utree operator*(utree const& a, utree const& b)
0595 {
0596 utree r = utree::visit(a, b, arithmetic_function_times);
0597 if (r.which() == utree_type::invalid_type)
0598 {
0599 BOOST_THROW_EXCEPTION(bad_type_exception
0600 ("multiplication performed on non-arithmetic utree types",
0601 a.which(), b.which()));
0602 }
0603 return r;
0604 }
0605
0606 inline utree operator/(utree const& a, utree const& b)
0607 {
0608 utree r = utree::visit(a, b, arithmetic_function_divides);
0609 if (r.which() == utree_type::invalid_type)
0610 {
0611 BOOST_THROW_EXCEPTION(bad_type_exception
0612 ("division performed on non-arithmetic utree types",
0613 a.which(), b.which()));
0614 }
0615 return r;
0616 }
0617
0618 inline utree operator%(utree const& a, utree const& b)
0619 {
0620 utree r = utree::visit(a, b, integral_function_modulus);
0621 if (r.which() == utree_type::invalid_type)
0622 {
0623 BOOST_THROW_EXCEPTION(bad_type_exception
0624 ("modulos performed on non-integral utree types",
0625 a.which(), b.which()));
0626 }
0627 return r;
0628 }
0629
0630 inline utree operator-(utree const& a)
0631 {
0632 utree r = utree::visit(a, arithmetic_function_negate);
0633 if (r.which() == utree_type::invalid_type)
0634 {
0635 BOOST_THROW_EXCEPTION(bad_type_exception
0636 ("negation performed on non-arithmetic utree type",
0637 a.which()));
0638 }
0639 return r;
0640 }
0641
0642 inline utree operator&(utree const& a, utree const& b)
0643 {
0644 utree r = utree::visit(a, b, integral_function_bitand_);
0645 if (r.which() == utree_type::invalid_type)
0646 {
0647 BOOST_THROW_EXCEPTION(bad_type_exception
0648 ("bitwise and performed on non-integral utree types",
0649 a.which(), b.which()));
0650 }
0651 return r;
0652 }
0653
0654 inline utree operator|(utree const& a, utree const& b)
0655 {
0656 utree r = utree::visit(a, b, integral_function_bitor_);
0657 if (r.which() == utree_type::invalid_type)
0658 {
0659 BOOST_THROW_EXCEPTION(bad_type_exception
0660 ("bitwise or performed on non-integral utree types",
0661 a.which(), b.which()));
0662 }
0663 return r;
0664 }
0665
0666 inline utree operator^(utree const& a, utree const& b)
0667 {
0668 utree r = utree::visit(a, b, integral_function_bitxor_);
0669 if (r.which() == utree_type::invalid_type)
0670 {
0671 BOOST_THROW_EXCEPTION(bad_type_exception
0672 ("bitwise xor performed on non-integral utree types",
0673 a.which(), b.which()));
0674 }
0675 return r;
0676 }
0677
0678 inline utree operator<<(utree const& a, utree const& b)
0679 {
0680 utree r = utree::visit(a, b, integral_function_shift_left);
0681 if (r.which() == utree_type::invalid_type)
0682 {
0683 BOOST_THROW_EXCEPTION(bad_type_exception
0684 ("left shift performed on non-integral utree types",
0685 a.which(), b.which()));
0686 }
0687 return r;
0688 }
0689
0690 inline utree operator>>(utree const& a, utree const& b)
0691 {
0692 utree r = utree::visit(a, b, integral_function_shift_right);
0693 if (r.which() == utree_type::invalid_type)
0694 {
0695 BOOST_THROW_EXCEPTION(bad_type_exception
0696 ("right shift performed on non-integral utree types",
0697 a.which(), b.which()));
0698 }
0699 return r;
0700 }
0701
0702 inline utree operator~(utree const& a)
0703 {
0704 utree r = utree::visit(a, integral_function_invert);
0705 if (r.which() == utree_type::invalid_type)
0706 {
0707 BOOST_THROW_EXCEPTION(bad_type_exception
0708 ("inversion performed on non-integral utree type",
0709 a.which()));
0710 }
0711 return r;
0712 }
0713 }}
0714
0715 #if defined(BOOST_MSVC)
0716 # pragma warning(pop)
0717 #endif
0718
0719 #endif