File indexing completed on 2025-01-18 09:53:48
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LOOKBEHIND_MATCHER_HPP_EAN_10_04_2005
0009 #define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LOOKBEHIND_MATCHER_HPP_EAN_10_04_2005
0010
0011
0012 #if defined(_MSC_VER)
0013 # pragma once
0014 #endif
0015
0016 #include <boost/assert.hpp>
0017 #include <boost/xpressive/regex_error.hpp>
0018 #include <boost/xpressive/regex_constants.hpp>
0019 #include <boost/xpressive/detail/detail_fwd.hpp>
0020 #include <boost/xpressive/detail/core/quant_style.hpp>
0021 #include <boost/xpressive/detail/core/state.hpp>
0022 #include <boost/xpressive/detail/utility/algorithm.hpp>
0023 #include <boost/xpressive/detail/utility/save_restore.hpp>
0024 #include <boost/xpressive/detail/utility/ignore_unused.hpp>
0025
0026 namespace boost { namespace xpressive { namespace detail
0027 {
0028
0029
0030
0031
0032 template<typename Xpr>
0033 struct lookbehind_matcher
0034 : quant_style<quant_none, 0, Xpr::pure>
0035 {
0036 lookbehind_matcher(Xpr const &xpr, std::size_t wid, bool no, bool pure = Xpr::pure)
0037 : xpr_(xpr)
0038 , not_(no)
0039 , pure_(pure)
0040 , width_(wid)
0041 {
0042 BOOST_XPR_ENSURE_(!is_unknown(this->width_), regex_constants::error_badlookbehind,
0043 "Variable-width look-behind assertions are not supported");
0044 }
0045
0046 void inverse()
0047 {
0048 this->not_ = !this->not_;
0049 }
0050
0051 template<typename BidiIter, typename Next>
0052 bool match(match_state<BidiIter> &state, Next const &next) const
0053 {
0054 return Xpr::pure || this->pure_
0055 ? this->match_(state, next, mpl::true_())
0056 : this->match_(state, next, mpl::false_());
0057 }
0058
0059 template<typename BidiIter, typename Next>
0060 bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const
0061 {
0062 typedef typename iterator_difference<BidiIter>::type difference_type;
0063 BidiIter const tmp = state.cur_;
0064 if(!detail::advance_to(state.cur_, -static_cast<difference_type>(this->width_), state.begin_))
0065 {
0066 state.cur_ = tmp;
0067 return this->not_ ? next.match(state) : false;
0068 }
0069
0070 if(this->not_)
0071 {
0072 if(this->xpr_.match(state))
0073 {
0074 BOOST_ASSERT(state.cur_ == tmp);
0075 return false;
0076 }
0077 state.cur_ = tmp;
0078 if(next.match(state))
0079 {
0080 return true;
0081 }
0082 }
0083 else
0084 {
0085 if(!this->xpr_.match(state))
0086 {
0087 state.cur_ = tmp;
0088 return false;
0089 }
0090 BOOST_ASSERT(state.cur_ == tmp);
0091 if(next.match(state))
0092 {
0093 return true;
0094 }
0095 }
0096
0097 BOOST_ASSERT(state.cur_ == tmp);
0098 return false;
0099 }
0100
0101 template<typename BidiIter, typename Next>
0102 bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const
0103 {
0104 typedef typename iterator_difference<BidiIter>::type difference_type;
0105 BidiIter const tmp = state.cur_;
0106 if(!detail::advance_to(state.cur_, -static_cast<difference_type>(this->width_), state.begin_))
0107 {
0108 state.cur_ = tmp;
0109 return this->not_ ? next.match(state) : false;
0110 }
0111
0112
0113 memento<BidiIter> mem = save_sub_matches(state);
0114
0115 if(this->not_)
0116 {
0117
0118 save_restore<bool> partial_match(state.found_partial_match_);
0119 detail::ignore_unused(partial_match);
0120
0121 if(this->xpr_.match(state))
0122 {
0123 restore_action_queue(mem, state);
0124 restore_sub_matches(mem, state);
0125 BOOST_ASSERT(state.cur_ == tmp);
0126 return false;
0127 }
0128 state.cur_ = tmp;
0129 restore_action_queue(mem, state);
0130 if(next.match(state))
0131 {
0132 reclaim_sub_matches(mem, state, true);
0133 return true;
0134 }
0135 reclaim_sub_matches(mem, state, false);
0136 }
0137 else
0138 {
0139 if(!this->xpr_.match(state))
0140 {
0141 state.cur_ = tmp;
0142 restore_action_queue(mem, state);
0143 reclaim_sub_matches(mem, state, false);
0144 return false;
0145 }
0146 BOOST_ASSERT(state.cur_ == tmp);
0147 restore_action_queue(mem, state);
0148 if(next.match(state))
0149 {
0150 reclaim_sub_matches(mem, state, true);
0151 return true;
0152 }
0153 restore_sub_matches(mem, state);
0154 }
0155
0156 BOOST_ASSERT(state.cur_ == tmp);
0157 return false;
0158 }
0159
0160 Xpr xpr_;
0161 bool not_;
0162 bool pure_;
0163 std::size_t width_;
0164 };
0165
0166 }}}
0167
0168 #endif