1 /////////////////////////////////////////////////////////////////////////////// 2 // predicate_matcher.hpp 3 // 4 // Copyright 2008 Eric Niebler. Distributed under the Boost 5 // Software License, Version 1.0. (See accompanying file 6 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 8 #ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_PREDICATE_MATCHER_HPP_EAN_03_22_2007 9 #define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_PREDICATE_MATCHER_HPP_EAN_03_22_2007 10 11 // MS compatible compilers support #pragma once 12 #if defined(_MSC_VER) 13 # pragma once 14 #endif 15 16 #include <boost/mpl/not.hpp> 17 #include <boost/mpl/placeholders.hpp> 18 #include <boost/xpressive/detail/detail_fwd.hpp> 19 #include <boost/xpressive/detail/core/quant_style.hpp> 20 #include <boost/xpressive/detail/core/matcher/action_matcher.hpp> 21 #include <boost/xpressive/detail/core/state.hpp> 22 #include <boost/proto/core.hpp> 23 24 namespace boost { namespace xpressive { namespace detail 25 { 26 /////////////////////////////////////////////////////////////////////////////// 27 // predicate_context 28 // 29 template<typename BidiIter> 30 struct predicate_context 31 { predicate_contextboost::xpressive::detail::predicate_context32 explicit predicate_context(int sub, sub_match_impl<BidiIter> const *sub_matches, action_args_type *action_args) 33 : sub_(sub) 34 , sub_matches_(sub_matches) 35 , action_args_(action_args) 36 {} 37 argsboost::xpressive::detail::predicate_context38 action_args_type const &args() const 39 { 40 return *this->action_args_; 41 } 42 43 // eval_terminal 44 template<typename Expr, typename Arg> 45 struct eval_terminal 46 : proto::default_eval<Expr, predicate_context const> 47 {}; 48 49 template<typename Expr, typename Arg> 50 struct eval_terminal<Expr, reference_wrapper<Arg> > 51 { 52 typedef Arg &result_type; operator ()boost::xpressive::detail::predicate_context::eval_terminal53 result_type operator()(Expr &expr, predicate_context const &) const 54 { 55 return proto::value(expr).get(); 56 } 57 }; 58 59 template<typename Expr> 60 struct eval_terminal<Expr, any_matcher> 61 { 62 typedef sub_match<BidiIter> const &result_type; operator ()boost::xpressive::detail::predicate_context::eval_terminal63 result_type operator()(Expr &, predicate_context const &ctx) const 64 { 65 return ctx.sub_matches_[ctx.sub_]; 66 } 67 }; 68 69 template<typename Expr> 70 struct eval_terminal<Expr, mark_placeholder> 71 { 72 typedef sub_match<BidiIter> const &result_type; operator ()boost::xpressive::detail::predicate_context::eval_terminal73 result_type operator()(Expr &expr, predicate_context const &ctx) const 74 { 75 return ctx.sub_matches_[proto::value(expr).mark_number_]; 76 } 77 }; 78 79 template<typename Expr, typename Type, typename Int> 80 struct eval_terminal<Expr, action_arg<Type, Int> > 81 { 82 typedef typename action_arg<Type, Int>::reference result_type; operator ()boost::xpressive::detail::predicate_context::eval_terminal83 result_type operator()(Expr &expr, predicate_context const &ctx) const 84 { 85 action_args_type::const_iterator where_ = ctx.args().find(&typeid(proto::value(expr))); 86 if(where_ == ctx.args().end()) 87 { 88 BOOST_THROW_EXCEPTION( 89 regex_error( 90 regex_constants::error_badarg 91 , "An argument to an action was unspecified" 92 ) 93 ); 94 } 95 return proto::value(expr).cast(where_->second); 96 } 97 }; 98 99 // eval 100 template<typename Expr, typename Tag = typename Expr::proto_tag> 101 struct eval 102 : proto::default_eval<Expr, predicate_context const> 103 {}; 104 105 template<typename Expr> 106 struct eval<Expr, proto::tag::terminal> 107 : eval_terminal<Expr, typename proto::result_of::value<Expr>::type> 108 {}; 109 110 #if BOOST_VERSION >= 103500 111 template<typename Expr> 112 struct eval<Expr, proto::tag::mem_ptr> 113 : mem_ptr_eval<Expr, predicate_context const> 114 {}; 115 #endif 116 117 int sub_; 118 sub_match_impl<BidiIter> const *sub_matches_; 119 action_args_type *action_args_; 120 }; 121 122 /////////////////////////////////////////////////////////////////////////////// 123 // AssertionFunctor 124 // 125 struct AssertionFunctor 126 : proto::function< 127 proto::terminal<check_tag> 128 , proto::terminal<proto::_> 129 > 130 {}; 131 132 /////////////////////////////////////////////////////////////////////////////// 133 // predicate_matcher 134 // 135 template<typename Predicate> 136 struct predicate_matcher 137 : quant_style_assertion 138 { 139 int sub_; 140 Predicate predicate_; 141 predicate_matcherboost::xpressive::detail::predicate_matcher142 predicate_matcher(Predicate const &pred, int sub) 143 : sub_(sub) 144 , predicate_(pred) 145 { 146 } 147 148 template<typename BidiIter, typename Next> matchboost::xpressive::detail::predicate_matcher149 bool match(match_state<BidiIter> &state, Next const &next) const 150 { 151 // Predicate is check(assertion), where assertion can be 152 // a lambda or a function object. 153 return this->match_(state, next, proto::matches<Predicate, AssertionFunctor>()); 154 } 155 156 private: 157 template<typename BidiIter, typename Next> match_boost::xpressive::detail::predicate_matcher158 bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const 159 { 160 sub_match<BidiIter> const &sub = state.sub_match(this->sub_); 161 return proto::value(proto::child_c<1>(this->predicate_))(sub) && next.match(state); 162 } 163 164 template<typename BidiIter, typename Next> match_boost::xpressive::detail::predicate_matcher165 bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const 166 { 167 predicate_context<BidiIter> ctx(this->sub_, state.sub_matches_, state.action_args_); 168 return proto::eval(proto::child_c<1>(this->predicate_), ctx) && next.match(state); 169 } 170 }; 171 172 }}} 173 174 #endif // BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_PREDICATE_MATCHER_HPP_EAN_03_22_2007 175