lookbehind_matcher.hpp 5.6 KB

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