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