]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // keeper_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_KEEPER_MATCHER_HPP_EAN_10_04_2005 | |
9 | #define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_KEEPER_MATCHER_HPP_EAN_10_04_2005 | |
10 | ||
11 | // MS compatible compilers support #pragma once | |
12 | #if defined(_MSC_VER) | |
13 | # pragma once | |
14 | #endif | |
15 | ||
16 | #include <boost/mpl/bool.hpp> | |
17 | #include <boost/xpressive/detail/detail_fwd.hpp> | |
18 | #include <boost/xpressive/detail/core/quant_style.hpp> | |
19 | #include <boost/xpressive/detail/core/state.hpp> | |
20 | ||
21 | namespace boost { namespace xpressive { namespace detail | |
22 | { | |
23 | ||
24 | /////////////////////////////////////////////////////////////////////////////// | |
25 | // keeper_matcher | |
26 | // Xpr can be either a static_xpression, or a shared_matchable | |
27 | template<typename Xpr> | |
28 | struct keeper_matcher | |
29 | : quant_style<quant_variable_width, unknown_width::value, Xpr::pure> | |
30 | { | |
31 | keeper_matcher(Xpr const &xpr, bool pure = Xpr::pure) | |
32 | : xpr_(xpr) | |
33 | , pure_(pure) | |
34 | { | |
35 | } | |
36 | ||
37 | template<typename BidiIter, typename Next> | |
38 | bool match(match_state<BidiIter> &state, Next const &next) const | |
39 | { | |
40 | return Xpr::pure || this->pure_ | |
41 | ? this->match_(state, next, mpl::true_()) | |
42 | : this->match_(state, next, mpl::false_()); | |
43 | } | |
44 | ||
45 | template<typename BidiIter, typename Next> | |
46 | bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const | |
47 | { | |
48 | BidiIter const tmp = state.cur_; | |
49 | ||
50 | // matching xpr is guaranteed to not produce side-effects, don't bother saving state | |
51 | if(!this->xpr_.match(state)) | |
52 | { | |
53 | return false; | |
54 | } | |
55 | else if(next.match(state)) | |
56 | { | |
57 | return true; | |
58 | } | |
59 | ||
60 | state.cur_ = tmp; | |
61 | return false; | |
62 | } | |
63 | ||
64 | template<typename BidiIter, typename Next> | |
65 | bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const | |
66 | { | |
67 | BidiIter const tmp = state.cur_; | |
68 | ||
69 | // matching xpr could produce side-effects, save state | |
70 | memento<BidiIter> mem = save_sub_matches(state); | |
71 | ||
72 | if(!this->xpr_.match(state)) | |
73 | { | |
74 | restore_action_queue(mem, state); | |
75 | reclaim_sub_matches(mem, state, false); | |
76 | return false; | |
77 | } | |
78 | restore_action_queue(mem, state); | |
79 | if(next.match(state)) | |
80 | { | |
81 | reclaim_sub_matches(mem, state, true); | |
82 | return true; | |
83 | } | |
84 | ||
85 | restore_sub_matches(mem, state); | |
86 | state.cur_ = tmp; | |
87 | return false; | |
88 | } | |
89 | ||
90 | Xpr xpr_; | |
91 | bool pure_; // false if matching xpr_ could modify the sub-matches | |
92 | }; | |
93 | ||
94 | }}} | |
95 | ||
96 | #endif |