1 ///////////////////////////////////////////////////////////////////////////////
2 // lookahead_matcher.hpp
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)
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
11 // MS compatible compilers support #pragma once
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>
24 namespace boost { namespace xpressive { namespace detail
27 ///////////////////////////////////////////////////////////////////////////////
29 // Xpr can be either a static_xpression, or a shared_matchable
31 template<typename Xpr>
32 struct lookahead_matcher
33 : quant_style<quant_none, 0, Xpr::pure>
35 lookahead_matcher(Xpr const &xpr, bool no, bool pure = Xpr::pure)
44 this->not_ = !this->not_;
47 template<typename BidiIter, typename Next>
48 bool match(match_state<BidiIter> &state, Next const &next) const
50 return Xpr::pure || this->pure_
51 ? this->match_(state, next, mpl::true_())
52 : this->match_(state, next, mpl::false_());
55 template<typename BidiIter, typename Next>
56 bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const
58 BidiIter const tmp = state.cur_;
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);
66 if(this->xpr_.match(state))
71 else if(next.match(state))
78 if(!this->xpr_.match(state))
89 BOOST_ASSERT(state.cur_ == tmp);
93 template<typename BidiIter, typename Next>
94 bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const
96 BidiIter const tmp = state.cur_;
98 // matching xpr could produce side-effects, save state
99 memento<BidiIter> mem = save_sub_matches(state);
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);
107 if(this->xpr_.match(state))
109 restore_action_queue(mem, state);
110 restore_sub_matches(mem, state);
114 restore_action_queue(mem, state);
115 if(next.match(state))
117 reclaim_sub_matches(mem, state, true);
120 reclaim_sub_matches(mem, state, false);
124 if(!this->xpr_.match(state))
126 restore_action_queue(mem, state);
127 reclaim_sub_matches(mem, state, false);
131 restore_action_queue(mem, state);
132 if(next.match(state))
134 reclaim_sub_matches(mem, state, true);
137 restore_sub_matches(mem, state);
140 BOOST_ASSERT(state.cur_ == tmp);
146 bool pure_; // false if matching xpr_ could modify the sub-matches