PageRenderTime 20ms CodeModel.GetById 8ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/xpressive/detail/core/matcher/lookbehind_matcher.hpp

http://hadesmem.googlecode.com/
C++ Header | 168 lines | 138 code | 18 blank | 12 comment | 20 complexity | 0f3a7ec9c64f6261e637bcbe1122fcc4 MD5 | raw file
  1///////////////////////////////////////////////////////////////////////////////
  2// lookbehind_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_LOOKBEHIND_MATCHER_HPP_EAN_10_04_2005
  9#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LOOKBEHIND_MATCHER_HPP_EAN_10_04_2005
 10
 11// MS compatible compilers support #pragma once
 12#if defined(_MSC_VER) && (_MSC_VER >= 1020)
 13# pragma once
 14#endif
 15
 16#include <boost/assert.hpp>
 17#include <boost/xpressive/regex_error.hpp>
 18#include <boost/xpressive/regex_constants.hpp>
 19#include <boost/xpressive/detail/detail_fwd.hpp>
 20#include <boost/xpressive/detail/core/quant_style.hpp>
 21#include <boost/xpressive/detail/core/state.hpp>
 22#include <boost/xpressive/detail/utility/algorithm.hpp>
 23#include <boost/xpressive/detail/utility/save_restore.hpp>
 24#include <boost/xpressive/detail/utility/ignore_unused.hpp>
 25
 26namespace boost { namespace xpressive { namespace detail
 27{
 28
 29    ///////////////////////////////////////////////////////////////////////////////
 30    // lookbehind_matcher
 31    //   Xpr can be either a static_xpression or a shared_matchable
 32    template<typename Xpr>
 33    struct lookbehind_matcher
 34      : quant_style<quant_none, 0, Xpr::pure>
 35    {
 36        lookbehind_matcher(Xpr const &xpr, std::size_t wid, bool no, bool pure = Xpr::pure)
 37          : xpr_(xpr)
 38          , not_(no)
 39          , pure_(pure)
 40          , width_(wid)
 41        {
 42            BOOST_XPR_ENSURE_(!is_unknown(this->width_), regex_constants::error_badlookbehind,
 43                "Variable-width look-behind assertions are not supported");
 44        }
 45
 46        void inverse()
 47        {
 48            this->not_ = !this->not_;
 49        }
 50
 51        template<typename BidiIter, typename Next>
 52        bool match(match_state<BidiIter> &state, Next const &next) const
 53        {
 54            return Xpr::pure || this->pure_
 55              ? this->match_(state, next, mpl::true_())
 56              : this->match_(state, next, mpl::false_());
 57        }
 58
 59        template<typename BidiIter, typename Next>
 60        bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const
 61        {
 62            typedef typename iterator_difference<BidiIter>::type difference_type;
 63            BidiIter const tmp = state.cur_;
 64            if(!detail::advance_to(state.cur_, -static_cast<difference_type>(this->width_), state.begin_))
 65            {
 66                state.cur_ = tmp;
 67                return this->not_ ? next.match(state) : false;
 68            }
 69
 70            if(this->not_)
 71            {
 72                if(this->xpr_.match(state))
 73                {
 74                    BOOST_ASSERT(state.cur_ == tmp);
 75                    return false;
 76                }
 77                state.cur_ = tmp;
 78                if(next.match(state))
 79                {
 80                    return true;
 81                }
 82            }
 83            else
 84            {
 85                if(!this->xpr_.match(state))
 86                {
 87                    state.cur_ = tmp;
 88                    return false;
 89                }
 90                BOOST_ASSERT(state.cur_ == tmp);
 91                if(next.match(state))
 92                {
 93                    return true;
 94                }
 95            }
 96
 97            BOOST_ASSERT(state.cur_ == tmp);
 98            return false;
 99        }
100
101        template<typename BidiIter, typename Next>
102        bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const
103        {
104            typedef typename iterator_difference<BidiIter>::type difference_type;
105            BidiIter const tmp = state.cur_;
106            if(!detail::advance_to(state.cur_, -static_cast<difference_type>(this->width_), state.begin_))
107            {
108                state.cur_ = tmp;
109                return this->not_ ? next.match(state) : false;
110            }
111
112            // matching xpr could produce side-effects, save state
113            memento<BidiIter> mem = save_sub_matches(state);
114
115            if(this->not_)
116            {
117                // negative look-ahead assertions do not trigger partial matches.
118                save_restore<bool> partial_match(state.found_partial_match_);
119                detail::ignore_unused(partial_match);
120
121                if(this->xpr_.match(state))
122                {
123                    restore_action_queue(mem, state);
124                    restore_sub_matches(mem, state);
125                    BOOST_ASSERT(state.cur_ == tmp);
126                    return false;
127                }
128                state.cur_ = tmp;
129                restore_action_queue(mem, state);
130                if(next.match(state))
131                {
132                    reclaim_sub_matches(mem, state, true);
133                    return true;
134                }
135                reclaim_sub_matches(mem, state, false);
136            }
137            else
138            {
139                if(!this->xpr_.match(state))
140                {
141                    state.cur_ = tmp;
142                    restore_action_queue(mem, state);
143                    reclaim_sub_matches(mem, state, false);
144                    return false;
145                }
146                BOOST_ASSERT(state.cur_ == tmp);
147                restore_action_queue(mem, state);
148                if(next.match(state))
149                {
150                    reclaim_sub_matches(mem, state, true);
151                    return true;
152                }
153                restore_sub_matches(mem, state);
154            }
155
156            BOOST_ASSERT(state.cur_ == tmp);
157            return false;
158        }
159
160        Xpr xpr_;
161        bool not_;
162        bool pure_; // false if matching xpr_ could modify the sub-matches
163        std::size_t width_;
164    };
165
166}}}
167
168#endif