Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:53:48

0001 ///////////////////////////////////////////////////////////////////////////////
0002 // lookbehind_matcher.hpp
0003 //
0004 //  Copyright 2008 Eric Niebler. Distributed under the Boost
0005 //  Software License, Version 1.0. (See accompanying file
0006 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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 // MS compatible compilers support #pragma once
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     // lookbehind_matcher
0031     //   Xpr can be either a static_xpression or a shared_matchable
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             // matching xpr could produce side-effects, save state
0113             memento<BidiIter> mem = save_sub_matches(state);
0114 
0115             if(this->not_)
0116             {
0117                 // negative look-ahead assertions do not trigger partial matches.
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_; // false if matching xpr_ could modify the sub-matches
0163         std::size_t width_;
0164     };
0165 
0166 }}}
0167 
0168 #endif