You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
175 lines
4.4 KiB
175 lines
4.4 KiB
/////////////////////////////////////////////////////////////////////////////// |
|
// 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
|
|
|