sequence.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // sequence.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_DYNAMIC_SEQUENCE_HPP_EAN_04_10_2006
  8. #define BOOST_XPRESSIVE_DETAIL_DYNAMIC_SEQUENCE_HPP_EAN_04_10_2006
  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/intrusive_ptr.hpp>
  15. #include <boost/xpressive/detail/utility/width.hpp>
  16. #include <boost/xpressive/detail/detail_fwd.hpp>
  17. namespace boost { namespace xpressive { namespace detail
  18. {
  19. ///////////////////////////////////////////////////////////////////////////////
  20. // sequence
  21. template<typename BidiIter>
  22. struct sequence
  23. {
  24. sequence()
  25. : pure_(true)
  26. , width_(0)
  27. , quant_(quant_none)
  28. , head_()
  29. , tail_(0)
  30. , alt_end_xpr_()
  31. , alternates_(0)
  32. {
  33. }
  34. template<typename Matcher>
  35. sequence(intrusive_ptr<dynamic_xpression<Matcher, BidiIter> > const &xpr)
  36. : pure_(Matcher::pure)
  37. , width_(xpr->Matcher::get_width())
  38. , quant_(static_cast<quant_enum>(Matcher::quant))
  39. , head_(xpr)
  40. , tail_(&xpr->next_)
  41. , alt_end_xpr_()
  42. , alternates_(0)
  43. {
  44. }
  45. template<typename Traits>
  46. sequence(intrusive_ptr<dynamic_xpression<alternate_matcher<alternates_vector<BidiIter>, Traits>, BidiIter> > const &xpr)
  47. : pure_(true)
  48. , width_(0)
  49. , quant_(quant_none)
  50. , head_(xpr)
  51. , tail_(&xpr->next_)
  52. , alt_end_xpr_()
  53. , alternates_(&xpr->alternates_)
  54. {
  55. }
  56. bool empty() const
  57. {
  58. return !this->head_;
  59. }
  60. sequence<BidiIter> &operator +=(sequence<BidiIter> const &that)
  61. {
  62. if(this->empty())
  63. {
  64. *this = that;
  65. }
  66. else if(!that.empty())
  67. {
  68. *this->tail_ = that.head_;
  69. this->tail_ = that.tail_;
  70. // keep track of sequence width and purity
  71. this->width_ += that.width_;
  72. this->pure_ = this->pure_ && that.pure_;
  73. this->set_quant_();
  74. }
  75. return *this;
  76. }
  77. sequence<BidiIter> &operator |=(sequence<BidiIter> that)
  78. {
  79. BOOST_ASSERT(!this->empty());
  80. BOOST_ASSERT(0 != this->alternates_);
  81. // Keep track of width and purity
  82. if(this->alternates_->empty())
  83. {
  84. this->width_ = that.width_;
  85. this->pure_ = that.pure_;
  86. }
  87. else
  88. {
  89. this->width_ |= that.width_;
  90. this->pure_ = this->pure_ && that.pure_;
  91. }
  92. // through the wonders of reference counting, all alternates_ can share an end_alternate
  93. if(!this->alt_end_xpr_)
  94. {
  95. this->alt_end_xpr_ = new alt_end_xpr_type;
  96. }
  97. // terminate each alternate with an alternate_end_matcher
  98. that += sequence(this->alt_end_xpr_);
  99. this->alternates_->push_back(that.head_);
  100. this->set_quant_();
  101. return *this;
  102. }
  103. void repeat(quant_spec const &spec)
  104. {
  105. this->xpr().matchable()->repeat(spec, *this);
  106. }
  107. shared_matchable<BidiIter> const &xpr() const
  108. {
  109. return this->head_;
  110. }
  111. detail::width width() const
  112. {
  113. return this->width_;
  114. }
  115. bool pure() const
  116. {
  117. return this->pure_;
  118. }
  119. quant_enum quant() const
  120. {
  121. return this->quant_;
  122. }
  123. private:
  124. typedef dynamic_xpression<alternate_end_matcher, BidiIter> alt_end_xpr_type;
  125. void set_quant_()
  126. {
  127. this->quant_ = (!is_unknown(this->width_) && this->pure_)
  128. ? (!this->width_ ? quant_none : quant_fixed_width)
  129. : quant_variable_width;
  130. }
  131. bool pure_;
  132. detail::width width_;
  133. quant_enum quant_;
  134. shared_matchable<BidiIter> head_;
  135. shared_matchable<BidiIter> *tail_;
  136. intrusive_ptr<alt_end_xpr_type> alt_end_xpr_;
  137. alternates_vector<BidiIter> *alternates_;
  138. };
  139. template<typename BidiIter>
  140. inline sequence<BidiIter> operator +(sequence<BidiIter> left, sequence<BidiIter> const &right)
  141. {
  142. return left += right;
  143. }
  144. template<typename BidiIter>
  145. inline sequence<BidiIter> operator |(sequence<BidiIter> left, sequence<BidiIter> const &right)
  146. {
  147. return left |= right;
  148. }
  149. }}} // namespace boost::xpressive::detail
  150. #endif