]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // lookahead_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_LOOKAHEAD_MATCHER_HPP_EAN_10_04_2005 | |
9 | #define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LOOKAHEAD_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/assert.hpp> | |
17 | #include <boost/mpl/bool.hpp> | |
18 | #include <boost/xpressive/detail/detail_fwd.hpp> | |
19 | #include <boost/xpressive/detail/core/quant_style.hpp> | |
20 | #include <boost/xpressive/detail/core/state.hpp> | |
21 | #include <boost/xpressive/detail/utility/save_restore.hpp> | |
22 | #include <boost/xpressive/detail/utility/ignore_unused.hpp> | |
23 | ||
24 | namespace boost { namespace xpressive { namespace detail | |
25 | { | |
26 | ||
27 | /////////////////////////////////////////////////////////////////////////////// | |
28 | // lookahead_matcher | |
29 | // Xpr can be either a static_xpression, or a shared_matchable | |
30 | // | |
31 | template<typename Xpr> | |
32 | struct lookahead_matcher | |
33 | : quant_style<quant_none, 0, Xpr::pure> | |
34 | { | |
35 | lookahead_matcher(Xpr const &xpr, bool no, bool pure = Xpr::pure) | |
36 | : xpr_(xpr) | |
37 | , not_(no) | |
38 | , pure_(pure) | |
39 | { | |
40 | } | |
41 | ||
42 | void inverse() | |
43 | { | |
44 | this->not_ = !this->not_; | |
45 | } | |
46 | ||
47 | template<typename BidiIter, typename Next> | |
48 | bool match(match_state<BidiIter> &state, Next const &next) const | |
49 | { | |
50 | return Xpr::pure || this->pure_ | |
51 | ? this->match_(state, next, mpl::true_()) | |
52 | : this->match_(state, next, mpl::false_()); | |
53 | } | |
54 | ||
55 | template<typename BidiIter, typename Next> | |
56 | bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const | |
57 | { | |
58 | BidiIter const tmp = state.cur_; | |
59 | ||
60 | if(this->not_) | |
61 | { | |
62 | // negative look-ahead assertions do not trigger partial matches. | |
63 | save_restore<bool> partial_match(state.found_partial_match_); | |
64 | detail::ignore_unused(partial_match); | |
65 | ||
66 | if(this->xpr_.match(state)) | |
67 | { | |
68 | state.cur_ = tmp; | |
69 | return false; | |
70 | } | |
71 | else if(next.match(state)) | |
72 | { | |
73 | return true; | |
74 | } | |
75 | } | |
76 | else | |
77 | { | |
78 | if(!this->xpr_.match(state)) | |
79 | { | |
80 | return false; | |
81 | } | |
82 | state.cur_ = tmp; | |
83 | if(next.match(state)) | |
84 | { | |
85 | return true; | |
86 | } | |
87 | } | |
88 | ||
89 | BOOST_ASSERT(state.cur_ == tmp); | |
90 | return false; | |
91 | } | |
92 | ||
93 | template<typename BidiIter, typename Next> | |
94 | bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const | |
95 | { | |
96 | BidiIter const tmp = state.cur_; | |
97 | ||
98 | // matching xpr could produce side-effects, save state | |
99 | memento<BidiIter> mem = save_sub_matches(state); | |
100 | ||
101 | if(this->not_) | |
102 | { | |
103 | // negative look-ahead assertions do not trigger partial matches. | |
104 | save_restore<bool> partial_match(state.found_partial_match_); | |
105 | detail::ignore_unused(partial_match); | |
106 | ||
107 | if(this->xpr_.match(state)) | |
108 | { | |
109 | restore_action_queue(mem, state); | |
110 | restore_sub_matches(mem, state); | |
111 | state.cur_ = tmp; | |
112 | return false; | |
113 | } | |
114 | restore_action_queue(mem, state); | |
115 | if(next.match(state)) | |
116 | { | |
117 | reclaim_sub_matches(mem, state, true); | |
118 | return true; | |
119 | } | |
120 | reclaim_sub_matches(mem, state, false); | |
121 | } | |
122 | else | |
123 | { | |
124 | if(!this->xpr_.match(state)) | |
125 | { | |
126 | restore_action_queue(mem, state); | |
127 | reclaim_sub_matches(mem, state, false); | |
128 | return false; | |
129 | } | |
130 | state.cur_ = tmp; | |
131 | restore_action_queue(mem, state); | |
132 | if(next.match(state)) | |
133 | { | |
134 | reclaim_sub_matches(mem, state, true); | |
135 | return true; | |
136 | } | |
137 | restore_sub_matches(mem, state); | |
138 | } | |
139 | ||
140 | BOOST_ASSERT(state.cur_ == tmp); | |
141 | return false; | |
142 | } | |
143 | ||
144 | Xpr xpr_; | |
145 | bool not_; | |
146 | bool pure_; // false if matching xpr_ could modify the sub-matches | |
147 | }; | |
148 | ||
149 | }}} | |
150 | ||
151 | #endif |