Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / xpressive / detail / core / matcher / predicate_matcher.hpp
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     {
32         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
38         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;
53             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;
63             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;
73             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;
83             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
142         predicate_matcher(Predicate const &pred, int sub)
143           : sub_(sub)
144           , predicate_(pred)
145         {
146         }
147
148         template<typename BidiIter, typename Next>
149         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>
158         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>
165         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