Added boost header

This commit is contained in:
Christophe Riccio
2012-01-08 01:26:07 +00:00
parent 9c3faaca40
commit c7d752cdf8
8946 changed files with 1732316 additions and 0 deletions

View File

@@ -0,0 +1,337 @@
///////////////////////////////////////////////////////////////////////////////
// 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) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <vector>
#include <utility>
#include <algorithm>
#include <boost/assert.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/throw_exception.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/dynamic/matchable.hpp>
#include <boost/xpressive/detail/dynamic/sequence.hpp>
#include <boost/xpressive/detail/core/icase.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// invalid_xpression
template<typename BidiIter>
struct invalid_xpression
: matchable_ex<BidiIter>
{
invalid_xpression()
: matchable_ex<BidiIter>()
{
intrusive_ptr_add_ref(this); // keep alive forever
}
bool match(match_state<BidiIter> &) const
{
BOOST_ASSERT(false);
return false;
}
};
///////////////////////////////////////////////////////////////////////////////
// get_invalid_xpression
template<typename BidiIter>
inline shared_matchable<BidiIter> const &get_invalid_xpression()
{
static invalid_xpression<BidiIter> const invalid_xpr;
static intrusive_ptr<matchable_ex<BidiIter> const> const invalid_ptr(&invalid_xpr);
static shared_matchable<BidiIter> const invalid_matchable(invalid_ptr);
return invalid_matchable;
}
///////////////////////////////////////////////////////////////////////////////
// dynamic_xpression
template<typename Matcher, typename BidiIter>
struct dynamic_xpression
: Matcher
, matchable_ex<BidiIter>
{
typedef typename iterator_value<BidiIter>::type char_type;
dynamic_xpression(Matcher const &matcher = Matcher())
: Matcher(matcher)
, next_(get_invalid_xpression<BidiIter>())
{
}
virtual bool match(match_state<BidiIter> &state) const
{
return this->Matcher::match(state, *this->next_.matchable());
}
virtual void link(xpression_linker<char_type> &linker) const
{
linker.accept(*static_cast<Matcher const *>(this), this->next_.matchable().get());
this->next_.link(linker);
}
virtual void peek(xpression_peeker<char_type> &peeker) const
{
this->peek_next_(peeker.accept(*static_cast<Matcher const *>(this)), peeker);
}
virtual void repeat(quant_spec const &spec, sequence<BidiIter> &seq) const
{
this->repeat_(spec, seq, quant_type<Matcher>(), is_same<Matcher, mark_begin_matcher>());
}
private:
friend struct sequence<BidiIter>;
void peek_next_(mpl::true_, xpression_peeker<char_type> &peeker) const
{
this->next_.peek(peeker);
}
void peek_next_(mpl::false_, xpression_peeker<char_type> &) const
{
// no-op
}
void repeat_(quant_spec const &spec, sequence<BidiIter> &seq, mpl::int_<quant_none>, 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_<quant_variable_width>(), mpl::false_());
}
}
void repeat_(quant_spec const &spec, sequence<BidiIter> &seq, mpl::int_<quant_fixed_width>, mpl::false_) const
{
if(this->next_ == get_invalid_xpression<BidiIter>())
{
make_simple_repeat(spec, seq, matcher_wrapper<Matcher>(*this));
}
else
{
this->repeat_(spec, seq, mpl::int_<quant_variable_width>(), mpl::false_());
}
}
void repeat_(quant_spec const &spec, sequence<BidiIter> &seq, mpl::int_<quant_variable_width>, 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<BidiIter> &seq, mpl::int_<quant_fixed_width>, mpl::true_) const
{
make_repeat(spec, seq, this->mark_number_);
}
shared_matchable<BidiIter> next_;
};
///////////////////////////////////////////////////////////////////////////////
// make_dynamic
template<typename BidiIter, typename Matcher>
inline sequence<BidiIter> make_dynamic(Matcher const &matcher)
{
typedef dynamic_xpression<Matcher, BidiIter> xpression_type;
intrusive_ptr<xpression_type> xpr(new xpression_type(matcher));
return sequence<BidiIter>(xpr);
}
///////////////////////////////////////////////////////////////////////////////
// alternates_vector
template<typename BidiIter>
struct alternates_vector
: std::vector<shared_matchable<BidiIter> >
{
BOOST_STATIC_CONSTANT(std::size_t, width = unknown_width::value);
BOOST_STATIC_CONSTANT(bool, pure = false);
};
///////////////////////////////////////////////////////////////////////////////
// matcher_wrapper
template<typename Matcher>
struct matcher_wrapper
: Matcher
{
matcher_wrapper(Matcher const &matcher = Matcher())
: Matcher(matcher)
{
}
template<typename BidiIter>
bool match(match_state<BidiIter> &state) const
{
return this->Matcher::match(state, matcher_wrapper<true_matcher>());
}
template<typename Char>
void link(xpression_linker<Char> &linker) const
{
linker.accept(*static_cast<Matcher const *>(this), 0);
}
template<typename Char>
void peek(xpression_peeker<Char> &peeker) const
{
peeker.accept(*static_cast<Matcher const *>(this));
}
};
//////////////////////////////////////////////////////////////////////////
// make_simple_repeat
template<typename BidiIter, typename Xpr>
inline void
make_simple_repeat(quant_spec const &spec, sequence<BidiIter> &seq, Xpr const &xpr)
{
if(spec.greedy_)
{
simple_repeat_matcher<Xpr, mpl::true_> quant(xpr, spec.min_, spec.max_, seq.width().value());
seq = make_dynamic<BidiIter>(quant);
}
else
{
simple_repeat_matcher<Xpr, mpl::false_> quant(xpr, spec.min_, spec.max_, seq.width().value());
seq = make_dynamic<BidiIter>(quant);
}
}
//////////////////////////////////////////////////////////////////////////
// make_simple_repeat
template<typename BidiIter>
inline void
make_simple_repeat(quant_spec const &spec, sequence<BidiIter> &seq)
{
seq += make_dynamic<BidiIter>(true_matcher());
make_simple_repeat(spec, seq, seq.xpr());
}
//////////////////////////////////////////////////////////////////////////
// make_optional
template<typename BidiIter>
inline void
make_optional(quant_spec const &spec, sequence<BidiIter> &seq)
{
typedef shared_matchable<BidiIter> xpr_type;
seq += make_dynamic<BidiIter>(alternate_end_matcher());
if(spec.greedy_)
{
optional_matcher<xpr_type, mpl::true_> opt(seq.xpr());
seq = make_dynamic<BidiIter>(opt);
}
else
{
optional_matcher<xpr_type, mpl::false_> opt(seq.xpr());
seq = make_dynamic<BidiIter>(opt);
}
}
//////////////////////////////////////////////////////////////////////////
// make_optional
template<typename BidiIter>
inline void
make_optional(quant_spec const &spec, sequence<BidiIter> &seq, int mark_nbr)
{
typedef shared_matchable<BidiIter> xpr_type;
seq += make_dynamic<BidiIter>(alternate_end_matcher());
if(spec.greedy_)
{
optional_mark_matcher<xpr_type, mpl::true_> opt(seq.xpr(), mark_nbr);
seq = make_dynamic<BidiIter>(opt);
}
else
{
optional_mark_matcher<xpr_type, mpl::false_> opt(seq.xpr(), mark_nbr);
seq = make_dynamic<BidiIter>(opt);
}
}
//////////////////////////////////////////////////////////////////////////
// make_repeat
template<typename BidiIter>
inline void
make_repeat(quant_spec const &spec, sequence<BidiIter> &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<int>(++*spec.hidden_mark_count_);
seq = make_dynamic<BidiIter>(mark_begin_matcher(mark_nbr)) + seq
+ make_dynamic<BidiIter>(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<typename BidiIter>
inline void
make_repeat(quant_spec const &spec, sequence<BidiIter> &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<mpl::true_> repeat_end(mark_nbr, min, spec.max_);
seq = make_dynamic<BidiIter>(repeat_begin) + seq
+ make_dynamic<BidiIter>(repeat_end);
}
else
{
repeat_end_matcher<mpl::false_> repeat_end(mark_nbr, min, spec.max_);
seq = make_dynamic<BidiIter>(repeat_begin) + seq
+ make_dynamic<BidiIter>(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

View File

@@ -0,0 +1,177 @@
///////////////////////////////////////////////////////////////////////////////
// matchable.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_MATCHABLE_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_DYNAMIC_MATCHABLE_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/assert.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/throw_exception.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/utility/counted_base.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/dynamic/sequence.hpp>
#include <boost/xpressive/regex_error.hpp>
namespace boost { namespace xpressive { namespace detail
{
//////////////////////////////////////////////////////////////////////////
// quant_spec
struct quant_spec
{
unsigned int min_;
unsigned int max_;
bool greedy_;
std::size_t *hidden_mark_count_;
};
///////////////////////////////////////////////////////////////////////////////
// matchable
template<typename BidiIter>
struct matchable
{
typedef BidiIter iterator_type;
typedef typename iterator_value<iterator_type>::type char_type;
virtual ~matchable() {}
virtual bool match(match_state<BidiIter> &state) const = 0;
};
///////////////////////////////////////////////////////////////////////////////
// matchable_ex
template<typename BidiIter>
struct matchable_ex
: matchable<BidiIter>
, counted_base<matchable_ex<BidiIter> >
{
typedef BidiIter iterator_type;
typedef typename iterator_value<iterator_type>::type char_type;
virtual void link(xpression_linker<char_type> &) const
{
}
virtual void peek(xpression_peeker<char_type> &peeker) const
{
peeker.fail();
}
virtual void repeat(quant_spec const &, sequence<BidiIter> &) const
{
BOOST_THROW_EXCEPTION(
regex_error(regex_constants::error_badrepeat, "expression cannot be quantified")
);
}
///////////////////////////////////////////////////////////////////////////////////////////////
// The following 4 functions (push_match, top_match, pop_match and skip_match) are
// used to implement looping and branching across the matchers. Call push_match to record
// a position. Then, another matcher further down the xpression chain has the
// option to call either top_match, pop_match or skip_match. top_match and pop_match will
// jump back to the place recorded by push_match, whereas skip_match will skip the jump and
// pass execution down the xpression chain. top_match will leave the xpression on top of the
// stack, whereas pop_match will remove it. Each function comes in 2 flavors: one for
// statically bound xpressions and one for dynamically bound xpressions.
//
template<typename Top>
bool push_match(match_state<BidiIter> &state) const
{
BOOST_MPL_ASSERT((is_same<Top, matchable_ex<BidiIter> >));
return this->match(state);
}
static bool top_match(match_state<BidiIter> &state, void const *top)
{
return static_cast<matchable_ex<BidiIter> const *>(top)->match(state);
}
static bool pop_match(match_state<BidiIter> &state, void const *top)
{
return static_cast<matchable_ex<BidiIter> const *>(top)->match(state);
}
bool skip_match(match_state<BidiIter> &state) const
{
return this->match(state);
}
};
///////////////////////////////////////////////////////////////////////////////
// shared_matchable
template<typename BidiIter>
struct shared_matchable
{
typedef BidiIter iterator_type;
typedef typename iterator_value<BidiIter>::type char_type;
typedef intrusive_ptr<matchable_ex<BidiIter> const> matchable_ptr;
BOOST_STATIC_CONSTANT(std::size_t, width = unknown_width::value);
BOOST_STATIC_CONSTANT(bool, pure = false);
shared_matchable(matchable_ptr const &xpr = matchable_ptr())
: xpr_(xpr)
{
}
bool operator !() const
{
return !this->xpr_;
}
friend bool operator ==(shared_matchable<BidiIter> const &left, shared_matchable<BidiIter> const &right)
{
return left.xpr_ == right.xpr_;
}
friend bool operator !=(shared_matchable<BidiIter> const &left, shared_matchable<BidiIter> const &right)
{
return left.xpr_ != right.xpr_;
}
matchable_ptr const &matchable() const
{
return this->xpr_;
}
bool match(match_state<BidiIter> &state) const
{
return this->xpr_->match(state);
}
void link(xpression_linker<char_type> &linker) const
{
this->xpr_->link(linker);
}
void peek(xpression_peeker<char_type> &peeker) const
{
this->xpr_->peek(peeker);
}
// BUGBUG yuk!
template<typename Top>
bool push_match(match_state<BidiIter> &state) const
{
BOOST_MPL_ASSERT((is_same<Top, matchable_ex<BidiIter> >));
return this->match(state);
}
private:
matchable_ptr xpr_;
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,365 @@
///////////////////////////////////////////////////////////////////////////////
// parse_charset.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_PARSE_CHARSET_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSE_CHARSET_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/integer.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/throw_exception.hpp>
#include <boost/numeric/conversion/converter.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/dynamic/parser_enum.hpp>
#include <boost/xpressive/detail/utility/literals.hpp>
#include <boost/xpressive/detail/utility/chset/chset.hpp>
#include <boost/xpressive/regex_constants.hpp>
namespace boost { namespace xpressive { namespace detail
{
enum escape_type
{
escape_char
, escape_mark
, escape_class
};
///////////////////////////////////////////////////////////////////////////////
// escape_value
//
template<typename Char, typename Class>
struct escape_value
{
Char ch_;
int mark_nbr_;
Class class_;
escape_type type_;
};
///////////////////////////////////////////////////////////////////////////////
// char_overflow_handler
//
struct char_overflow_handler
{
void operator ()(numeric::range_check_result result) const // throw(regex_error)
{
if(numeric::cInRange != result)
{
BOOST_THROW_EXCEPTION(
regex_error(
regex_constants::error_escape
, "character escape too large to fit in target character type"
)
);
}
}
};
///////////////////////////////////////////////////////////////////////////////
// parse_escape
//
template<typename FwdIter, typename CompilerTraits>
escape_value<typename iterator_value<FwdIter>::type, typename CompilerTraits::regex_traits::char_class_type>
parse_escape(FwdIter &begin, FwdIter end, CompilerTraits &tr)
{
using namespace regex_constants;
typedef typename iterator_value<FwdIter>::type char_type;
typedef typename CompilerTraits::regex_traits regex_traits;
typedef typename regex_traits::char_class_type char_class_type;
// define an unsigned type the same size as char_type
typedef typename boost::uint_t<CHAR_BIT * sizeof(char_type)>::least uchar_t;
BOOST_MPL_ASSERT_RELATION(sizeof(uchar_t), ==, sizeof(char_type));
typedef numeric::conversion_traits<uchar_t, int> converstion_traits;
BOOST_XPR_ENSURE_(begin != end, error_escape, "unexpected end of pattern found");
numeric::converter<int, uchar_t, converstion_traits, char_overflow_handler> converter;
escape_value<char_type,char_class_type> esc = { 0, 0, 0, escape_char };
bool const icase = (0 != (regex_constants::icase_ & tr.flags()));
regex_traits const &rxtraits = tr.traits();
FwdIter tmp;
esc.class_ = rxtraits.lookup_classname(begin, begin + 1, icase);
if(0 != esc.class_)
{
esc.type_ = escape_class;
return esc;
}
if(-1 != rxtraits.value(*begin, 8))
{
esc.ch_ = converter(toi(begin, end, rxtraits, 8, 0777));
return esc;
}
switch(*begin)
{
// bell character
case BOOST_XPR_CHAR_(char_type, 'a'):
esc.ch_ = BOOST_XPR_CHAR_(char_type, '\a');
++begin;
break;
// escape character
case BOOST_XPR_CHAR_(char_type, 'e'):
esc.ch_ = converter(27);
++begin;
break;
// control character
case BOOST_XPR_CHAR_(char_type, 'c'):
BOOST_XPR_ENSURE_(++begin != end, error_escape, "unexpected end of pattern found");
BOOST_XPR_ENSURE_
(
rxtraits.in_range(BOOST_XPR_CHAR_(char_type, 'a'), BOOST_XPR_CHAR_(char_type, 'z'), *begin)
|| rxtraits.in_range(BOOST_XPR_CHAR_(char_type, 'A'), BOOST_XPR_CHAR_(char_type, 'Z'), *begin)
, error_escape
, "invalid escape control letter; must be one of a-z or A-Z"
);
// Convert to character according to ECMA-262, section 15.10.2.10:
esc.ch_ = converter(*begin % 32);
++begin;
break;
// formfeed character
case BOOST_XPR_CHAR_(char_type, 'f'):
esc.ch_ = BOOST_XPR_CHAR_(char_type, '\f');
++begin;
break;
// newline
case BOOST_XPR_CHAR_(char_type, 'n'):
esc.ch_ = BOOST_XPR_CHAR_(char_type, '\n');
++begin;
break;
// return
case BOOST_XPR_CHAR_(char_type, 'r'):
esc.ch_ = BOOST_XPR_CHAR_(char_type, '\r');
++begin;
break;
// horizontal tab
case BOOST_XPR_CHAR_(char_type, 't'):
esc.ch_ = BOOST_XPR_CHAR_(char_type, '\t');
++begin;
break;
// vertical tab
case BOOST_XPR_CHAR_(char_type, 'v'):
esc.ch_ = BOOST_XPR_CHAR_(char_type, '\v');
++begin;
break;
// hex escape sequence
case BOOST_XPR_CHAR_(char_type, 'x'):
BOOST_XPR_ENSURE_(++begin != end, error_escape, "unexpected end of pattern found");
tmp = begin;
esc.ch_ = converter(toi(begin, end, rxtraits, 16, 0xff));
BOOST_XPR_ENSURE_(2 == std::distance(tmp, begin), error_escape, "invalid hex escape : "
"must be \\x HexDigit HexDigit");
break;
// Unicode escape sequence
case BOOST_XPR_CHAR_(char_type, 'u'):
BOOST_XPR_ENSURE_(++begin != end, error_escape, "unexpected end of pattern found");
tmp = begin;
esc.ch_ = converter(toi(begin, end, rxtraits, 16, 0xffff));
BOOST_XPR_ENSURE_(4 == std::distance(tmp, begin), error_escape, "invalid Unicode escape : "
"must be \\u HexDigit HexDigit HexDigit HexDigit");
break;
// backslash
case BOOST_XPR_CHAR_(char_type, '\\'):
//esc.ch_ = BOOST_XPR_CHAR_(char_type, '\\');
//++begin;
//break;
// all other escaped characters represent themselves
default:
esc.ch_ = *begin;
++begin;
break;
}
return esc;
}
//////////////////////////////////////////////////////////////////////////
// parse_charset
//
template<typename FwdIter, typename RegexTraits, typename CompilerTraits>
inline void parse_charset
(
FwdIter &begin
, FwdIter end
, compound_charset<RegexTraits> &chset
, CompilerTraits &tr
)
{
using namespace regex_constants;
typedef typename RegexTraits::char_type char_type;
typedef typename RegexTraits::char_class_type char_class_type;
BOOST_ASSERT(begin != end);
RegexTraits const &rxtraits = tr.traits();
bool const icase = (0 != (regex_constants::icase_ & tr.flags()));
FwdIter iprev = FwdIter();
escape_value<char_type, char_class_type> esc = {0, 0, 0, escape_char};
bool invert = false;
// check to see if we have an inverse charset
if(begin != end && token_charset_invert == tr.get_charset_token(iprev = begin, end))
{
begin = iprev;
invert = true;
}
// skip the end token if-and-only-if it is the first token in the charset
if(begin != end && token_charset_end == tr.get_charset_token(iprev = begin, end))
{
for(; begin != iprev; ++begin)
{
chset.set_char(*begin, rxtraits, icase);
}
}
compiler_token_type tok;
char_type ch_prev = char_type(), ch_next = char_type();
bool have_prev = false;
BOOST_XPR_ENSURE_(begin != end, error_brack, "unexpected end of pattern found");
// remember the current position and grab the next token
iprev = begin;
tok = tr.get_charset_token(begin, end);
do
{
BOOST_XPR_ENSURE_(begin != end, error_brack, "unexpected end of pattern found");
if(token_charset_hyphen == tok && have_prev)
{
// remember the current position
FwdIter iprev2 = begin;
have_prev = false;
// ch_prev is lower bound of a range
switch(tr.get_charset_token(begin, end))
{
case token_charset_hyphen:
case token_charset_invert:
begin = iprev2; // un-get these tokens and fall through
case token_literal:
ch_next = *begin++;
BOOST_XPR_ENSURE_(ch_prev <= ch_next, error_range, "invalid charset range");
chset.set_range(ch_prev, ch_next, rxtraits, icase);
continue;
case token_charset_backspace:
ch_next = char_type(8); // backspace
BOOST_XPR_ENSURE_(ch_prev <= ch_next, error_range, "invalid charset range");
chset.set_range(ch_prev, ch_next, rxtraits, icase);
continue;
case token_escape:
esc = parse_escape(begin, end, tr);
if(escape_char == esc.type_)
{
BOOST_XPR_ENSURE_(ch_prev <= esc.ch_, error_range, "invalid charset range");
chset.set_range(ch_prev, esc.ch_, rxtraits, icase);
continue;
}
case token_charset_end: // fall through
default: // not a range.
begin = iprev; // backup to hyphen token
chset.set_char(ch_prev, rxtraits, icase);
chset.set_char(*begin++, rxtraits, icase);
continue;
}
}
if(have_prev)
{
chset.set_char(ch_prev, rxtraits, icase);
have_prev = false;
}
switch(tok)
{
case token_charset_hyphen:
case token_charset_invert:
case token_charset_end:
case token_posix_charset_end:
begin = iprev; // un-get these tokens
ch_prev = *begin++;
have_prev = true;
continue;
case token_charset_backspace:
ch_prev = char_type(8); // backspace
have_prev = true;
continue;
case token_posix_charset_begin:
{
FwdIter tmp = begin, start = begin;
bool invert = (token_charset_invert == tr.get_charset_token(tmp, end));
if(invert)
{
begin = start = tmp;
}
while(token_literal == (tok = tr.get_charset_token(begin, end)))
{
tmp = ++begin;
BOOST_XPR_ENSURE_(begin != end, error_brack, "unexpected end of pattern found");
}
if(token_posix_charset_end == tok)
{
char_class_type chclass = rxtraits.lookup_classname(start, tmp, icase);
BOOST_XPR_ENSURE_(0 != chclass, error_ctype, "unknown class name");
chset.set_class(chclass, invert);
continue;
}
begin = iprev; // un-get this token
ch_prev = *begin++;
have_prev = true;
}
continue;
case token_escape:
esc = parse_escape(begin, end, tr);
if(escape_char == esc.type_)
{
ch_prev = esc.ch_;
have_prev = true;
}
else if(escape_class == esc.type_)
{
char_class_type upper_ = lookup_classname(rxtraits, "upper");
BOOST_ASSERT(0 != upper_);
chset.set_class(esc.class_, rxtraits.isctype(*begin++, upper_));
}
else
{
BOOST_ASSERT(false);
}
continue;
default:
ch_prev = *begin++;
have_prev = true;
continue;
}
}
while(BOOST_XPR_ENSURE_((iprev = begin) != end, error_brack, "unexpected end of pattern found"),
token_charset_end != (tok = tr.get_charset_token(begin, end)));
if(have_prev)
{
chset.set_char(ch_prev, rxtraits, icase);
}
if(invert)
{
chset.inverse();
}
}
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,360 @@
///////////////////////////////////////////////////////////////////////////////
/// \file parser.hpp
/// Contains the definition of regex_compiler, a factory for building regex objects
/// from strings.
//
// 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_PARSER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
# pragma warning(push)
# pragma warning(disable : 4127) // conditional expression is constant
#endif
#include <boost/assert.hpp>
#include <boost/xpressive/regex_constants.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/matchers.hpp>
#include <boost/xpressive/detail/utility/ignore_unused.hpp>
#include <boost/xpressive/detail/dynamic/dynamic.hpp>
// The Regular Expression grammar, in pseudo BNF:
//
// expression = alternates ;
//
// alternates = sequence, *('|', sequence) ;
//
// sequence = quant, *(quant) ;
//
// quant = atom, [*+?] ;
//
// atom = literal |
// '.' |
// '\' any |
// '(' expression ')' ;
//
// literal = not a meta-character ;
//
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// make_char_xpression
//
template<typename BidiIter, typename Char, typename Traits>
inline sequence<BidiIter> make_char_xpression
(
Char ch
, regex_constants::syntax_option_type flags
, Traits const &tr
)
{
if(0 != (regex_constants::icase_ & flags))
{
literal_matcher<Traits, mpl::true_, mpl::false_> matcher(ch, tr);
return make_dynamic<BidiIter>(matcher);
}
else
{
literal_matcher<Traits, mpl::false_, mpl::false_> matcher(ch, tr);
return make_dynamic<BidiIter>(matcher);
}
}
///////////////////////////////////////////////////////////////////////////////
// make_any_xpression
//
template<typename BidiIter, typename Traits>
inline sequence<BidiIter> make_any_xpression
(
regex_constants::syntax_option_type flags
, Traits const &tr
)
{
using namespace regex_constants;
typedef typename iterator_value<BidiIter>::type char_type;
typedef detail::set_matcher<Traits, mpl::int_<2> > set_matcher;
typedef literal_matcher<Traits, mpl::false_, mpl::true_> literal_matcher;
char_type const newline = tr.widen('\n');
set_matcher s;
s.set_[0] = newline;
s.set_[1] = 0;
s.inverse();
switch(((int)not_dot_newline | not_dot_null) & flags)
{
case not_dot_null:
return make_dynamic<BidiIter>(literal_matcher(char_type(0), tr));
case not_dot_newline:
return make_dynamic<BidiIter>(literal_matcher(newline, tr));
case (int)not_dot_newline | not_dot_null:
return make_dynamic<BidiIter>(s);
default:
return make_dynamic<BidiIter>(any_matcher());
}
}
///////////////////////////////////////////////////////////////////////////////
// make_literal_xpression
//
template<typename BidiIter, typename Traits>
inline sequence<BidiIter> make_literal_xpression
(
typename Traits::string_type const &literal
, regex_constants::syntax_option_type flags
, Traits const &tr
)
{
BOOST_ASSERT(0 != literal.size());
if(1 == literal.size())
{
return make_char_xpression<BidiIter>(literal[0], flags, tr);
}
if(0 != (regex_constants::icase_ & flags))
{
string_matcher<Traits, mpl::true_> matcher(literal, tr);
return make_dynamic<BidiIter>(matcher);
}
else
{
string_matcher<Traits, mpl::false_> matcher(literal, tr);
return make_dynamic<BidiIter>(matcher);
}
}
///////////////////////////////////////////////////////////////////////////////
// make_backref_xpression
//
template<typename BidiIter, typename Traits>
inline sequence<BidiIter> make_backref_xpression
(
int mark_nbr
, regex_constants::syntax_option_type flags
, Traits const &tr
)
{
if(0 != (regex_constants::icase_ & flags))
{
return make_dynamic<BidiIter>
(
mark_matcher<Traits, mpl::true_>(mark_nbr, tr)
);
}
else
{
return make_dynamic<BidiIter>
(
mark_matcher<Traits, mpl::false_>(mark_nbr, tr)
);
}
}
///////////////////////////////////////////////////////////////////////////////
// merge_charset
//
template<typename Char, typename Traits>
inline void merge_charset
(
basic_chset<Char> &basic
, compound_charset<Traits> const &compound
, Traits const &tr
)
{
detail::ignore_unused(tr);
if(0 != compound.posix_yes())
{
typename Traits::char_class_type mask = compound.posix_yes();
for(int i = 0; i <= static_cast<int>(UCHAR_MAX); ++i)
{
if(tr.isctype((Char)i, mask))
{
basic.set((Char)i);
}
}
}
if(!compound.posix_no().empty())
{
for(std::size_t j = 0; j < compound.posix_no().size(); ++j)
{
typename Traits::char_class_type mask = compound.posix_no()[j];
for(int i = 0; i <= static_cast<int>(UCHAR_MAX); ++i)
{
if(!tr.isctype((Char)i, mask))
{
basic.set((Char)i);
}
}
}
}
if(compound.is_inverted())
{
basic.inverse();
}
}
///////////////////////////////////////////////////////////////////////////////
// make_charset_xpression
//
template<typename BidiIter, typename Traits>
inline sequence<BidiIter> make_charset_xpression
(
compound_charset<Traits> &chset
, Traits const &tr
, regex_constants::syntax_option_type flags
)
{
typedef typename Traits::char_type char_type;
bool const icase = (0 != (regex_constants::icase_ & flags));
bool const optimize = is_narrow_char<char_type>::value && 0 != (regex_constants::optimize & flags);
// don't care about compile speed -- fold eveything into a bitset<256>
if(optimize)
{
typedef basic_chset<char_type> charset_type;
charset_type charset(chset.base());
if(icase)
{
charset_matcher<Traits, mpl::true_, charset_type> matcher(charset);
merge_charset(matcher.charset_, chset, tr);
return make_dynamic<BidiIter>(matcher);
}
else
{
charset_matcher<Traits, mpl::false_, charset_type> matcher(charset);
merge_charset(matcher.charset_, chset, tr);
return make_dynamic<BidiIter>(matcher);
}
}
// special case to make [[:digit:]] fast
else if(chset.base().empty() && chset.posix_no().empty())
{
BOOST_ASSERT(0 != chset.posix_yes());
posix_charset_matcher<Traits> matcher(chset.posix_yes(), chset.is_inverted());
return make_dynamic<BidiIter>(matcher);
}
// default, slow
else
{
if(icase)
{
charset_matcher<Traits, mpl::true_> matcher(chset);
return make_dynamic<BidiIter>(matcher);
}
else
{
charset_matcher<Traits, mpl::false_> matcher(chset);
return make_dynamic<BidiIter>(matcher);
}
}
}
///////////////////////////////////////////////////////////////////////////////
// make_posix_charset_xpression
//
template<typename BidiIter, typename Traits>
inline sequence<BidiIter> make_posix_charset_xpression
(
typename Traits::char_class_type m
, bool no
, regex_constants::syntax_option_type //flags
, Traits const & //traits
)
{
posix_charset_matcher<Traits> charset(m, no);
return make_dynamic<BidiIter>(charset);
}
///////////////////////////////////////////////////////////////////////////////
// make_assert_begin_line
//
template<typename BidiIter, typename Traits>
inline sequence<BidiIter> make_assert_begin_line
(
regex_constants::syntax_option_type flags
, Traits const &tr
)
{
if(0 != (regex_constants::single_line & flags))
{
return detail::make_dynamic<BidiIter>(detail::assert_bos_matcher());
}
else
{
detail::assert_bol_matcher<Traits> matcher(tr);
return detail::make_dynamic<BidiIter>(matcher);
}
}
///////////////////////////////////////////////////////////////////////////////
// make_assert_end_line
//
template<typename BidiIter, typename Traits>
inline sequence<BidiIter> make_assert_end_line
(
regex_constants::syntax_option_type flags
, Traits const &tr
)
{
if(0 != (regex_constants::single_line & flags))
{
return detail::make_dynamic<BidiIter>(detail::assert_eos_matcher());
}
else
{
detail::assert_eol_matcher<Traits> matcher(tr);
return detail::make_dynamic<BidiIter>(matcher);
}
}
///////////////////////////////////////////////////////////////////////////////
// make_assert_word
//
template<typename BidiIter, typename Cond, typename Traits>
inline sequence<BidiIter> make_assert_word(Cond, Traits const &tr)
{
typedef typename iterator_value<BidiIter>::type char_type;
return detail::make_dynamic<BidiIter>
(
detail::assert_word_matcher<Cond, Traits>(tr)
);
}
///////////////////////////////////////////////////////////////////////////////
// make_independent_end_xpression
//
template<typename BidiIter>
inline sequence<BidiIter> make_independent_end_xpression(bool pure)
{
if(pure)
{
return detail::make_dynamic<BidiIter>(detail::true_matcher());
}
else
{
return detail::make_dynamic<BidiIter>(detail::independent_end_matcher());
}
}
}}} // namespace boost::xpressive::detail
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma warning(pop)
#endif
#endif

View File

@@ -0,0 +1,81 @@
///////////////////////////////////////////////////////////////////////////////
// parser_enum.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_PARSER_ENUM_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSER_ENUM_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
namespace boost { namespace xpressive { namespace regex_constants
{
///////////////////////////////////////////////////////////////////////////////
// compiler_token_type
//
enum compiler_token_type
{
token_literal,
token_any, // .
token_escape, //
token_group_begin, // (
token_group_end, // )
token_alternate, // |
token_invalid_quantifier, // {
token_charset_begin, // [
token_charset_end, // ]
token_charset_invert, // ^
token_charset_hyphen, // -
token_charset_backspace, // \b
token_posix_charset_begin, // [:
token_posix_charset_end, // :]
token_equivalence_class_begin, // [=
token_equivalence_class_end, // =]
token_collation_element_begin, // [.
token_collation_element_end, // .]
token_quote_meta_begin, // \Q
token_quote_meta_end, // \E
token_no_mark, // ?:
token_positive_lookahead, // ?=
token_negative_lookahead, // ?!
token_positive_lookbehind, // ?<=
token_negative_lookbehind, // ?<!
token_independent_sub_expression, // ?>
token_comment, // ?#
token_recurse, // ?R
token_rule_assign, // ?$[name]=
token_rule_ref, // ?$[name]
token_named_mark, // ?P<name>
token_named_mark_ref, // ?P=name
token_assert_begin_sequence, // \A
token_assert_end_sequence, // \Z
token_assert_begin_line, // ^
token_assert_end_line, // $
token_assert_word_begin, // \<
token_assert_word_end, // \>
token_assert_word_boundary, // \b
token_assert_not_word_boundary, // \B
token_escape_newline, // \n
token_escape_escape, // \e
token_escape_formfeed, // \f
token_escape_horizontal_tab, // \t
token_escape_vertical_tab, // \v
token_escape_bell, // \a
token_escape_control, // \c
token_end_of_pattern
};
}}} // namespace boost::xpressive::regex_constants
#endif

View File

@@ -0,0 +1,474 @@
///////////////////////////////////////////////////////////////////////////////
// detail/dynamic/parser_traits.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_PARSER_TRAITS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_DYNAMIC_PARSER_TRAITS_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <string>
#include <climits>
#include <boost/assert.hpp>
#include <boost/throw_exception.hpp>
#include <boost/xpressive/regex_error.hpp>
#include <boost/xpressive/regex_traits.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/dynamic/matchable.hpp>
#include <boost/xpressive/detail/dynamic/parser_enum.hpp>
#include <boost/xpressive/detail/utility/literals.hpp>
#include <boost/xpressive/detail/utility/algorithm.hpp>
namespace boost { namespace xpressive
{
///////////////////////////////////////////////////////////////////////////////
// compiler_traits
// this works for char and wchar_t. it must be specialized for anything else.
//
template<typename RegexTraits>
struct compiler_traits
{
typedef RegexTraits regex_traits;
typedef typename regex_traits::char_type char_type;
typedef typename regex_traits::string_type string_type;
typedef typename regex_traits::locale_type locale_type;
///////////////////////////////////////////////////////////////////////////////
// constructor
explicit compiler_traits(RegexTraits const &traits = RegexTraits())
: traits_(traits)
, flags_(regex_constants::ECMAScript)
, space_(lookup_classname(traits_, "space"))
, alnum_(lookup_classname(traits_, "alnum"))
{
}
///////////////////////////////////////////////////////////////////////////////
// flags
regex_constants::syntax_option_type flags() const
{
return this->flags_;
}
///////////////////////////////////////////////////////////////////////////////
// flags
void flags(regex_constants::syntax_option_type flags)
{
this->flags_ = flags;
}
///////////////////////////////////////////////////////////////////////////////
// traits
regex_traits &traits()
{
return this->traits_;
}
regex_traits const &traits() const
{
return this->traits_;
}
///////////////////////////////////////////////////////////////////////////////
// imbue
locale_type imbue(locale_type const &loc)
{
locale_type oldloc = this->traits().imbue(loc);
this->space_ = lookup_classname(this->traits(), "space");
this->alnum_ = lookup_classname(this->traits(), "alnum");
return oldloc;
}
///////////////////////////////////////////////////////////////////////////////
// getloc
locale_type getloc() const
{
return this->traits().getloc();
}
///////////////////////////////////////////////////////////////////////////////
// get_token
// get a token and advance the iterator
template<typename FwdIter>
regex_constants::compiler_token_type get_token(FwdIter &begin, FwdIter end)
{
using namespace regex_constants;
if(this->eat_ws_(begin, end) == end)
{
return regex_constants::token_end_of_pattern;
}
switch(*begin)
{
case BOOST_XPR_CHAR_(char_type, '\\'): return this->get_escape_token(++begin, end);
case BOOST_XPR_CHAR_(char_type, '.'): ++begin; return token_any;
case BOOST_XPR_CHAR_(char_type, '^'): ++begin; return token_assert_begin_line;
case BOOST_XPR_CHAR_(char_type, '$'): ++begin; return token_assert_end_line;
case BOOST_XPR_CHAR_(char_type, '('): ++begin; return token_group_begin;
case BOOST_XPR_CHAR_(char_type, ')'): ++begin; return token_group_end;
case BOOST_XPR_CHAR_(char_type, '|'): ++begin; return token_alternate;
case BOOST_XPR_CHAR_(char_type, '['): ++begin; return token_charset_begin;
case BOOST_XPR_CHAR_(char_type, '*'):
case BOOST_XPR_CHAR_(char_type, '+'):
case BOOST_XPR_CHAR_(char_type, '?'):
return token_invalid_quantifier;
case BOOST_XPR_CHAR_(char_type, ']'):
case BOOST_XPR_CHAR_(char_type, '{'):
default:
return token_literal;
}
}
///////////////////////////////////////////////////////////////////////////////
// get_quant_spec
template<typename FwdIter>
bool get_quant_spec(FwdIter &begin, FwdIter end, detail::quant_spec &spec)
{
using namespace regex_constants;
FwdIter old_begin;
if(this->eat_ws_(begin, end) == end)
{
return false;
}
switch(*begin)
{
case BOOST_XPR_CHAR_(char_type, '*'):
spec.min_ = 0;
spec.max_ = (std::numeric_limits<unsigned int>::max)();
break;
case BOOST_XPR_CHAR_(char_type, '+'):
spec.min_ = 1;
spec.max_ = (std::numeric_limits<unsigned int>::max)();
break;
case BOOST_XPR_CHAR_(char_type, '?'):
spec.min_ = 0;
spec.max_ = 1;
break;
case BOOST_XPR_CHAR_(char_type, '{'):
old_begin = this->eat_ws_(++begin, end);
spec.min_ = spec.max_ = detail::toi(begin, end, this->traits());
BOOST_XPR_ENSURE_
(
begin != old_begin && begin != end, error_brace, "invalid quantifier"
);
if(*begin == BOOST_XPR_CHAR_(char_type, ','))
{
old_begin = this->eat_ws_(++begin, end);
spec.max_ = detail::toi(begin, end, this->traits());
BOOST_XPR_ENSURE_
(
begin != end && BOOST_XPR_CHAR_(char_type, '}') == *begin
, error_brace, "invalid quantifier"
);
if(begin == old_begin)
{
spec.max_ = (std::numeric_limits<unsigned int>::max)();
}
else
{
BOOST_XPR_ENSURE_
(
spec.min_ <= spec.max_, error_badbrace, "invalid quantification range"
);
}
}
else
{
BOOST_XPR_ENSURE_
(
BOOST_XPR_CHAR_(char_type, '}') == *begin, error_brace, "invalid quantifier"
);
}
break;
default:
return false;
}
spec.greedy_ = true;
if(this->eat_ws_(++begin, end) != end && BOOST_XPR_CHAR_(char_type, '?') == *begin)
{
++begin;
spec.greedy_ = false;
}
return true;
}
///////////////////////////////////////////////////////////////////////////
// get_group_type
template<typename FwdIter>
regex_constants::compiler_token_type get_group_type(FwdIter &begin, FwdIter end, string_type &name)
{
using namespace regex_constants;
if(this->eat_ws_(begin, end) != end && BOOST_XPR_CHAR_(char_type, '?') == *begin)
{
this->eat_ws_(++begin, end);
BOOST_XPR_ENSURE_(begin != end, error_paren, "incomplete extension");
switch(*begin)
{
case BOOST_XPR_CHAR_(char_type, ':'): ++begin; return token_no_mark;
case BOOST_XPR_CHAR_(char_type, '>'): ++begin; return token_independent_sub_expression;
case BOOST_XPR_CHAR_(char_type, '#'): ++begin; return token_comment;
case BOOST_XPR_CHAR_(char_type, '='): ++begin; return token_positive_lookahead;
case BOOST_XPR_CHAR_(char_type, '!'): ++begin; return token_negative_lookahead;
case BOOST_XPR_CHAR_(char_type, 'R'): ++begin; return token_recurse;
case BOOST_XPR_CHAR_(char_type, '$'):
this->get_name_(++begin, end, name);
BOOST_XPR_ENSURE_(begin != end, error_paren, "incomplete extension");
if(BOOST_XPR_CHAR_(char_type, '=') == *begin)
{
++begin;
return token_rule_assign;
}
return token_rule_ref;
case BOOST_XPR_CHAR_(char_type, '<'):
this->eat_ws_(++begin, end);
BOOST_XPR_ENSURE_(begin != end, error_paren, "incomplete extension");
switch(*begin)
{
case BOOST_XPR_CHAR_(char_type, '='): ++begin; return token_positive_lookbehind;
case BOOST_XPR_CHAR_(char_type, '!'): ++begin; return token_negative_lookbehind;
default:
BOOST_THROW_EXCEPTION(regex_error(error_badbrace, "unrecognized extension"));
}
case BOOST_XPR_CHAR_(char_type, 'P'):
this->eat_ws_(++begin, end);
BOOST_XPR_ENSURE_(begin != end, error_paren, "incomplete extension");
switch(*begin)
{
case BOOST_XPR_CHAR_(char_type, '<'):
this->get_name_(++begin, end, name);
BOOST_XPR_ENSURE_(begin != end && BOOST_XPR_CHAR_(char_type, '>') == *begin++, error_paren, "incomplete extension");
return token_named_mark;
case BOOST_XPR_CHAR_(char_type, '='):
this->get_name_(++begin, end, name);
BOOST_XPR_ENSURE_(begin != end, error_paren, "incomplete extension");
return token_named_mark_ref;
default:
BOOST_THROW_EXCEPTION(regex_error(error_badbrace, "unrecognized extension"));
}
case BOOST_XPR_CHAR_(char_type, 'i'):
case BOOST_XPR_CHAR_(char_type, 'm'):
case BOOST_XPR_CHAR_(char_type, 's'):
case BOOST_XPR_CHAR_(char_type, 'x'):
case BOOST_XPR_CHAR_(char_type, '-'):
return this->parse_mods_(begin, end);
default:
BOOST_THROW_EXCEPTION(regex_error(error_badbrace, "unrecognized extension"));
}
}
return token_literal;
}
//////////////////////////////////////////////////////////////////////////
// get_charset_token
// NOTE: white-space is *never* ignored in a charset.
template<typename FwdIter>
regex_constants::compiler_token_type get_charset_token(FwdIter &begin, FwdIter end)
{
using namespace regex_constants;
BOOST_ASSERT(begin != end);
switch(*begin)
{
case BOOST_XPR_CHAR_(char_type, '^'): ++begin; return token_charset_invert;
case BOOST_XPR_CHAR_(char_type, '-'): ++begin; return token_charset_hyphen;
case BOOST_XPR_CHAR_(char_type, ']'): ++begin; return token_charset_end;
case BOOST_XPR_CHAR_(char_type, '['):
{
FwdIter next = begin; ++next;
if(next != end)
{
BOOST_XPR_ENSURE_(
*next != BOOST_XPR_CHAR_(char_type, '=')
, error_collate
, "equivalence classes are not yet supported"
);
BOOST_XPR_ENSURE_(
*next != BOOST_XPR_CHAR_(char_type, '.')
, error_collate
, "collation sequences are not yet supported"
);
if(*next == BOOST_XPR_CHAR_(char_type, ':'))
{
begin = ++next;
return token_posix_charset_begin;
}
}
}
break;
case BOOST_XPR_CHAR_(char_type, ':'):
{
FwdIter next = begin; ++next;
if(next != end && *next == BOOST_XPR_CHAR_(char_type, ']'))
{
begin = ++next;
return token_posix_charset_end;
}
}
break;
case BOOST_XPR_CHAR_(char_type, '\\'):
if(++begin != end)
{
switch(*begin)
{
case BOOST_XPR_CHAR_(char_type, 'b'): ++begin; return token_charset_backspace;
default:;
}
}
return token_escape;
default:;
}
return token_literal;
}
//////////////////////////////////////////////////////////////////////////
// get_escape_token
template<typename FwdIter>
regex_constants::compiler_token_type get_escape_token(FwdIter &begin, FwdIter end)
{
using namespace regex_constants;
if(begin != end)
{
switch(*begin)
{
//case BOOST_XPR_CHAR_(char_type, 'a'): ++begin; return token_escape_bell;
//case BOOST_XPR_CHAR_(char_type, 'c'): ++begin; return token_escape_control;
//case BOOST_XPR_CHAR_(char_type, 'e'): ++begin; return token_escape_escape;
//case BOOST_XPR_CHAR_(char_type, 'f'): ++begin; return token_escape_formfeed;
//case BOOST_XPR_CHAR_(char_type, 'n'): ++begin; return token_escape_newline;
//case BOOST_XPR_CHAR_(char_type, 't'): ++begin; return token_escape_horizontal_tab;
//case BOOST_XPR_CHAR_(char_type, 'v'): ++begin; return token_escape_vertical_tab;
case BOOST_XPR_CHAR_(char_type, 'A'): ++begin; return token_assert_begin_sequence;
case BOOST_XPR_CHAR_(char_type, 'b'): ++begin; return token_assert_word_boundary;
case BOOST_XPR_CHAR_(char_type, 'B'): ++begin; return token_assert_not_word_boundary;
case BOOST_XPR_CHAR_(char_type, 'E'): ++begin; return token_quote_meta_end;
case BOOST_XPR_CHAR_(char_type, 'Q'): ++begin; return token_quote_meta_begin;
case BOOST_XPR_CHAR_(char_type, 'Z'): ++begin; return token_assert_end_sequence;
// Non-standard extension to ECMAScript syntax
case BOOST_XPR_CHAR_(char_type, '<'): ++begin; return token_assert_word_begin;
case BOOST_XPR_CHAR_(char_type, '>'): ++begin; return token_assert_word_end;
default:; // fall-through
}
}
return token_escape;
}
private:
//////////////////////////////////////////////////////////////////////////
// parse_mods_
template<typename FwdIter>
regex_constants::compiler_token_type parse_mods_(FwdIter &begin, FwdIter end)
{
using namespace regex_constants;
bool set = true;
do switch(*begin)
{
case BOOST_XPR_CHAR_(char_type, 'i'): this->flag_(set, icase_); break;
case BOOST_XPR_CHAR_(char_type, 'm'): this->flag_(!set, single_line); break;
case BOOST_XPR_CHAR_(char_type, 's'): this->flag_(!set, not_dot_newline); break;
case BOOST_XPR_CHAR_(char_type, 'x'): this->flag_(set, ignore_white_space); break;
case BOOST_XPR_CHAR_(char_type, ':'): ++begin; // fall-through
case BOOST_XPR_CHAR_(char_type, ')'): return token_no_mark;
case BOOST_XPR_CHAR_(char_type, '-'): if(false == (set = !set)) break; // else fall-through
default: BOOST_THROW_EXCEPTION(regex_error(error_paren, "unknown pattern modifier"));
}
while(BOOST_XPR_ENSURE_(++begin != end, error_paren, "incomplete extension"));
// this return is technically unreachable, but this must
// be here to work around a bug in gcc 4.0
return token_no_mark;
}
///////////////////////////////////////////////////////////////////////////////
// flag_
void flag_(bool set, regex_constants::syntax_option_type flag)
{
this->flags_ = set ? (this->flags_ | flag) : (this->flags_ & ~flag);
}
///////////////////////////////////////////////////////////////////////////
// is_space_
bool is_space_(char_type ch) const
{
return 0 != this->space_ && this->traits().isctype(ch, this->space_);
}
///////////////////////////////////////////////////////////////////////////
// is_alnum_
bool is_alnum_(char_type ch) const
{
return 0 != this->alnum_ && this->traits().isctype(ch, this->alnum_);
}
///////////////////////////////////////////////////////////////////////////
// get_name_
template<typename FwdIter>
void get_name_(FwdIter &begin, FwdIter end, string_type &name)
{
this->eat_ws_(begin, end);
for(name.clear(); begin != end && this->is_alnum_(*begin); ++begin)
{
name.push_back(*begin);
}
this->eat_ws_(begin, end);
BOOST_XPR_ENSURE_(!name.empty(), regex_constants::error_paren, "incomplete extension");
}
///////////////////////////////////////////////////////////////////////////////
// eat_ws_
template<typename FwdIter>
FwdIter &eat_ws_(FwdIter &begin, FwdIter end)
{
if(0 != (regex_constants::ignore_white_space & this->flags()))
{
while(end != begin && (BOOST_XPR_CHAR_(char_type, '#') == *begin || this->is_space_(*begin)))
{
if(BOOST_XPR_CHAR_(char_type, '#') == *begin++)
{
while(end != begin && BOOST_XPR_CHAR_(char_type, '\n') != *begin++) {}
}
else
{
for(; end != begin && this->is_space_(*begin); ++begin) {}
}
}
}
return begin;
}
regex_traits traits_;
regex_constants::syntax_option_type flags_;
typename regex_traits::char_class_type space_;
typename regex_traits::char_class_type alnum_;
};
}} // namespace boost::xpressive
#endif

View File

@@ -0,0 +1,175 @@
///////////////////////////////////////////////////////////////////////////////
// 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