lookahead_matcher.hpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // lookahead_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_LOOKAHEAD_MATCHER_HPP_EAN_10_04_2005
  8. #define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LOOKAHEAD_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/mpl/bool.hpp>
  15. #include <boost/xpressive/detail/detail_fwd.hpp>
  16. #include <boost/xpressive/detail/core/quant_style.hpp>
  17. #include <boost/xpressive/detail/core/state.hpp>
  18. #include <boost/xpressive/detail/utility/save_restore.hpp>
  19. #include <boost/xpressive/detail/utility/ignore_unused.hpp>
  20. namespace boost { namespace xpressive { namespace detail
  21. {
  22. ///////////////////////////////////////////////////////////////////////////////
  23. // lookahead_matcher
  24. // Xpr can be either a static_xpression, or a shared_matchable
  25. //
  26. template<typename Xpr>
  27. struct lookahead_matcher
  28. : quant_style<quant_none, 0, Xpr::pure>
  29. {
  30. lookahead_matcher(Xpr const &xpr, bool no, bool pure = Xpr::pure)
  31. : xpr_(xpr)
  32. , not_(no)
  33. , pure_(pure)
  34. {
  35. }
  36. void inverse()
  37. {
  38. this->not_ = !this->not_;
  39. }
  40. template<typename BidiIter, typename Next>
  41. bool match(match_state<BidiIter> &state, Next const &next) const
  42. {
  43. return Xpr::pure || this->pure_
  44. ? this->match_(state, next, mpl::true_())
  45. : this->match_(state, next, mpl::false_());
  46. }
  47. template<typename BidiIter, typename Next>
  48. bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const
  49. {
  50. BidiIter const tmp = state.cur_;
  51. if(this->not_)
  52. {
  53. // negative look-ahead assertions do not trigger partial matches.
  54. save_restore<bool> partial_match(state.found_partial_match_);
  55. detail::ignore_unused(partial_match);
  56. if(this->xpr_.match(state))
  57. {
  58. state.cur_ = tmp;
  59. return false;
  60. }
  61. else if(next.match(state))
  62. {
  63. return true;
  64. }
  65. }
  66. else
  67. {
  68. if(!this->xpr_.match(state))
  69. {
  70. return false;
  71. }
  72. state.cur_ = tmp;
  73. if(next.match(state))
  74. {
  75. return true;
  76. }
  77. }
  78. BOOST_ASSERT(state.cur_ == tmp);
  79. return false;
  80. }
  81. template<typename BidiIter, typename Next>
  82. bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const
  83. {
  84. BidiIter const tmp = state.cur_;
  85. // matching xpr could produce side-effects, save state
  86. memento<BidiIter> mem = save_sub_matches(state);
  87. if(this->not_)
  88. {
  89. // negative look-ahead assertions do not trigger partial matches.
  90. save_restore<bool> partial_match(state.found_partial_match_);
  91. detail::ignore_unused(partial_match);
  92. if(this->xpr_.match(state))
  93. {
  94. restore_action_queue(mem, state);
  95. restore_sub_matches(mem, state);
  96. state.cur_ = tmp;
  97. return false;
  98. }
  99. restore_action_queue(mem, state);
  100. if(next.match(state))
  101. {
  102. reclaim_sub_matches(mem, state, true);
  103. return true;
  104. }
  105. reclaim_sub_matches(mem, state, false);
  106. }
  107. else
  108. {
  109. if(!this->xpr_.match(state))
  110. {
  111. restore_action_queue(mem, state);
  112. reclaim_sub_matches(mem, state, false);
  113. return false;
  114. }
  115. state.cur_ = tmp;
  116. restore_action_queue(mem, state);
  117. if(next.match(state))
  118. {
  119. reclaim_sub_matches(mem, state, true);
  120. return true;
  121. }
  122. restore_sub_matches(mem, state);
  123. }
  124. BOOST_ASSERT(state.cur_ == tmp);
  125. return false;
  126. }
  127. Xpr xpr_;
  128. bool not_;
  129. bool pure_; // false if matching xpr_ could modify the sub-matches
  130. };
  131. }}}
  132. #endif