| /////////////////////////////////////////////////////////////////////////////// |
| // predicate_matcher.hpp |
| // |
| // Copyright 2008 Eric Niebler. 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) |
| |
| #ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_PREDICATE_MATCHER_HPP_EAN_03_22_2007 |
| #define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_PREDICATE_MATCHER_HPP_EAN_03_22_2007 |
| |
| // MS compatible compilers support #pragma once |
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) |
| # pragma once |
| #endif |
| |
| #include <boost/mpl/not.hpp> |
| #include <boost/mpl/placeholders.hpp> |
| #include <boost/xpressive/detail/detail_fwd.hpp> |
| #include <boost/xpressive/detail/core/quant_style.hpp> |
| #include <boost/xpressive/detail/core/matcher/action_matcher.hpp> |
| #include <boost/xpressive/detail/core/state.hpp> |
| #include <boost/proto/core.hpp> |
| |
| namespace boost { namespace xpressive { namespace detail |
| { |
| /////////////////////////////////////////////////////////////////////////////// |
| // predicate_context |
| // |
| template<typename BidiIter> |
| struct predicate_context |
| { |
| explicit predicate_context(int sub, sub_match_impl<BidiIter> const *sub_matches, action_args_type *action_args) |
| : sub_(sub) |
| , sub_matches_(sub_matches) |
| , action_args_(action_args) |
| {} |
| |
| action_args_type const &args() const |
| { |
| return *this->action_args_; |
| } |
| |
| // eval_terminal |
| template<typename Expr, typename Arg> |
| struct eval_terminal |
| : proto::default_eval<Expr, predicate_context const> |
| {}; |
| |
| template<typename Expr, typename Arg> |
| struct eval_terminal<Expr, reference_wrapper<Arg> > |
| { |
| typedef Arg &result_type; |
| result_type operator()(Expr &expr, predicate_context const &) const |
| { |
| return proto::value(expr).get(); |
| } |
| }; |
| |
| template<typename Expr> |
| struct eval_terminal<Expr, any_matcher> |
| { |
| typedef sub_match<BidiIter> const &result_type; |
| result_type operator()(Expr &, predicate_context const &ctx) const |
| { |
| return ctx.sub_matches_[ctx.sub_]; |
| } |
| }; |
| |
| template<typename Expr> |
| struct eval_terminal<Expr, mark_placeholder> |
| { |
| typedef sub_match<BidiIter> const &result_type; |
| result_type operator()(Expr &expr, predicate_context const &ctx) const |
| { |
| return ctx.sub_matches_[proto::value(expr).mark_number_]; |
| } |
| }; |
| |
| template<typename Expr, typename Type, typename Int> |
| struct eval_terminal<Expr, action_arg<Type, Int> > |
| { |
| typedef typename action_arg<Type, Int>::reference result_type; |
| result_type operator()(Expr &expr, predicate_context const &ctx) const |
| { |
| action_args_type::const_iterator where_ = ctx.args().find(&typeid(proto::value(expr))); |
| if(where_ == ctx.args().end()) |
| { |
| BOOST_THROW_EXCEPTION( |
| regex_error( |
| regex_constants::error_badarg |
| , "An argument to an action was unspecified" |
| ) |
| ); |
| } |
| return proto::value(expr).cast(where_->second); |
| } |
| }; |
| |
| // eval |
| template<typename Expr, typename Tag = typename Expr::proto_tag> |
| struct eval |
| : proto::default_eval<Expr, predicate_context const> |
| {}; |
| |
| template<typename Expr> |
| struct eval<Expr, proto::tag::terminal> |
| : eval_terminal<Expr, typename proto::result_of::value<Expr>::type> |
| {}; |
| |
| #if BOOST_VERSION >= 103500 |
| template<typename Expr> |
| struct eval<Expr, proto::tag::mem_ptr> |
| : mem_ptr_eval<Expr, predicate_context const> |
| {}; |
| #endif |
| |
| int sub_; |
| sub_match_impl<BidiIter> const *sub_matches_; |
| action_args_type *action_args_; |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AssertionFunctor |
| // |
| struct AssertionFunctor |
| : proto::function< |
| proto::terminal<check_tag> |
| , proto::terminal<proto::_> |
| > |
| {}; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // predicate_matcher |
| // |
| template<typename Predicate> |
| struct predicate_matcher |
| : quant_style_assertion |
| { |
| int sub_; |
| Predicate predicate_; |
| |
| predicate_matcher(Predicate const &pred, int sub) |
| : sub_(sub) |
| , predicate_(pred) |
| { |
| } |
| |
| template<typename BidiIter, typename Next> |
| bool match(match_state<BidiIter> &state, Next const &next) const |
| { |
| // Predicate is check(assertion), where assertion can be |
| // a lambda or a function object. |
| return this->match_(state, next, proto::matches<Predicate, AssertionFunctor>()); |
| } |
| |
| private: |
| template<typename BidiIter, typename Next> |
| bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const |
| { |
| sub_match<BidiIter> const &sub = state.sub_match(this->sub_); |
| return proto::value(proto::child_c<1>(this->predicate_))(sub) && next.match(state); |
| } |
| |
| template<typename BidiIter, typename Next> |
| bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const |
| { |
| predicate_context<BidiIter> ctx(this->sub_, state.sub_matches_, state.action_args_); |
| return proto::eval(proto::child_c<1>(this->predicate_), ctx) && next.match(state); |
| } |
| }; |
| |
| }}} |
| |
| #endif // BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_PREDICATE_MATCHER_HPP_EAN_03_22_2007 |