/////////////////////////////////////////////////////////////////////////////// | |
// 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 |