1 /////////////////////////////////////////////////////////////////////////////// 2 // repeat_end_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_REPEAT_END_MATCHER_HPP_EAN_10_04_2005 9 #define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_REPEAT_END_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/mpl/bool.hpp> 17 #include <boost/xpressive/detail/detail_fwd.hpp> 18 #include <boost/xpressive/detail/core/quant_style.hpp> 19 #include <boost/xpressive/detail/core/state.hpp> 20 21 namespace boost { namespace xpressive { namespace detail 22 { 23 24 /////////////////////////////////////////////////////////////////////////////// 25 // repeat_end_matcher 26 // 27 template<typename Greedy> 28 struct repeat_end_matcher 29 : quant_style<quant_none, 0, false> 30 { 31 typedef Greedy greedy_type; 32 int mark_number_; 33 unsigned int min_, max_; 34 mutable void const *back_; 35 repeat_end_matcherboost::xpressive::detail::repeat_end_matcher36 repeat_end_matcher(int mark_nbr, unsigned int min, unsigned int max) 37 : mark_number_(mark_nbr) 38 , min_(min) 39 , max_(max) 40 , back_(0) 41 { 42 } 43 44 template<typename BidiIter, typename Next> matchboost::xpressive::detail::repeat_end_matcher45 bool match(match_state<BidiIter> &state, Next const &next) const 46 { 47 // prevent repeated zero-width sub-matches from causing infinite recursion 48 sub_match_impl<BidiIter> &br = state.sub_match(this->mark_number_); 49 50 if(br.zero_width_ && br.begin_ == state.cur_) 51 { 52 return next.skip_match(state); 53 } 54 55 bool old_zero_width = br.zero_width_; 56 br.zero_width_ = (br.begin_ == state.cur_); 57 58 if(this->match_(state, next, greedy_type())) 59 { 60 return true; 61 } 62 63 br.zero_width_ = old_zero_width; 64 return false; 65 } 66 67 // greedy, variable-width quantifier 68 template<typename BidiIter, typename Next> match_boost::xpressive::detail::repeat_end_matcher69 bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const 70 { 71 sub_match_impl<BidiIter> &br = state.sub_match(this->mark_number_); 72 73 if(this->max_ > br.repeat_count_) 74 { 75 ++br.repeat_count_; 76 // loop back to the expression "pushed" in repeat_begin_matcher::match 77 if(next.top_match(state, this->back_)) 78 { 79 return true; 80 } 81 else if(--br.repeat_count_ < this->min_) 82 { 83 return false; 84 } 85 } 86 87 // looping finished, continue matching the rest of the pattern 88 return next.skip_match(state); 89 } 90 91 // non-greedy, variable-width quantifier 92 template<typename BidiIter, typename Next> match_boost::xpressive::detail::repeat_end_matcher93 bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const 94 { 95 sub_match_impl<BidiIter> &br = state.sub_match(this->mark_number_); 96 97 if(this->min_ <= br.repeat_count_) 98 { 99 if(next.skip_match(state)) 100 { 101 return true; 102 } 103 } 104 105 if(this->max_ > br.repeat_count_) 106 { 107 ++br.repeat_count_; 108 if(next.top_match(state, this->back_)) 109 { 110 return true; 111 } 112 --br.repeat_count_; 113 } 114 115 return false; 116 } 117 }; 118 119 }}} 120 121 #endif 122