| /////////////////////////////////////////////////////////////////////////////// |
| // sequence.hpp |
| // |
| // Copyright 2008 Eric Niebler. Distributed under the Boost |
| // Software License, Version 1.0. (See accompanying file |
| // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| |
| #ifndef BOOST_XPRESSIVE_DETAIL_DYNAMIC_SEQUENCE_HPP_EAN_04_10_2006 |
| #define BOOST_XPRESSIVE_DETAIL_DYNAMIC_SEQUENCE_HPP_EAN_04_10_2006 |
| |
| // MS compatible compilers support #pragma once |
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) |
| # pragma once |
| #endif |
| |
| #include <boost/assert.hpp> |
| #include <boost/intrusive_ptr.hpp> |
| #include <boost/xpressive/detail/utility/width.hpp> |
| #include <boost/xpressive/detail/detail_fwd.hpp> |
| |
| namespace boost { namespace xpressive { namespace detail |
| { |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // sequence |
| template<typename BidiIter> |
| struct sequence |
| { |
| sequence() |
| : pure_(true) |
| , width_(0) |
| , quant_(quant_none) |
| , head_() |
| , tail_(0) |
| , alt_end_xpr_() |
| , alternates_(0) |
| { |
| } |
| |
| template<typename Matcher> |
| sequence(intrusive_ptr<dynamic_xpression<Matcher, BidiIter> > const &xpr) |
| : pure_(Matcher::pure) |
| , width_(xpr->Matcher::get_width()) |
| , quant_(static_cast<quant_enum>(Matcher::quant)) |
| , head_(xpr) |
| , tail_(&xpr->next_) |
| , alt_end_xpr_() |
| , alternates_(0) |
| { |
| } |
| |
| template<typename Traits> |
| sequence(intrusive_ptr<dynamic_xpression<alternate_matcher<alternates_vector<BidiIter>, Traits>, BidiIter> > const &xpr) |
| : pure_(true) |
| , width_(0) |
| , quant_(quant_none) |
| , head_(xpr) |
| , tail_(&xpr->next_) |
| , alt_end_xpr_() |
| , alternates_(&xpr->alternates_) |
| { |
| } |
| |
| bool empty() const |
| { |
| return !this->head_; |
| } |
| |
| sequence<BidiIter> &operator +=(sequence<BidiIter> const &that) |
| { |
| if(this->empty()) |
| { |
| *this = that; |
| } |
| else if(!that.empty()) |
| { |
| *this->tail_ = that.head_; |
| this->tail_ = that.tail_; |
| // keep track of sequence width and purity |
| this->width_ += that.width_; |
| this->pure_ = this->pure_ && that.pure_; |
| this->set_quant_(); |
| } |
| return *this; |
| } |
| |
| sequence<BidiIter> &operator |=(sequence<BidiIter> that) |
| { |
| BOOST_ASSERT(!this->empty()); |
| BOOST_ASSERT(0 != this->alternates_); |
| |
| // Keep track of width and purity |
| if(this->alternates_->empty()) |
| { |
| this->width_ = that.width_; |
| this->pure_ = that.pure_; |
| } |
| else |
| { |
| this->width_ |= that.width_; |
| this->pure_ = this->pure_ && that.pure_; |
| } |
| |
| // through the wonders of reference counting, all alternates_ can share an end_alternate |
| if(!this->alt_end_xpr_) |
| { |
| this->alt_end_xpr_ = new alt_end_xpr_type; |
| } |
| |
| // terminate each alternate with an alternate_end_matcher |
| that += sequence(this->alt_end_xpr_); |
| this->alternates_->push_back(that.head_); |
| this->set_quant_(); |
| return *this; |
| } |
| |
| void repeat(quant_spec const &spec) |
| { |
| this->xpr().matchable()->repeat(spec, *this); |
| } |
| |
| shared_matchable<BidiIter> const &xpr() const |
| { |
| return this->head_; |
| } |
| |
| detail::width width() const |
| { |
| return this->width_; |
| } |
| |
| bool pure() const |
| { |
| return this->pure_; |
| } |
| |
| quant_enum quant() const |
| { |
| return this->quant_; |
| } |
| |
| private: |
| typedef dynamic_xpression<alternate_end_matcher, BidiIter> alt_end_xpr_type; |
| |
| void set_quant_() |
| { |
| this->quant_ = (!is_unknown(this->width_) && this->pure_) |
| ? (!this->width_ ? quant_none : quant_fixed_width) |
| : quant_variable_width; |
| } |
| |
| bool pure_; |
| detail::width width_; |
| quant_enum quant_; |
| shared_matchable<BidiIter> head_; |
| shared_matchable<BidiIter> *tail_; |
| intrusive_ptr<alt_end_xpr_type> alt_end_xpr_; |
| alternates_vector<BidiIter> *alternates_; |
| }; |
| |
| template<typename BidiIter> |
| inline sequence<BidiIter> operator +(sequence<BidiIter> left, sequence<BidiIter> const &right) |
| { |
| return left += right; |
| } |
| |
| template<typename BidiIter> |
| inline sequence<BidiIter> operator |(sequence<BidiIter> left, sequence<BidiIter> const &right) |
| { |
| return left |= right; |
| } |
| |
| }}} // namespace boost::xpressive::detail |
| |
| #endif |