/usr/include/boost/xpressive/detail/dynamic
Edit: /usr/include/boost/xpressive/detail/dynamic/dynamic.hpp (10242B)
///////////////////////////////////////////////////////////////////////////////
// dynamic.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_DYNAMIC_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_DYNAMIC_DYNAMIC_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// invalid_xpression
template
struct invalid_xpression
: matchable_ex
{
invalid_xpression()
: matchable_ex()
{
intrusive_ptr_add_ref(this); // keep alive forever
}
bool match(match_state &) const
{
BOOST_ASSERT(false);
return false;
}
};
///////////////////////////////////////////////////////////////////////////////
// get_invalid_xpression
template
inline shared_matchable const &get_invalid_xpression()
{
static invalid_xpression const invalid_xpr;
static intrusive_ptr const> const invalid_ptr(&invalid_xpr);
static shared_matchable const invalid_matchable(invalid_ptr);
return invalid_matchable;
}
///////////////////////////////////////////////////////////////////////////////
// dynamic_xpression
template
struct dynamic_xpression
: Matcher
, matchable_ex
{
typedef typename iterator_value::type char_type;
dynamic_xpression(Matcher const &matcher = Matcher())
: Matcher(matcher)
, next_(get_invalid_xpression())
{
}
virtual bool match(match_state &state) const
{
return this->Matcher::match(state, *this->next_.matchable());
}
virtual void link(xpression_linker &linker) const
{
linker.accept(*static_cast(this), this->next_.matchable().get());
this->next_.link(linker);
}
virtual void peek(xpression_peeker &peeker) const
{
this->peek_next_(peeker.accept(*static_cast(this)), peeker);
}
virtual void repeat(quant_spec const &spec, sequence &seq) const
{
this->repeat_(spec, seq, quant_type(), is_same());
}
private:
friend struct sequence;
void peek_next_(mpl::true_, xpression_peeker &peeker) const
{
this->next_.peek(peeker);
}
void peek_next_(mpl::false_, xpression_peeker &) const
{
// no-op
}
void repeat_(quant_spec const &spec, sequence &seq, mpl::int_, mpl::false_) const
{
if(quant_none == seq.quant())
{
BOOST_THROW_EXCEPTION(
regex_error(regex_constants::error_badrepeat, "expression cannot be quantified")
);
}
else
{
this->repeat_(spec, seq, mpl::int_(), mpl::false_());
}
}
void repeat_(quant_spec const &spec, sequence &seq, mpl::int_, mpl::false_) const
{
if(this->next_ == get_invalid_xpression())
{
make_simple_repeat(spec, seq, matcher_wrapper(*this));
}
else
{
this->repeat_(spec, seq, mpl::int_(), mpl::false_());
}
}
void repeat_(quant_spec const &spec, sequence &seq, mpl::int_, mpl::false_) const
{
if(!is_unknown(seq.width()) && seq.pure())
{
make_simple_repeat(spec, seq);
}
else
{
make_repeat(spec, seq);
}
}
void repeat_(quant_spec const &spec, sequence &seq, mpl::int_, mpl::true_) const
{
make_repeat(spec, seq, this->mark_number_);
}
shared_matchable next_;
};
///////////////////////////////////////////////////////////////////////////////
// make_dynamic
template
inline sequence make_dynamic(Matcher const &matcher)
{
typedef dynamic_xpression xpression_type;
intrusive_ptr xpr(new xpression_type(matcher));
return sequence(xpr);
}
///////////////////////////////////////////////////////////////////////////////
// alternates_vector
template
struct alternates_vector
: std::vector >
{
BOOST_STATIC_CONSTANT(std::size_t, width = unknown_width::value);
BOOST_STATIC_CONSTANT(bool, pure = false);
};
///////////////////////////////////////////////////////////////////////////////
// matcher_wrapper
template
struct matcher_wrapper
: Matcher
{
matcher_wrapper(Matcher const &matcher = Matcher())
: Matcher(matcher)
{
}
template
bool match(match_state &state) const
{
return this->Matcher::match(state, matcher_wrapper());
}
template
void link(xpression_linker &linker) const
{
linker.accept(*static_cast(this), 0);
}
template
void peek(xpression_peeker &peeker) const
{
peeker.accept(*static_cast(this));
}
};
//////////////////////////////////////////////////////////////////////////
// make_simple_repeat
template
inline void
make_simple_repeat(quant_spec const &spec, sequence &seq, Xpr const &xpr)
{
if(spec.greedy_)
{
simple_repeat_matcher quant(xpr, spec.min_, spec.max_, seq.width().value());
seq = make_dynamic(quant);
}
else
{
simple_repeat_matcher quant(xpr, spec.min_, spec.max_, seq.width().value());
seq = make_dynamic(quant);
}
}
//////////////////////////////////////////////////////////////////////////
// make_simple_repeat
template
inline void
make_simple_repeat(quant_spec const &spec, sequence &seq)
{
seq += make_dynamic(true_matcher());
make_simple_repeat(spec, seq, seq.xpr());
}
//////////////////////////////////////////////////////////////////////////
// make_optional
template
inline void
make_optional(quant_spec const &spec, sequence &seq)
{
typedef shared_matchable xpr_type;
seq += make_dynamic(alternate_end_matcher());
if(spec.greedy_)
{
optional_matcher opt(seq.xpr());
seq = make_dynamic(opt);
}
else
{
optional_matcher opt(seq.xpr());
seq = make_dynamic(opt);
}
}
//////////////////////////////////////////////////////////////////////////
// make_optional
template
inline void
make_optional(quant_spec const &spec, sequence &seq, int mark_nbr)
{
typedef shared_matchable xpr_type;
seq += make_dynamic(alternate_end_matcher());
if(spec.greedy_)
{
optional_mark_matcher opt(seq.xpr(), mark_nbr);
seq = make_dynamic(opt);
}
else
{
optional_mark_matcher opt(seq.xpr(), mark_nbr);
seq = make_dynamic(opt);
}
}
//////////////////////////////////////////////////////////////////////////
// make_repeat
template
inline void
make_repeat(quant_spec const &spec, sequence &seq)
{
// only bother creating a repeater if max is greater than one
if(1 < spec.max_)
{
// create a hidden mark so this expression can be quantified
int mark_nbr = -static_cast(++*spec.hidden_mark_count_);
seq = make_dynamic(mark_begin_matcher(mark_nbr)) + seq
+ make_dynamic(mark_end_matcher(mark_nbr));
make_repeat(spec, seq, mark_nbr);
return;
}
// if min is 0, the repeat must be made optional
if(0 == spec.min_)
{
make_optional(spec, seq);
}
}
//////////////////////////////////////////////////////////////////////////
// make_repeat
template
inline void
make_repeat(quant_spec const &spec, sequence &seq, int mark_nbr)
{
BOOST_ASSERT(spec.max_); // we should never get here if max is 0
// only bother creating a repeater if max is greater than one
if(1 < spec.max_)
{
// TODO: statically bind the repeat matchers to the mark matchers for better perf
unsigned int min = spec.min_ ? spec.min_ : 1U;
repeat_begin_matcher repeat_begin(mark_nbr);
if(spec.greedy_)
{
repeat_end_matcher repeat_end(mark_nbr, min, spec.max_);
seq = make_dynamic(repeat_begin) + seq
+ make_dynamic(repeat_end);
}
else
{
repeat_end_matcher repeat_end(mark_nbr, min, spec.max_);
seq = make_dynamic(repeat_begin) + seq
+ make_dynamic(repeat_end);
}
}
// if min is 0, the repeat must be made optional
if(0 == spec.min_)
{
make_optional(spec, seq, mark_nbr);
}
}
}}} // namespace boost::xpressive::detail
#endif