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,132 @@
///////////////////////////////////////////////////////////////////////////////
// access.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_CORE_ACCESS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_ACCESS_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <vector>
#include <boost/shared_ptr.hpp>
#include <boost/proto/traits.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/dynamic/matchable.hpp>
#include <boost/xpressive/match_results.hpp> // for type_info_less
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// core_access
//
template<typename BidiIter>
struct core_access
{
typedef typename iterator_value<BidiIter>::type char_type;
static std::size_t get_hidden_mark_count(basic_regex<BidiIter> const &rex)
{
return proto::value(rex)->hidden_mark_count_;
}
static bool match(basic_regex<BidiIter> const &rex, match_state<BidiIter> &state)
{
return rex.match_(state);
}
static shared_ptr<detail::regex_impl<BidiIter> > const &
get_regex_impl(basic_regex<BidiIter> const &rex)
{
return proto::value(rex).get();
}
static void init_sub_match_vector
(
sub_match_vector<BidiIter> &subs_vect
, sub_match_impl<BidiIter> *subs_ptr
, std::size_t size
)
{
subs_vect.init_(subs_ptr, size);
}
static void init_sub_match_vector
(
sub_match_vector<BidiIter> &subs_vect
, sub_match_impl<BidiIter> *subs_ptr
, std::size_t size
, sub_match_vector<BidiIter> const &that
)
{
subs_vect.init_(subs_ptr, size, that);
}
static void init_match_results
(
match_results<BidiIter> &what
, regex_id_type regex_id
, intrusive_ptr<traits<char_type> const> const &tr
, sub_match_impl<BidiIter> *sub_matches
, std::size_t size
, std::vector<named_mark<char_type> > const &named_marks
)
{
what.init_(regex_id, tr, sub_matches, size, named_marks);
}
static sub_match_vector<BidiIter> &get_sub_match_vector(match_results<BidiIter> &what)
{
return what.sub_matches_;
}
static sub_match_impl<BidiIter> *get_sub_matches(sub_match_vector<BidiIter> &subs)
{
return subs.sub_matches_;
}
static results_extras<BidiIter> &get_extras(match_results<BidiIter> &what)
{
return what.get_extras_();
}
static nested_results<BidiIter> &get_nested_results(match_results<BidiIter> &what)
{
return what.nested_results_;
}
static action_args_type &get_action_args(match_results<BidiIter> &what)
{
return what.args_;
}
static void set_prefix_suffix(match_results<BidiIter> &what, BidiIter begin, BidiIter end)
{
what.set_prefix_suffix_(begin, end);
}
static void reset(match_results<BidiIter> &what)
{
what.reset_();
}
static void set_base(match_results<BidiIter> &what, BidiIter base)
{
what.set_base_(base);
}
static BidiIter get_base(match_results<BidiIter> &what)
{
return *what.base_;
}
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,39 @@
///////////////////////////////////////////////////////////////////////////////
// action.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_CORE_ACTION_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_ACTION_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/match_results.hpp> // for type_info_less
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// actionable
//
struct actionable
{
virtual ~actionable() {}
virtual void execute(action_args_type *) const {}
actionable()
: next(0)
{}
actionable const *next;
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,81 @@
///////////////////////////////////////////////////////////////////////////////
// adaptor.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_CORE_ADAPTOR_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_ADAPTOR_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/ref.hpp>
#include <boost/implicit_cast.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/dynamic/matchable.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// xpression_adaptor
//
// wrap a static xpression in a matchable interface so it can be stored
// in and invoked from a basic_regex object.
template<typename Xpr, typename Base>
struct xpression_adaptor
: Base // either matchable or matchable_ex
{
typedef typename Base::iterator_type iterator_type;
typedef typename iterator_value<iterator_type>::type char_type;
Xpr xpr_;
xpression_adaptor(Xpr const &xpr)
#if BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(4)) \
&& ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)))
// Ugh, gcc has an optimizer bug which elides this c'tor call
// resulting in pure virtual function calls.
__attribute__((noinline))
#endif
: xpr_(xpr)
{
}
virtual bool match(match_state<iterator_type> &state) const
{
typedef typename boost::unwrap_reference<Xpr const>::type xpr_type;
return implicit_cast<xpr_type &>(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);
}
private:
xpression_adaptor &operator =(xpression_adaptor const &);
};
///////////////////////////////////////////////////////////////////////////////
// make_adaptor
//
template<typename Base, typename Xpr>
inline intrusive_ptr<Base const> make_adaptor(Xpr const &xpr)
{
return intrusive_ptr<Base const>(new xpression_adaptor<Xpr, Base>(xpr));
}
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,221 @@
/// Contains the definition of the basic_regex\<\> class template and its associated helper functions.
//
// 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_CORE_FINDER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_FINDER_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 : 4189) // local variable is initialized but not referenced
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/regex_impl.hpp>
#include <boost/xpressive/detail/utility/boyer_moore.hpp>
#include <boost/xpressive/detail/utility/hash_peek_bitset.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// boyer_moore_finder
//
template<typename BidiIter, typename Traits>
struct boyer_moore_finder
: finder<BidiIter>
{
typedef typename iterator_value<BidiIter>::type char_type;
boyer_moore_finder(char_type const *begin, char_type const *end, Traits const &tr, bool icase)
: bm_(begin, end, tr, icase)
{
}
bool ok_for_partial_matches() const
{
return false;
}
bool operator ()(match_state<BidiIter> &state) const
{
Traits const &tr = traits_cast<Traits>(state);
state.cur_ = this->bm_.find(state.cur_, state.end_, tr);
return state.cur_ != state.end_;
}
private:
boyer_moore_finder(boyer_moore_finder const &);
boyer_moore_finder &operator =(boyer_moore_finder const &);
boyer_moore<BidiIter, Traits> bm_;
};
///////////////////////////////////////////////////////////////////////////////
// hash_peek_finder
//
template<typename BidiIter, typename Traits>
struct hash_peek_finder
: finder<BidiIter>
{
typedef typename iterator_value<BidiIter>::type char_type;
hash_peek_finder(hash_peek_bitset<char_type> const &bset)
: bset_(bset)
{
}
bool operator ()(match_state<BidiIter> &state) const
{
Traits const &tr = traits_cast<Traits>(state);
state.cur_ = (this->bset_.icase()
? this->find_(state.cur_, state.end_, tr, mpl::true_())
: this->find_(state.cur_, state.end_, tr, mpl::false_()));
return state.cur_ != state.end_;
}
private:
hash_peek_finder(hash_peek_finder const &);
hash_peek_finder &operator =(hash_peek_finder const &);
template<typename ICase>
BidiIter find_(BidiIter begin, BidiIter end, Traits const &tr, ICase) const
{
for(; begin != end && !this->bset_.test(*begin, tr, ICase()); ++begin)
;
return begin;
}
hash_peek_bitset<char_type> bset_;
};
///////////////////////////////////////////////////////////////////////////////
// line_start_finder
//
template<typename BidiIter, typename Traits, std::size_t Size = sizeof(typename iterator_value<BidiIter>::type)>
struct line_start_finder
: finder<BidiIter>
{
typedef typename iterator_value<BidiIter>::type char_type;
typedef typename iterator_difference<BidiIter>::type diff_type;
typedef typename Traits::char_class_type char_class_type;
line_start_finder(Traits const &tr)
: newline_(lookup_classname(tr, "newline"))
{
}
bool operator ()(match_state<BidiIter> &state) const
{
if(state.bos() && state.flags_.match_bol_)
{
return true;
}
Traits const &tr = traits_cast<Traits>(state);
BidiIter cur = state.cur_;
BidiIter const end = state.end_;
std::advance(cur, static_cast<diff_type>(-!state.bos()));
for(; cur != end; ++cur)
{
if(tr.isctype(*cur, this->newline_))
{
state.cur_ = ++cur;
return true;
}
}
return false;
}
private:
line_start_finder(line_start_finder const &);
line_start_finder &operator =(line_start_finder const &);
char_class_type newline_;
};
///////////////////////////////////////////////////////////////////////////////
// line_start_finder
//
template<typename BidiIter, typename Traits>
struct line_start_finder<BidiIter, Traits, 1u>
: finder<BidiIter>
{
typedef typename iterator_value<BidiIter>::type char_type;
typedef typename iterator_difference<BidiIter>::type diff_type;
typedef typename Traits::char_class_type char_class_type;
line_start_finder(Traits const &tr)
{
char_class_type newline = lookup_classname(tr, "newline");
for(int j = 0; j < 256; ++j)
{
this->bits_[j] = tr.isctype(static_cast<char_type>(static_cast<unsigned char>(j)), newline);
}
}
bool operator ()(match_state<BidiIter> &state) const
{
if(state.bos() && state.flags_.match_bol_)
{
return true;
}
BidiIter cur = state.cur_;
BidiIter const end = state.end_;
std::advance(cur, static_cast<diff_type>(-!state.bos()));
for(; cur != end; ++cur)
{
if(this->bits_[static_cast<unsigned char>(*cur)])
{
state.cur_ = ++cur;
return true;
}
}
return false;
}
private:
line_start_finder(line_start_finder const &);
line_start_finder &operator =(line_start_finder const &);
bool bits_[256];
};
///////////////////////////////////////////////////////////////////////////////
// leading_simple_repeat_finder
//
template<typename BidiIter>
struct leading_simple_repeat_finder
: finder<BidiIter>
{
leading_simple_repeat_finder()
: finder<BidiIter>()
{}
bool operator ()(match_state<BidiIter> &state) const
{
state.cur_ = state.next_search_;
return true;
}
private:
leading_simple_repeat_finder(leading_simple_repeat_finder const &);
leading_simple_repeat_finder &operator =(leading_simple_repeat_finder const &);
};
}}}
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma warning(pop)
#endif
#endif

View File

@@ -0,0 +1,74 @@
///////////////////////////////////////////////////////////////////////////////
// flow_control.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_CORE_FLOW_CONTROL_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_FLOW_CONTROL_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/regex_impl.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/utility/ignore_unused.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// push_context_match
//
template<typename BidiIter>
inline bool push_context_match
(
regex_impl<BidiIter> const &impl
, match_state<BidiIter> &state
, matchable<BidiIter> const &next
)
{
// avoid infinite recursion
// BUGBUG this only catches direct infinite recursion, like sregex::compile("(?R)"), but
// not indirect infinite recursion where two rules invoke each other recursively.
if(state.is_active_regex(impl) && state.cur_ == state.sub_match(0).begin_)
{
return next.match(state);
}
// save state
match_context<BidiIter> context = state.push_context(impl, next, context);
detail::ignore_unused(context);
// match the nested regex and uninitialize the match context
// (reclaims the sub_match objects if necessary)
return state.pop_context(impl, impl.xpr_->match(state));
}
///////////////////////////////////////////////////////////////////////////////
// pop_context_match
//
template<typename BidiIter>
inline bool pop_context_match(match_state<BidiIter> &state)
{
// save state
// BUGBUG nested regex could have changed state.traits_
match_context<BidiIter> &context(*state.context_.prev_context_);
state.swap_context(context);
// Finished matching the nested regex; now match the rest of the enclosing regex
bool success = context.next_ptr_->match(state);
// restore state
state.swap_context(context);
return success;
}
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,42 @@
///////////////////////////////////////////////////////////////////////////////
// icase.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_CORE_ICASE_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_ICASE_HPP_EAN_10_04_2005
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/regex_constants.hpp>
#include <boost/xpressive/detail/static/modifier.hpp>
#include <boost/xpressive/detail/core/linker.hpp>
#include <boost/xpressive/detail/utility/ignore_unused.hpp>
namespace boost { namespace xpressive { namespace regex_constants
{
///////////////////////////////////////////////////////////////////////////////
/// \brief Makes a sub-expression case-insensitive.
///
/// Use icase() to make a sub-expression case-insensitive. For instance,
/// "foo" >> icase(set['b'] >> "ar") will match "foo" exactly followed by
/// "bar" irrespective of case.
detail::modifier_op<detail::icase_modifier> const icase = {{}, regex_constants::icase_};
} // namespace regex_constants
using regex_constants::icase;
namespace detail
{
inline void ignore_unused_icase()
{
detail::ignore_unused(icase);
}
}
}} // namespace boost::xpressive
#endif

View File

@@ -0,0 +1,325 @@
///////////////////////////////////////////////////////////////////////////////
// linker.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_CORE_LINKER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_LINKER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/config.hpp>
#ifndef BOOST_NO_STD_LOCALE
# include <locale>
#endif
#include <stack>
#include <limits>
#include <typeinfo>
#include <boost/shared_ptr.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/version.hpp>
#if BOOST_VERSION >= 103500
# include <boost/fusion/include/for_each.hpp>
#else
# include <boost/spirit/fusion/algorithm/for_each.hpp>
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/dynamic/matchable.hpp>
#include <boost/xpressive/detail/core/matchers.hpp>
#include <boost/xpressive/detail/core/peeker.hpp>
#include <boost/xpressive/detail/utility/never_true.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// icase_modifier
//
// wrapped by the modifier<> template and inserted into the xpression
// template with the icase() helper function. icase_modifier morphs
// a case-sensitive visitor into a case-insensitive visitor, which
// causes all matchers visited to become case-insensitive.
//
struct icase_modifier
{
template<typename Visitor>
struct apply {};
template<typename BidiIter, typename ICase, typename Traits>
struct apply<xpression_visitor<BidiIter, ICase, Traits> >
{
typedef xpression_visitor<BidiIter, mpl::true_, Traits> type;
};
template<typename Visitor>
static typename apply<Visitor>::type
call(Visitor &visitor)
{
return typename apply<Visitor>::type(visitor.traits(), visitor.self());
}
};
///////////////////////////////////////////////////////////////////////////////
// regex_traits_type : wrap a locale in the appropriate regex_traits
//
template<typename Locale, typename BidiIter>
struct regex_traits_type
{
#ifndef BOOST_NO_STD_LOCALE
typedef typename iterator_value<BidiIter>::type char_type;
// if Locale is std::locale, wrap it in a cpp_regex_traits<Char>
typedef typename mpl::if_c
<
is_same<Locale, std::locale>::value
, cpp_regex_traits<char_type>
, Locale
>::type type;
#else
typedef Locale type;
#endif
};
///////////////////////////////////////////////////////////////////////////////
// locale_modifier
//
// wrapped by the modifier<> template and inserted into the xpression
// template with the imbue() helper function. Causes a sub-xpression to
// use the specified Locale
//
template<typename Locale>
struct locale_modifier
{
typedef Locale locale_type;
locale_modifier(Locale const &loc)
: loc_(loc)
{
}
template<typename Visitor>
struct apply {};
template<typename BidiIter, typename ICase, typename OtherTraits>
struct apply<xpression_visitor<BidiIter, ICase, OtherTraits> >
{
typedef typename regex_traits_type<Locale, BidiIter>::type traits_type;
typedef xpression_visitor<BidiIter, ICase, traits_type> type;
};
template<typename Visitor>
typename apply<Visitor>::type
call(Visitor &visitor) const
{
return typename apply<Visitor>::type(this->loc_, visitor.self());
}
Locale getloc() const
{
return this->loc_;
}
private:
Locale loc_;
};
///////////////////////////////////////////////////////////////////////////////
// xpression_linker
//
template<typename Char>
struct xpression_linker
{
template<typename Traits>
explicit xpression_linker(Traits const &tr)
: back_stack_()
, traits_(&tr)
, traits_type_(&typeid(Traits))
, has_backrefs_(false)
{
}
template<typename Matcher>
void accept(Matcher const &, void const *)
{
// no-op
}
template<typename Traits, typename ICase>
void accept(mark_matcher<Traits, ICase> const &, void const *)
{
this->has_backrefs_ = true;
}
template<typename Action>
void accept(action_matcher<Action> const &, void const *)
{
this->has_backrefs_ = true;
}
template<typename Predicate>
void accept(predicate_matcher<Predicate> const &, void const *)
{
this->has_backrefs_ = true;
}
void accept(repeat_begin_matcher const &, void const *next)
{
this->back_stack_.push(next);
}
template<typename Greedy>
void accept(repeat_end_matcher<Greedy> const &matcher, void const *)
{
matcher.back_ = this->back_stack_.top();
this->back_stack_.pop();
}
template<typename Alternates, typename Traits>
void accept(alternate_matcher<Alternates, Traits> const &matcher, void const *next)
{
xpression_peeker<Char> peeker(matcher.bset_, this->get_traits<Traits>());
this->alt_link(matcher.alternates_, next, &peeker);
}
void accept(alternate_end_matcher const &matcher, void const *)
{
matcher.back_ = this->back_stack_.top();
this->back_stack_.pop();
}
template<typename Xpr, typename Greedy>
void accept(optional_matcher<Xpr, Greedy> const &matcher, void const *next)
{
this->back_stack_.push(next);
matcher.xpr_.link(*this);
}
template<typename Xpr, typename Greedy>
void accept(optional_mark_matcher<Xpr, Greedy> const &matcher, void const *next)
{
this->back_stack_.push(next);
matcher.xpr_.link(*this);
}
template<typename Xpr>
void accept(keeper_matcher<Xpr> const &matcher, void const *)
{
matcher.xpr_.link(*this);
}
template<typename Xpr>
void accept(lookahead_matcher<Xpr> const &matcher, void const *)
{
matcher.xpr_.link(*this);
}
template<typename Xpr>
void accept(lookbehind_matcher<Xpr> const &matcher, void const *)
{
matcher.xpr_.link(*this);
}
template<typename Xpr, typename Greedy>
void accept(simple_repeat_matcher<Xpr, Greedy> const &matcher, void const *)
{
matcher.xpr_.link(*this);
}
// accessors
bool has_backrefs() const
{
return this->has_backrefs_;
}
// for use by alt_link_pred below
template<typename Xpr>
void alt_branch_link(Xpr const &xpr, void const *next, xpression_peeker<Char> *peeker)
{
this->back_stack_.push(next);
xpr.link(*this);
xpr.peek(*peeker);
}
private:
///////////////////////////////////////////////////////////////////////////////
// alt_link_pred
//
struct alt_link_pred
{
xpression_linker<Char> *linker_;
xpression_peeker<Char> *peeker_;
void const *next_;
alt_link_pred
(
xpression_linker<Char> *linker
, xpression_peeker<Char> *peeker
, void const *next
)
: linker_(linker)
, peeker_(peeker)
, next_(next)
{
}
template<typename Xpr>
void operator ()(Xpr const &xpr) const
{
this->linker_->alt_branch_link(xpr, this->next_, this->peeker_);
}
};
template<typename BidiIter>
void alt_link
(
alternates_vector<BidiIter> const &alternates
, void const *next
, xpression_peeker<Char> *peeker
)
{
std::for_each(alternates.begin(), alternates.end(), alt_link_pred(this, peeker, next));
}
template<typename Alternates>
void alt_link
(
fusion::sequence_base<Alternates> const &alternates
, void const *next
, xpression_peeker<Char> *peeker
)
{
#if BOOST_VERSION >= 103500
fusion::for_each(alternates.derived(), alt_link_pred(this, peeker, next));
#else
fusion::for_each(alternates.cast(), alt_link_pred(this, peeker, next));
#endif
}
template<typename Traits>
Traits const &get_traits() const
{
BOOST_ASSERT(*this->traits_type_ == typeid(Traits));
return *static_cast<Traits const *>(this->traits_);
}
std::stack<void const *> back_stack_;
void const *traits_;
std::type_info const *traits_type_;
bool has_backrefs_;
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,243 @@
///////////////////////////////////////////////////////////////////////////////
// list.hpp
// A simple implementation of std::list that allows incomplete
// types, does no dynamic allocation in the default constructor,
// and has a guarnteed O(1) splice.
//
// Copyright 2009 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_CORE_LIST_HPP_EAN_10_26_2009
#define BOOST_XPRESSIVE_DETAIL_CORE_LIST_HPP_EAN_10_26_2009
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <cstddef>
#include <iterator>
#include <algorithm>
#include <boost/assert.hpp>
#include <boost/iterator/iterator_facade.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// list
//
template<typename T>
struct list
{
private:
struct node_base
{
node_base *_prev;
node_base *_next;
};
struct node : node_base
{
explicit node(T const &value)
: _value(value)
{}
T _value;
};
node_base _sentry;
template<typename Ref = T &>
struct list_iterator
: boost::iterator_facade<list_iterator<Ref>, T, std::bidirectional_iterator_tag, Ref>
{
list_iterator(list_iterator<> const &it) : _node(it._node) {}
explicit list_iterator(node_base *n = 0) : _node(n) {}
private:
friend struct list<T>;
friend class boost::iterator_core_access;
Ref dereference() const { return static_cast<node *>(_node)->_value; }
void increment() { _node = _node->_next; }
void decrement() { _node = _node->_prev; }
bool equal(list_iterator const &it) const { return _node == it._node; }
node_base *_node;
};
public:
typedef T *pointer;
typedef T const *const_pointer;
typedef T &reference;
typedef T const &const_reference;
typedef list_iterator<> iterator;
typedef list_iterator<T const &> const_iterator;
typedef std::size_t size_type;
list()
{
_sentry._next = _sentry._prev = &_sentry;
}
list(list const &that)
{
_sentry._next = _sentry._prev = &_sentry;
const_iterator it = that.begin(), e = that.end();
for( ; it != e; ++it)
push_back(*it);
}
list &operator =(list const &that)
{
list(that).swap(*this);
return *this;
}
~list()
{
clear();
}
void clear()
{
while(!empty())
pop_front();
}
void swap(list &that) // throw()
{
list temp;
temp.splice(temp.begin(), that); // move that to temp
that.splice(that.begin(), *this); // move this to that
splice(begin(), temp); // move temp to this
}
void push_front(T const &t)
{
node *new_node = new node(t);
new_node->_next = _sentry._next;
new_node->_prev = &_sentry;
_sentry._next->_prev = new_node;
_sentry._next = new_node;
}
void push_back(T const &t)
{
node *new_node = new node(t);
new_node->_next = &_sentry;
new_node->_prev = _sentry._prev;
_sentry._prev->_next = new_node;
_sentry._prev = new_node;
}
void pop_front()
{
BOOST_ASSERT(!empty());
node *old_node = static_cast<node *>(_sentry._next);
_sentry._next = old_node->_next;
_sentry._next->_prev = &_sentry;
delete old_node;
}
void pop_back()
{
BOOST_ASSERT(!empty());
node *old_node = static_cast<node *>(_sentry._prev);
_sentry._prev = old_node->_prev;
_sentry._prev->_next = &_sentry;
delete old_node;
}
bool empty() const
{
return _sentry._next == &_sentry;
}
void splice(iterator it, list &x)
{
if(x.empty())
return;
x._sentry._prev->_next = it._node;
x._sentry._next->_prev = it._node->_prev;
it._node->_prev->_next = x._sentry._next;
it._node->_prev = x._sentry._prev;
x._sentry._prev = x._sentry._next = &x._sentry;
}
void splice(iterator it, list &, iterator xit)
{
xit._node->_prev->_next = xit._node->_next;
xit._node->_next->_prev = xit._node->_prev;
xit._node->_next = it._node;
xit._node->_prev = it._node->_prev;
it._node->_prev = it._node->_prev->_next = xit._node;
}
reference front()
{
BOOST_ASSERT(!empty());
return static_cast<node *>(_sentry._next)->_value;
}
const_reference front() const
{
BOOST_ASSERT(!empty());
return static_cast<node *>(_sentry._next)->_value;
}
reference back()
{
BOOST_ASSERT(!empty());
return static_cast<node *>(_sentry._prev)->_value;
}
const_reference back() const
{
BOOST_ASSERT(!empty());
return static_cast<node *>(_sentry._prev)->_value;
}
iterator begin()
{
return iterator(_sentry._next);
}
const_iterator begin() const
{
return const_iterator(_sentry._next);
}
iterator end()
{
return iterator(&_sentry);
}
const_iterator end() const
{
return const_iterator(const_cast<node_base *>(&_sentry));
}
size_type size() const
{
return static_cast<size_type>(std::distance(begin(), end()));
}
};
template<typename T>
void swap(list<T> &lhs, list<T> &rhs)
{
lhs.swap(rhs);
}
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,501 @@
///////////////////////////////////////////////////////////////////////////////
// action_matcher.hpp
//
// Copyright 2008 Eric Niebler.
// Copyright 2008 David Jenkins.
//
// 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_CORE_MATCHER_ACTION_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ACTION_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/config.hpp>
#include <boost/version.hpp>
#include <boost/ref.hpp>
#include <boost/assert.hpp>
#include <boost/mpl/if.hpp>
#include <boost/throw_exception.hpp>
#include <boost/utility/result_of.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/action.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/proto/core.hpp>
#include <boost/proto/context.hpp>
#include <boost/xpressive/match_results.hpp> // for type_info_less
#include <boost/xpressive/detail/static/transforms/as_action.hpp> // for 'read_attr'
#if BOOST_VERSION >= 103500
# include <boost/proto/fusion.hpp>
# include <boost/fusion/include/transform_view.hpp>
# include <boost/fusion/include/invoke.hpp>
# include <boost/fusion/include/push_front.hpp>
# include <boost/fusion/include/pop_front.hpp>
#endif
#if BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4510) // default constructor could not be generated
#pragma warning(disable : 4512) // assignment operator could not be generated
#pragma warning(disable : 4610) // can never be instantiated - user defined constructor required
#endif
namespace boost { namespace xpressive { namespace detail
{
#if BOOST_VERSION >= 103500
struct DataMember
: proto::mem_ptr<proto::_, proto::terminal<proto::_> >
{};
template<typename Expr, long N>
struct child_
: remove_reference<
typename proto::result_of::child_c<Expr &, N>::type
>
{};
///////////////////////////////////////////////////////////////////////////////
// mem_ptr_eval
// Rewrites expressions of the form x->*foo(a) into foo(x, a) and then
// evaluates them.
template<typename Expr, typename Context, bool IsDataMember = proto::matches<Expr, DataMember>::value>
struct mem_ptr_eval
{
typedef typename child_<Expr, 0>::type left_type;
typedef typename child_<Expr, 1>::type right_type;
typedef
typename proto::result_of::value<
typename proto::result_of::child_c<right_type, 0>::type
>::type
function_type;
typedef
fusion::transform_view<
typename fusion::result_of::push_front<
typename fusion::result_of::pop_front<right_type>::type const
, reference_wrapper<left_type>
>::type const
, proto::eval_fun<Context>
>
evaluated_args;
typedef
typename fusion::result_of::invoke<function_type, evaluated_args>::type
result_type;
result_type operator()(Expr &expr, Context &ctx) const
{
return fusion::invoke<function_type>(
proto::value(proto::child_c<0>(proto::right(expr)))
, evaluated_args(
fusion::push_front(fusion::pop_front(proto::right(expr)), boost::ref(proto::left(expr)))
, proto::eval_fun<Context>(ctx)
)
);
}
};
///////////////////////////////////////////////////////////////////////////////
// mem_ptr_eval
// Rewrites expressions of the form x->*foo into foo(x) and then
// evaluates them.
template<typename Expr, typename Context>
struct mem_ptr_eval<Expr, Context, true>
{
typedef typename child_<Expr, 0>::type left_type;
typedef typename child_<Expr, 1>::type right_type;
typedef
typename proto::result_of::value<right_type>::type
function_type;
typedef typename boost::result_of<
function_type(typename proto::result_of::eval<left_type, Context>::type)
>::type result_type;
result_type operator()(Expr &expr, Context &ctx) const
{
return proto::value(proto::right(expr))(
proto::eval(proto::left(expr), ctx)
);
}
};
#endif
struct attr_with_default_tag
{};
template<typename T>
struct opt;
///////////////////////////////////////////////////////////////////////////////
// action_context
//
struct action_context
{
explicit action_context(action_args_type *action_args)
: action_args_(action_args)
{}
action_args_type const &args() const
{
return *this->action_args_;
}
// eval_terminal
template<typename Expr, typename Arg>
struct eval_terminal
: proto::default_eval<Expr, action_context const>
{};
template<typename Expr, typename Arg>
struct eval_terminal<Expr, reference_wrapper<Arg> >
{
typedef Arg &result_type;
result_type operator()(Expr &expr, action_context const &) const
{
return proto::value(expr).get();
}
};
template<typename Expr, typename Arg>
struct eval_terminal<Expr, opt<Arg> >
{
typedef Arg const &result_type;
result_type operator()(Expr &expr, action_context const &) const
{
return proto::value(expr);
}
};
template<typename Expr, typename Type, typename Int>
struct eval_terminal<Expr, action_arg<Type, Int> >
{
typedef typename action_arg<Type, Int>::reference result_type;
result_type operator()(Expr &expr, action_context const &ctx) const
{
action_args_type::const_iterator where_ = ctx.args().find(&typeid(proto::value(expr)));
if(where_ == ctx.args().end())
{
BOOST_THROW_EXCEPTION(
regex_error(
regex_constants::error_badarg
, "An argument to an action was unspecified"
)
);
}
return proto::value(expr).cast(where_->second);
}
};
// eval
template<typename Expr, typename Tag = typename Expr::proto_tag>
struct eval
: proto::default_eval<Expr, action_context const>
{};
template<typename Expr>
struct eval<Expr, proto::tag::terminal>
: eval_terminal<Expr, typename proto::result_of::value<Expr>::type>
{};
// Evaluate attributes like a1|42
template<typename Expr>
struct eval<Expr, attr_with_default_tag>
{
typedef
typename proto::result_of::value<
typename proto::result_of::left<
typename proto::result_of::child<
Expr
>::type
>::type
>::type
temp_type;
typedef typename temp_type::type result_type;
result_type operator ()(Expr const &expr, action_context const &ctx) const
{
return proto::value(proto::left(proto::child(expr))).t_
? *proto::value(proto::left(proto::child(expr))).t_
: proto::eval(proto::right(proto::child(expr)), ctx);
}
};
#if BOOST_VERSION >= 103500
template<typename Expr>
struct eval<Expr, proto::tag::mem_ptr>
: mem_ptr_eval<Expr, action_context const>
{};
#endif
private:
action_args_type *action_args_;
};
///////////////////////////////////////////////////////////////////////////////
// action
//
template<typename Actor>
struct action
: actionable
{
action(Actor const &actor)
: actionable()
, actor_(actor)
{
}
virtual void execute(action_args_type *action_args) const
{
action_context const ctx(action_args);
proto::eval(this->actor_, ctx);
}
private:
Actor actor_;
};
///////////////////////////////////////////////////////////////////////////////
// subreg_transform
//
struct subreg_transform : proto::transform<subreg_transform>
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
{
typedef typename impl::state state_type;
typedef
typename proto::terminal<sub_match<typename state_type::iterator> >::type
result_type;
result_type operator ()(
typename impl::expr_param
, typename impl::state_param state
, typename impl::data_param data
) const
{
return result_type::make(state.sub_matches_[ data ]);
}
};
};
///////////////////////////////////////////////////////////////////////////////
// mark_transform
//
struct mark_transform : proto::transform<mark_transform>
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
{
typedef typename impl::state state_type;
typedef
typename proto::terminal<sub_match<typename state_type::iterator> >::type
result_type;
result_type operator ()(
typename impl::expr_param expr
, typename impl::state_param state
, typename impl::data_param
) const
{
return result_type::make(state.sub_matches_[ proto::value(expr).mark_number_ ]);
}
};
};
///////////////////////////////////////////////////////////////////////////////
// opt
//
template<typename T>
struct opt
{
typedef T type;
typedef T const &reference;
opt(T const *t)
: t_(t)
{}
operator reference() const
{
BOOST_XPR_ENSURE_(0 != this->t_, regex_constants::error_badattr, "Use of uninitialized regex attribute");
return *this->t_;
}
T const *t_;
};
///////////////////////////////////////////////////////////////////////////////
// attr_transform
//
struct attr_transform : proto::transform<attr_transform>
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
{
typedef typename impl::expr expr_type;
typedef
typename expr_type::proto_child0::matcher_type::value_type::second_type
attr_type;
typedef
typename proto::terminal<opt<attr_type> >::type
result_type;
result_type operator ()(
typename impl::expr_param
, typename impl::state_param state
, typename impl::data_param
) const
{
int slot = typename expr_type::proto_child0::nbr_type();
attr_type const *attr = static_cast<attr_type const *>(state.attr_context_.attr_slots_[slot-1]);
return result_type::make(opt<attr_type>(attr));
}
};
};
///////////////////////////////////////////////////////////////////////////////
// attr_with_default_transform
//
template<typename Grammar, typename Callable = proto::callable>
struct attr_with_default_transform : proto::transform<attr_with_default_transform<Grammar, Callable> >
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
{
typedef
typename proto::unary_expr<
attr_with_default_tag
, typename Grammar::template impl<Expr, State, Data>::result_type
>::type
result_type;
result_type operator ()(
typename impl::expr_param expr
, typename impl::state_param state
, typename impl::data_param data
) const
{
result_type that = {
typename Grammar::template impl<Expr, State, Data>()(expr, state, data)
};
return that;
}
};
};
///////////////////////////////////////////////////////////////////////////////
// by_ref_transform
//
struct by_ref_transform : proto::transform<by_ref_transform>
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
{
typedef
typename proto::result_of::value<typename impl::expr_param>::type
reference;
typedef
typename proto::terminal<reference>::type
result_type;
result_type operator ()(
typename impl::expr_param expr
, typename impl::state_param
, typename impl::data_param
) const
{
return result_type::make(proto::value(expr));
}
};
};
///////////////////////////////////////////////////////////////////////////////
// BindActionArgs
//
struct BindActionArgs
: proto::or_<
proto::when<proto::terminal<any_matcher>, subreg_transform>
, proto::when<proto::terminal<mark_placeholder>, mark_transform>
, proto::when<proto::terminal<read_attr<proto::_, proto::_> >, attr_transform>
, proto::when<proto::terminal<proto::_>, by_ref_transform>
, proto::when<
proto::bitwise_or<proto::terminal<read_attr<proto::_, proto::_> >, BindActionArgs>
, attr_with_default_transform<proto::bitwise_or<attr_transform, BindActionArgs> >
>
, proto::otherwise<proto::nary_expr<proto::_, proto::vararg<BindActionArgs> > >
>
{};
///////////////////////////////////////////////////////////////////////////////
// action_matcher
//
template<typename Actor>
struct action_matcher
: quant_style<quant_none, 0, false>
{
int sub_;
Actor actor_;
action_matcher(Actor const &actor, int sub)
: sub_(sub)
, actor_(actor)
{
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
// Bind the arguments
typedef
typename boost::result_of<BindActionArgs(
Actor const &
, match_state<BidiIter> &
, int const &
)>::type
action_type;
action<action_type> actor(BindActionArgs()(this->actor_, state, this->sub_));
// Put the action in the action list
actionable const **action_list_tail = state.action_list_tail_;
*state.action_list_tail_ = &actor;
state.action_list_tail_ = &actor.next;
// Match the rest of the pattern
if(next.match(state))
{
return true;
}
BOOST_ASSERT(0 == actor.next);
// remove action from list
*action_list_tail = 0;
state.action_list_tail_ = action_list_tail;
return false;
}
};
}}}
#if BOOST_MSVC
#pragma warning(pop)
#endif
#endif

View File

@@ -0,0 +1,51 @@
///////////////////////////////////////////////////////////////////////////////
// alternate_end_matcher.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_CORE_MATCHER_ALTERNATE_END_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ALTERNATE_END_MATCHER_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 : 4100) // unreferenced formal parameter
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// alternate_end_matcher
//
struct alternate_end_matcher
: quant_style_assertion
{
mutable void const *back_;
alternate_end_matcher()
: back_(0)
{
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
return next.pop_match(state, this->back_);
}
};
}}}
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma warning(pop)
#endif
#endif

View File

@@ -0,0 +1,132 @@
///////////////////////////////////////////////////////////////////////////////
// alternate_matcher.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_CORE_MATCHER_ALTERNATE_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ALTERNATE_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/version.hpp>
#if BOOST_VERSION <= 103200
// WORKAROUND for Fusion bug in Boost 1.32
namespace boost { namespace fusion
{
namespace detail { struct iterator_root; }
using detail::iterator_root;
}}
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/dynamic/matchable.hpp>
#include <boost/xpressive/detail/utility/hash_peek_bitset.hpp>
#include <boost/xpressive/detail/utility/algorithm.hpp>
#include <boost/xpressive/detail/utility/any.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// alt_match_pred
//
template<typename BidiIter, typename Next>
struct alt_match_pred
{
alt_match_pred(match_state<BidiIter> &state)
: state_(&state)
{
}
template<typename Xpr>
bool operator ()(Xpr const &xpr) const
{
return xpr.BOOST_NESTED_TEMPLATE push_match<Next>(*this->state_);
}
private:
match_state<BidiIter> *state_;
};
///////////////////////////////////////////////////////////////////////////////
// alt_match
//
template<typename BidiIter, typename Next>
inline bool alt_match
(
alternates_vector<BidiIter> const &alts, match_state<BidiIter> &state, Next const &
)
{
return detail::any(alts.begin(), alts.end(), alt_match_pred<BidiIter, Next>(state));
}
template<typename Head, typename Tail, typename BidiIter, typename Next>
inline bool alt_match
(
alternates_list<Head, Tail> const &alts, match_state<BidiIter> &state, Next const &
)
{
return fusion::any(alts, alt_match_pred<BidiIter, Next>(state));
}
///////////////////////////////////////////////////////////////////////////////
// alternate_matcher
template<typename Alternates, typename Traits>
struct alternate_matcher
: quant_style<
Alternates::width != unknown_width::value && Alternates::pure ? quant_fixed_width : quant_variable_width
, Alternates::width
, Alternates::pure
>
{
typedef Alternates alternates_type;
typedef typename Traits::char_type char_type;
Alternates alternates_;
mutable hash_peek_bitset<char_type> bset_;
explicit alternate_matcher(Alternates const &alternates = Alternates())
: alternates_(alternates)
, bset_()
{
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
if(!state.eos() && !this->can_match_(*state.cur_, traits_cast<Traits>(state)))
{
return false;
}
return detail::alt_match(this->alternates_, state, next);
}
detail::width get_width() const
{
// Only called when constructing static regexes, and this is a
// set of same-width alternates where the widths are known at compile
// time, as in: sregex rx = +(_ | 'a' | _n);
BOOST_MPL_ASSERT_RELATION(unknown_width::value, !=, Alternates::width);
return Alternates::width;
}
private:
alternate_matcher &operator =(alternate_matcher const &);
bool can_match_(char_type ch, Traits const &tr) const
{
return this->bset_.test(ch, tr);
}
};
}}}
#endif

View File

@@ -0,0 +1,51 @@
///////////////////////////////////////////////////////////////////////////////
// any_matcher.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_CORE_MATCHER_ANY_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ANY_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// any_matcher
//
struct any_matcher
{
BOOST_XPR_QUANT_STYLE(quant_fixed_width, 1, true)
template<typename BidiIter, typename Next>
static bool match(match_state<BidiIter> &state, Next const &next)
{
if(state.eos())
{
return false;
}
++state.cur_;
if(next.match(state))
{
return true;
}
--state.cur_;
return false;
}
};
}}}
#endif

View File

@@ -0,0 +1,71 @@
///////////////////////////////////////////////////////////////////////////////
// assert_bol_matcher.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_CORE_MATCHER_ASSERT_BOL_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ASSERT_BOL_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/next_prior.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/core/matcher/assert_line_base.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// assert_bol_matcher
//
template<typename Traits>
struct assert_bol_matcher
: assert_line_base<Traits>
{
typedef typename Traits::char_type char_type;
assert_bol_matcher(Traits const &tr)
: assert_line_base<Traits>(tr)
{
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
if(state.bos())
{
if(!state.flags_.match_bol_)
{
return false;
}
}
else
{
char_type ch = *boost::prior(state.cur_);
// If the previous character is not a newline, we're not at the start of a line
if(!traits_cast<Traits>(state).isctype(ch, this->newline_))
{
return false;
}
// There is no line-break between \r and \n
else if(ch == this->cr_ && !state.eos() && *state.cur_ == this->nl_)
{
return false;
}
}
return next.match(state);
}
};
}}}
#endif

View File

@@ -0,0 +1,39 @@
///////////////////////////////////////////////////////////////////////////////
// assert_bos_matcher.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_CORE_MATCHER_ASSERT_BOS_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ASSERT_BOS_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// assert_bos_matcher
// match the beginning of the sequence (\A)
struct assert_bos_matcher
{
BOOST_XPR_QUANT_STYLE(quant_none, 0, true)
template<typename BidiIter, typename Next>
static bool match(match_state<BidiIter> &state, Next const &next)
{
return state.bos() && next.match(state);
}
};
}}}
#endif

View File

@@ -0,0 +1,71 @@
///////////////////////////////////////////////////////////////////////////////
// assert_eol_matcher.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_CORE_MATCHER_ASSERT_EOL_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ASSERT_EOL_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/next_prior.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/core/matcher/assert_line_base.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// assert_eol_matcher
//
template<typename Traits>
struct assert_eol_matcher
: assert_line_base<Traits>
{
typedef typename Traits::char_type char_type;
assert_eol_matcher(Traits const &tr)
: assert_line_base<Traits>(tr)
{
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
if(state.eos())
{
if(!state.flags_.match_eol_)
{
return false;
}
}
else
{
char_type ch = *state.cur_;
// If the current character is not a newline, we're not at the end of a line
if(!traits_cast<Traits>(state).isctype(ch, this->newline_))
{
return false;
}
// There is no line-break between \r and \n
else if(ch == this->nl_ && (!state.bos() || state.flags_.match_prev_avail_) && *boost::prior(state.cur_) == this->cr_)
{
return false;
}
}
return next.match(state);
}
};
}}}
#endif

View File

@@ -0,0 +1,39 @@
///////////////////////////////////////////////////////////////////////////////
// assert_eos_matcher.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_CORE_MATCHER_ASSERT_EOS_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ASSERT_EOS_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// assert_eos_matcher
// match the end of the sequence (\Z)
struct assert_eos_matcher
{
BOOST_XPR_QUANT_STYLE(quant_none, 0, true)
template<typename BidiIter, typename Next>
static bool match(match_state<BidiIter> &state, Next const &next)
{
return state.eos() && next.match(state);
}
};
}}}
#endif

View File

@@ -0,0 +1,47 @@
///////////////////////////////////////////////////////////////////////////////
// assert_line_base.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_CORE_MATCHER_DETAIL_ASSERT_LINE_BASE_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_DETAIL_ASSERT_LINE_BASE_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// assert_line_base
//
template<typename Traits>
struct assert_line_base
: quant_style_assertion
{
typedef typename Traits::char_type char_type;
typedef typename Traits::char_class_type char_class_type;
protected:
assert_line_base(Traits const &tr)
: newline_(lookup_classname(tr, "newline"))
, nl_(tr.widen('\n'))
, cr_(tr.widen('\r'))
{
}
char_class_type newline_;
char_type nl_, cr_;
};
}}}
#endif

View File

@@ -0,0 +1,125 @@
///////////////////////////////////////////////////////////////////////////////
// assert_word_matcher.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_CORE_MATCHER_ASSERT_WORD_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ASSERT_WORD_MATCHER_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/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/utility/ignore_unused.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// word_boundary
//
template<typename IsBoundary>
struct word_boundary
{
template<typename BidiIter>
static bool eval(bool prevword, bool thisword, match_state<BidiIter> &state)
{
if((state.flags_.match_not_bow_ && state.bos()) || (state.flags_.match_not_eow_ && state.eos()))
{
return !IsBoundary::value;
}
return IsBoundary::value == (prevword != thisword);
}
};
///////////////////////////////////////////////////////////////////////////////
// word_begin
//
struct word_begin
{
template<typename BidiIter>
static bool eval(bool prevword, bool thisword, match_state<BidiIter> &state)
{
if(state.flags_.match_not_bow_ && state.bos())
{
return false;
}
return !prevword && thisword;
}
};
///////////////////////////////////////////////////////////////////////////////
// word_end
//
struct word_end
{
template<typename BidiIter>
static bool eval(bool prevword, bool thisword, match_state<BidiIter> &state)
{
if(state.flags_.match_not_eow_ && state.eos())
{
return false;
}
return prevword && !thisword;
}
};
///////////////////////////////////////////////////////////////////////////////
// assert_word_matcher
//
template<typename Cond, typename Traits>
struct assert_word_matcher
: quant_style_assertion
{
typedef typename Traits::char_type char_type;
typedef typename Traits::char_class_type char_class_type;
assert_word_matcher(Traits const &tr)
: word_(lookup_classname(tr, "w"))
{
BOOST_ASSERT(0 != this->word_);
}
assert_word_matcher(char_class_type word)
: word_(word)
{}
bool is_word(Traits const &tr, char_type ch) const
{
detail::ignore_unused(tr);
return tr.isctype(tr.translate(ch), this->word_);
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
BidiIter cur = state.cur_;
bool const thisword = !state.eos() && this->is_word(traits_cast<Traits>(state), *cur);
bool const prevword = (!state.bos() || state.flags_.match_prev_avail_)
&& this->is_word(traits_cast<Traits>(state), *--cur);
return Cond::eval(prevword, thisword, state) && next.match(state);
}
char_class_type word() const
{
return this->word_;
}
private:
char_class_type word_;
};
}}}
#endif

View File

@@ -0,0 +1,50 @@
///////////////////////////////////////////////////////////////////////////////
// attr_begin_matcher.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_CORE_MATCHER_ATTR_BEGIN_MATCHER_HPP_EAN_06_09_2007
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ATTR_BEGIN_MATCHER_HPP_EAN_06_09_2007
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// attr_begin_matcher
//
template<typename Nbr>
struct attr_begin_matcher
: quant_style<quant_none, 0, false>
{
template<typename BidiIter, typename Next>
static bool match(match_state<BidiIter> &state, Next const &next)
{
void const *attr_slots[Nbr::value] = {};
attr_context old_attr_context = state.attr_context_;
state.attr_context_.attr_slots_ = attr_slots;
state.attr_context_.prev_attr_context_ = &old_attr_context;
if(next.match(state))
{
return true;
}
state.attr_context_ = old_attr_context;
return false;
}
};
}}}
#endif

View File

@@ -0,0 +1,47 @@
///////////////////////////////////////////////////////////////////////////////
// attr_end_matcher.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_CORE_MATCHER_ATTR_END_MATCHER_HPP_EAN_06_09_2007
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ATTR_END_MATCHER_HPP_EAN_06_09_2007
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// attr_end_matcher
//
struct attr_end_matcher
: quant_style<quant_none, 0, false>
{
template<typename BidiIter, typename Next>
static bool match(match_state<BidiIter> &state, Next const &next)
{
attr_context old_attr_context = state.attr_context_;
state.attr_context_ = *old_attr_context.prev_attr_context_;
if(next.match(state))
{
return true;
}
state.attr_context_ = old_attr_context;
return false;
}
};
}}}
#endif

View File

@@ -0,0 +1,111 @@
///////////////////////////////////////////////////////////////////////////////
// attr_matcher.hpp
//
// Copyright 2008 Eric Niebler.
// Copyright 2008 David Jenkins.
//
// 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_CORE_MATCHER_ATTR_MATCHER_HPP_EAN_06_09_2007
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ATTR_MATCHER_HPP_EAN_06_09_2007
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/utility/symbols.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// char_translate
//
template<typename Traits, bool ICase>
struct char_translate
{
typedef typename Traits::char_type char_type;
Traits const &traits_;
explicit char_translate(Traits const &tr)
: traits_(tr)
{}
char_type operator ()(char_type ch1) const
{
return this->traits_.translate(ch1);
}
private:
char_translate &operator =(char_translate const &);
};
///////////////////////////////////////////////////////////////////////////////
// char_translate
//
template<typename Traits>
struct char_translate<Traits, true>
{
typedef typename Traits::char_type char_type;
Traits const &traits_;
explicit char_translate(Traits const &tr)
: traits_(tr)
{}
char_type operator ()(char_type ch1) const
{
return this->traits_.translate_nocase(ch1);
}
private:
char_translate &operator =(char_translate const &);
};
///////////////////////////////////////////////////////////////////////////////
// attr_matcher
// Note: the Matcher is a std::map
template<typename Matcher, typename Traits, typename ICase>
struct attr_matcher
: quant_style<quant_none, 0, false>
{
typedef typename Matcher::value_type::second_type const* result_type;
attr_matcher(int slot, Matcher const &matcher, Traits const& tr)
: slot_(slot-1)
{
char_translate<Traits, ICase::value> trans(tr);
this->sym_.load(matcher, trans);
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
BidiIter tmp = state.cur_;
char_translate<Traits, ICase::value> trans(traits_cast<Traits>(state));
result_type const &result = this->sym_(state.cur_, state.end_, trans);
if(result)
{
void const *old_slot = state.attr_context_.attr_slots_[this->slot_];
state.attr_context_.attr_slots_[this->slot_] = &*result;
if(next.match(state))
{
return true;
}
state.attr_context_.attr_slots_[this->slot_] = old_slot;
}
state.cur_ = tmp;
return false;
}
int slot_;
boost::xpressive::detail::symbols<Matcher> sym_;
};
}}}
#endif

View File

@@ -0,0 +1,67 @@
///////////////////////////////////////////////////////////////////////////////
// charset_matcher.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_CORE_MATCHER_CHARSET_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_CHARSET_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// charset_matcher
//
template<typename Traits, typename ICase, typename CharSet>
struct charset_matcher
: quant_style_fixed_width<1>
{
typedef typename Traits::char_type char_type;
typedef Traits traits_type;
typedef ICase icase_type;
charset_matcher(CharSet const &charset = CharSet())
: charset_(charset)
{
}
void inverse()
{
this->charset_.inverse();
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
if(state.eos() || !this->charset_.test(*state.cur_, traits_cast<Traits>(state), icase_type()))
{
return false;
}
++state.cur_;
if(next.match(state))
{
return true;
}
--state.cur_;
return false;
}
CharSet charset_;
};
}}}
#endif

View File

@@ -0,0 +1,98 @@
///////////////////////////////////////////////////////////////////////////////
// end_matcher.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_CORE_MATCHER_END_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_END_MATCHER_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/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/core/sub_match_impl.hpp>
#include <boost/xpressive/detail/core/flow_control.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// end_matcher
//
struct end_matcher
: quant_style_assertion
{
template<typename BidiIter, typename Next>
static bool match(match_state<BidiIter> &state, Next const &)
{
BidiIter const tmp = state.cur_;
sub_match_impl<BidiIter> &s0 = state.sub_match(0);
BOOST_ASSERT(!s0.matched);
// SPECIAL: if there is a match context on the context stack, then
// this pattern has been nested within another. pop that context and
// continue executing.
if(0 != state.context_.prev_context_)
{
if(!pop_context_match(state))
{
return false;
}
// record the end of sub-match zero
s0.first = s0.begin_;
s0.second = tmp;
s0.matched = true;
return true;
}
else if((state.flags_.match_all_ && !state.eos()) ||
(state.flags_.match_not_null_ && state.cur_ == s0.begin_))
{
return false;
}
// record the end of sub-match zero
s0.first = s0.begin_;
s0.second = tmp;
s0.matched = true;
// Now execute any actions that have been queued
for(actionable const *actor = state.action_list_.next; 0 != actor; actor = actor->next)
{
actor->execute(state.action_args_);
}
return true;
}
};
///////////////////////////////////////////////////////////////////////////////
// independent_end_matcher
//
struct independent_end_matcher
: quant_style_assertion
{
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &) const
{
// Now execute any actions that have been queued
for(actionable const *actor = state.action_list_.next; 0 != actor; actor = actor->next)
{
actor->execute(state.action_args_);
}
return true;
}
};
}}}
#endif

View File

@@ -0,0 +1,39 @@
///////////////////////////////////////////////////////////////////////////////
// epsilon_matcher.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_CORE_MATCHER_EPSILON_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_EPSILON_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// epsilon_matcher
//
struct epsilon_matcher
{
BOOST_XPR_QUANT_STYLE(quant_none, 0, true)
template<typename BidiIter, typename Next>
static bool match(match_state<BidiIter> &state, Next const &next)
{
return next.match(state);
}
};
}}}
#endif

View File

@@ -0,0 +1,96 @@
///////////////////////////////////////////////////////////////////////////////
// keeper_matcher.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_CORE_MATCHER_KEEPER_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_KEEPER_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/mpl/bool.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// keeper_matcher
// Xpr can be either a static_xpression, or a shared_matchable
template<typename Xpr>
struct keeper_matcher
: quant_style<quant_variable_width, unknown_width::value, Xpr::pure>
{
keeper_matcher(Xpr const &xpr, bool pure = Xpr::pure)
: xpr_(xpr)
, pure_(pure)
{
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
return Xpr::pure || this->pure_
? this->match_(state, next, mpl::true_())
: this->match_(state, next, mpl::false_());
}
template<typename BidiIter, typename Next>
bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const
{
BidiIter const tmp = state.cur_;
// matching xpr is guaranteed to not produce side-effects, don't bother saving state
if(!this->xpr_.match(state))
{
return false;
}
else if(next.match(state))
{
return true;
}
state.cur_ = tmp;
return false;
}
template<typename BidiIter, typename Next>
bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const
{
BidiIter const tmp = state.cur_;
// matching xpr could produce side-effects, save state
memento<BidiIter> mem = save_sub_matches(state);
if(!this->xpr_.match(state))
{
restore_action_queue(mem, state);
reclaim_sub_matches(mem, state, false);
return false;
}
restore_action_queue(mem, state);
if(next.match(state))
{
reclaim_sub_matches(mem, state, true);
return true;
}
restore_sub_matches(mem, state);
state.cur_ = tmp;
return false;
}
Xpr xpr_;
bool pure_; // false if matching xpr_ could modify the sub-matches
};
}}}
#endif

View File

@@ -0,0 +1,66 @@
///////////////////////////////////////////////////////////////////////////////
// literal_matcher.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_CORE_MATCHER_LITERAL_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LITERAL_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/utility/traits_utils.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// literal_matcher
//
template<typename Traits, typename ICase, typename Not>
struct literal_matcher
: quant_style_fixed_width<1>
{
typedef typename Traits::char_type char_type;
typedef Not not_type;
typedef ICase icase_type;
char_type ch_;
explicit literal_matcher(char_type ch)
: ch_(ch)
{}
literal_matcher(char_type ch, Traits const &tr)
: ch_(detail::translate(ch, tr, icase_type()))
{}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
if(state.eos() || Not::value ==
(detail::translate(*state.cur_, traits_cast<Traits>(state), icase_type()) == this->ch_))
{
return false;
}
++state.cur_;
if(next.match(state))
{
return true;
}
--state.cur_;
return false;
}
};
}}}
#endif

View File

@@ -0,0 +1,83 @@
///////////////////////////////////////////////////////////////////////////////
// logical_newline_matcher.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_CORE_MATCHER_LOGICAL_NEWLINE_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LOGICAL_NEWLINE_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
//////////////////////////////////////////////////////////////////////////
// logical_newline_matcher
//
template<typename Traits>
struct logical_newline_matcher
: quant_style_variable_width
{
typedef typename Traits::char_type char_type;
typedef typename Traits::char_class_type char_class_type;
logical_newline_matcher(Traits const &tr)
: newline_(lookup_classname(tr, "newline"))
, nl_(tr.widen('\n'))
, cr_(tr.widen('\r'))
{
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
if(state.eos())
{
return false;
}
char_type ch = *state.cur_;
if(traits_cast<Traits>(state).isctype(ch, this->newline_))
{
++state.cur_;
if(this->cr_ == ch && !state.eos() && this->nl_ == *state.cur_)
{
++state.cur_;
if(next.match(state))
{
return true;
}
--state.cur_;
}
else if(next.match(state))
{
return true;
}
--state.cur_;
}
return false;
}
char_class_type newline() const
{
return this->newline_;
}
private:
char_class_type newline_;
char_type nl_, cr_;
};
}}}
#endif

View File

@@ -0,0 +1,151 @@
///////////////////////////////////////////////////////////////////////////////
// lookahead_matcher.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_CORE_MATCHER_LOOKAHEAD_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LOOKAHEAD_MATCHER_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/bool.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/utility/save_restore.hpp>
#include <boost/xpressive/detail/utility/ignore_unused.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// lookahead_matcher
// Xpr can be either a static_xpression, or a shared_matchable
//
template<typename Xpr>
struct lookahead_matcher
: quant_style<quant_none, 0, Xpr::pure>
{
lookahead_matcher(Xpr const &xpr, bool no, bool pure = Xpr::pure)
: xpr_(xpr)
, not_(no)
, pure_(pure)
{
}
void inverse()
{
this->not_ = !this->not_;
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
return Xpr::pure || this->pure_
? this->match_(state, next, mpl::true_())
: this->match_(state, next, mpl::false_());
}
template<typename BidiIter, typename Next>
bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const
{
BidiIter const tmp = state.cur_;
if(this->not_)
{
// negative look-ahead assertions do not trigger partial matches.
save_restore<bool> partial_match(state.found_partial_match_);
detail::ignore_unused(partial_match);
if(this->xpr_.match(state))
{
state.cur_ = tmp;
return false;
}
else if(next.match(state))
{
return true;
}
}
else
{
if(!this->xpr_.match(state))
{
return false;
}
state.cur_ = tmp;
if(next.match(state))
{
return true;
}
}
BOOST_ASSERT(state.cur_ == tmp);
return false;
}
template<typename BidiIter, typename Next>
bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const
{
BidiIter const tmp = state.cur_;
// matching xpr could produce side-effects, save state
memento<BidiIter> mem = save_sub_matches(state);
if(this->not_)
{
// negative look-ahead assertions do not trigger partial matches.
save_restore<bool> partial_match(state.found_partial_match_);
detail::ignore_unused(partial_match);
if(this->xpr_.match(state))
{
restore_action_queue(mem, state);
restore_sub_matches(mem, state);
state.cur_ = tmp;
return false;
}
restore_action_queue(mem, state);
if(next.match(state))
{
reclaim_sub_matches(mem, state, true);
return true;
}
reclaim_sub_matches(mem, state, false);
}
else
{
if(!this->xpr_.match(state))
{
restore_action_queue(mem, state);
reclaim_sub_matches(mem, state, false);
return false;
}
state.cur_ = tmp;
restore_action_queue(mem, state);
if(next.match(state))
{
reclaim_sub_matches(mem, state, true);
return true;
}
restore_sub_matches(mem, state);
}
BOOST_ASSERT(state.cur_ == tmp);
return false;
}
Xpr xpr_;
bool not_;
bool pure_; // false if matching xpr_ could modify the sub-matches
};
}}}
#endif

View File

@@ -0,0 +1,168 @@
///////////////////////////////////////////////////////////////////////////////
// lookbehind_matcher.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_CORE_MATCHER_LOOKBEHIND_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LOOKBEHIND_MATCHER_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/xpressive/regex_error.hpp>
#include <boost/xpressive/regex_constants.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/utility/algorithm.hpp>
#include <boost/xpressive/detail/utility/save_restore.hpp>
#include <boost/xpressive/detail/utility/ignore_unused.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// lookbehind_matcher
// Xpr can be either a static_xpression or a shared_matchable
template<typename Xpr>
struct lookbehind_matcher
: quant_style<quant_none, 0, Xpr::pure>
{
lookbehind_matcher(Xpr const &xpr, std::size_t wid, bool no, bool pure = Xpr::pure)
: xpr_(xpr)
, not_(no)
, pure_(pure)
, width_(wid)
{
BOOST_XPR_ENSURE_(!is_unknown(this->width_), regex_constants::error_badlookbehind,
"Variable-width look-behind assertions are not supported");
}
void inverse()
{
this->not_ = !this->not_;
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
return Xpr::pure || this->pure_
? this->match_(state, next, mpl::true_())
: this->match_(state, next, mpl::false_());
}
template<typename BidiIter, typename Next>
bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const
{
typedef typename iterator_difference<BidiIter>::type difference_type;
BidiIter const tmp = state.cur_;
if(!detail::advance_to(state.cur_, -static_cast<difference_type>(this->width_), state.begin_))
{
state.cur_ = tmp;
return this->not_ ? next.match(state) : false;
}
if(this->not_)
{
if(this->xpr_.match(state))
{
BOOST_ASSERT(state.cur_ == tmp);
return false;
}
state.cur_ = tmp;
if(next.match(state))
{
return true;
}
}
else
{
if(!this->xpr_.match(state))
{
state.cur_ = tmp;
return false;
}
BOOST_ASSERT(state.cur_ == tmp);
if(next.match(state))
{
return true;
}
}
BOOST_ASSERT(state.cur_ == tmp);
return false;
}
template<typename BidiIter, typename Next>
bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const
{
typedef typename iterator_difference<BidiIter>::type difference_type;
BidiIter const tmp = state.cur_;
if(!detail::advance_to(state.cur_, -static_cast<difference_type>(this->width_), state.begin_))
{
state.cur_ = tmp;
return this->not_ ? next.match(state) : false;
}
// matching xpr could produce side-effects, save state
memento<BidiIter> mem = save_sub_matches(state);
if(this->not_)
{
// negative look-ahead assertions do not trigger partial matches.
save_restore<bool> partial_match(state.found_partial_match_);
detail::ignore_unused(partial_match);
if(this->xpr_.match(state))
{
restore_action_queue(mem, state);
restore_sub_matches(mem, state);
BOOST_ASSERT(state.cur_ == tmp);
return false;
}
state.cur_ = tmp;
restore_action_queue(mem, state);
if(next.match(state))
{
reclaim_sub_matches(mem, state, true);
return true;
}
reclaim_sub_matches(mem, state, false);
}
else
{
if(!this->xpr_.match(state))
{
state.cur_ = tmp;
restore_action_queue(mem, state);
reclaim_sub_matches(mem, state, false);
return false;
}
BOOST_ASSERT(state.cur_ == tmp);
restore_action_queue(mem, state);
if(next.match(state))
{
reclaim_sub_matches(mem, state, true);
return true;
}
restore_sub_matches(mem, state);
}
BOOST_ASSERT(state.cur_ == tmp);
return false;
}
Xpr xpr_;
bool not_;
bool pure_; // false if matching xpr_ could modify the sub-matches
std::size_t width_;
};
}}}
#endif

View File

@@ -0,0 +1,56 @@
///////////////////////////////////////////////////////////////////////////////
// mark_begin_matcher.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_CORE_MATCHER_MARK_BEGIN_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_MARK_BEGIN_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// mark_begin_matcher
//
struct mark_begin_matcher
: quant_style<quant_fixed_width, 0, false>
{
int mark_number_; // signed because it could be negative
mark_begin_matcher(int mark_number)
: mark_number_(mark_number)
{
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
sub_match_impl<BidiIter> &br = state.sub_match(this->mark_number_);
BidiIter old_begin = br.begin_;
br.begin_ = state.cur_;
if(next.match(state))
{
return true;
}
br.begin_ = old_begin;
return false;
}
};
}}}
#endif

View File

@@ -0,0 +1,64 @@
///////////////////////////////////////////////////////////////////////////////
// mark_end_matcher.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_CORE_MATCHER_MARK_END_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_MARK_END_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// mark_end_matcher
//
struct mark_end_matcher
: quant_style<quant_none, 0, false>
{
int mark_number_;
mark_end_matcher(int mark_number)
: mark_number_(mark_number)
{
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
sub_match_impl<BidiIter> &br = state.sub_match(this->mark_number_);
BidiIter old_first = br.first;
BidiIter old_second = br.second;
bool old_matched = br.matched;
br.first = br.begin_;
br.second = state.cur_;
br.matched = true;
if(next.match(state))
{
return true;
}
br.first = old_first;
br.second = old_second;
br.matched = old_matched;
return false;
}
};
}}}
#endif

View File

@@ -0,0 +1,78 @@
///////////////////////////////////////////////////////////////////////////////
// mark_matcher.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_CORE_MATCHER_MARK_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_MARK_MATCHER_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/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/utility/traits_utils.hpp>
namespace boost { namespace xpressive { namespace detail
{
// TODO: the mark matcher is acually a fixed-width matcher, but the width is
// not known until pattern match time.
///////////////////////////////////////////////////////////////////////////////
// mark_matcher
//
template<typename Traits, typename ICase>
struct mark_matcher
: quant_style_variable_width
{
typedef ICase icase_type;
int mark_number_;
mark_matcher(int mark_number, Traits const &)
: mark_number_(mark_number)
{
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
BOOST_ASSERT(this->mark_number_ < static_cast<int>(state.mark_count_));
sub_match_impl<BidiIter> const &br = state.sub_match(this->mark_number_);
if(!br.matched)
{
return false;
}
BidiIter const tmp = state.cur_;
for(BidiIter begin = br.first, end = br.second; begin != end; ++begin, ++state.cur_)
{
if(state.eos()
|| detail::translate(*state.cur_, traits_cast<Traits>(state), icase_type())
!= detail::translate(*begin, traits_cast<Traits>(state), icase_type()))
{
state.cur_ = tmp;
return false;
}
}
if(next.match(state))
{
return true;
}
state.cur_ = tmp;
return false;
}
};
}}}
#endif

View File

@@ -0,0 +1,121 @@
///////////////////////////////////////////////////////////////////////////////
// optional_matcher.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_CORE_MATCHER_OPTIONAL_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_OPTIONAL_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/mpl/bool.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// optional_matcher
template<typename Xpr, typename Greedy>
struct optional_matcher
: quant_style<quant_variable_width, unknown_width::value, Xpr::pure>
{
Xpr xpr_;
explicit optional_matcher(Xpr const &xpr)
: xpr_(xpr)
{
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
return this->match_(state, next, Greedy());
}
private:
template<typename BidiIter, typename Next>
bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const // Greedy
{
return this->xpr_.BOOST_NESTED_TEMPLATE push_match<Next>(state)
|| next.match(state);
}
template<typename BidiIter, typename Next>
bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const // Non-greedy
{
return next.match(state)
|| this->xpr_.BOOST_NESTED_TEMPLATE push_match<Next>(state);
}
optional_matcher &operator =(optional_matcher const &);
};
///////////////////////////////////////////////////////////////////////////////
// optional_mark_matcher
template<typename BidiIter, typename Next>
inline bool match_next(match_state<BidiIter> &state, Next const &next, int mark_number)
{
sub_match_impl<BidiIter> &br = state.sub_match(mark_number);
bool old_matched = br.matched;
br.matched = false;
if(next.match(state))
{
return true;
}
br.matched = old_matched;
return false;
}
///////////////////////////////////////////////////////////////////////////////
// optional_mark_matcher
template<typename Xpr, typename Greedy>
struct optional_mark_matcher
: quant_style<quant_variable_width, unknown_width::value, Xpr::pure>
{
Xpr xpr_;
int mark_number_;
explicit optional_mark_matcher(Xpr const &xpr, int mark_number)
: xpr_(xpr)
, mark_number_(mark_number)
{
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
return this->match_(state, next, Greedy());
}
private:
template<typename BidiIter, typename Next>
bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const // Greedy
{
return this->xpr_.BOOST_NESTED_TEMPLATE push_match<Next>(state)
|| match_next(state, next, this->mark_number_);
}
template<typename BidiIter, typename Next>
bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const // Non-greedy
{
return match_next(state, next, this->mark_number_)
|| this->xpr_.BOOST_NESTED_TEMPLATE push_match<Next>(state);
}
optional_mark_matcher &operator =(optional_mark_matcher const &);
};
}}}
#endif

View File

@@ -0,0 +1,73 @@
///////////////////////////////////////////////////////////////////////////////
// posix_charset_matcher.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_CORE_MATCHER_POSIX_CHARSET_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_POSIX_CHARSET_MATCHER_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/bool.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/utility/traits_utils.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// posix_charset_matcher
//
template<typename Traits>
struct posix_charset_matcher
: quant_style_fixed_width<1>
{
typedef Traits traits_type;
typedef typename Traits::char_class_type char_class_type;
posix_charset_matcher(char_class_type m, bool no)
: not_(no)
, mask_(m)
{
BOOST_ASSERT(0 != this->mask_);
}
void inverse()
{
this->not_ = !this->not_;
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
if(state.eos() || this->not_ == traits_cast<Traits>(state).isctype(
*state.cur_, this->mask_))
{
return false;
}
++state.cur_;
if(next.match(state))
{
return true;
}
--state.cur_;
return false;
}
bool not_;
char_class_type mask_;
};
}}}
#endif

View File

@@ -0,0 +1,174 @@
///////////////////////////////////////////////////////////////////////////////
// predicate_matcher.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_CORE_MATCHER_PREDICATE_MATCHER_HPP_EAN_03_22_2007
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_PREDICATE_MATCHER_HPP_EAN_03_22_2007
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/mpl/not.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/matcher/action_matcher.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/proto/core.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// predicate_context
//
template<typename BidiIter>
struct predicate_context
{
explicit predicate_context(int sub, sub_match_impl<BidiIter> const *sub_matches, action_args_type *action_args)
: sub_(sub)
, sub_matches_(sub_matches)
, action_args_(action_args)
{}
action_args_type const &args() const
{
return *this->action_args_;
}
// eval_terminal
template<typename Expr, typename Arg>
struct eval_terminal
: proto::default_eval<Expr, predicate_context const>
{};
template<typename Expr, typename Arg>
struct eval_terminal<Expr, reference_wrapper<Arg> >
{
typedef Arg &result_type;
result_type operator()(Expr &expr, predicate_context const &) const
{
return proto::value(expr).get();
}
};
template<typename Expr>
struct eval_terminal<Expr, any_matcher>
{
typedef sub_match<BidiIter> const &result_type;
result_type operator()(Expr &, predicate_context const &ctx) const
{
return ctx.sub_matches_[ctx.sub_];
}
};
template<typename Expr>
struct eval_terminal<Expr, mark_placeholder>
{
typedef sub_match<BidiIter> const &result_type;
result_type operator()(Expr &expr, predicate_context const &ctx) const
{
return ctx.sub_matches_[proto::value(expr).mark_number_];
}
};
template<typename Expr, typename Type, typename Int>
struct eval_terminal<Expr, action_arg<Type, Int> >
{
typedef typename action_arg<Type, Int>::reference result_type;
result_type operator()(Expr &expr, predicate_context const &ctx) const
{
action_args_type::const_iterator where_ = ctx.args().find(&typeid(proto::value(expr)));
if(where_ == ctx.args().end())
{
BOOST_THROW_EXCEPTION(
regex_error(
regex_constants::error_badarg
, "An argument to an action was unspecified"
)
);
}
return proto::value(expr).cast(where_->second);
}
};
// eval
template<typename Expr, typename Tag = typename Expr::proto_tag>
struct eval
: proto::default_eval<Expr, predicate_context const>
{};
template<typename Expr>
struct eval<Expr, proto::tag::terminal>
: eval_terminal<Expr, typename proto::result_of::value<Expr>::type>
{};
#if BOOST_VERSION >= 103500
template<typename Expr>
struct eval<Expr, proto::tag::mem_ptr>
: mem_ptr_eval<Expr, predicate_context const>
{};
#endif
int sub_;
sub_match_impl<BidiIter> const *sub_matches_;
action_args_type *action_args_;
};
///////////////////////////////////////////////////////////////////////////////
// AssertionFunctor
//
struct AssertionFunctor
: proto::function<
proto::terminal<check_tag>
, proto::terminal<proto::_>
>
{};
///////////////////////////////////////////////////////////////////////////////
// predicate_matcher
//
template<typename Predicate>
struct predicate_matcher
: quant_style_assertion
{
int sub_;
Predicate predicate_;
predicate_matcher(Predicate const &pred, int sub)
: sub_(sub)
, predicate_(pred)
{
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
// Predicate is check(assertion), where assertion can be
// a lambda or a function object.
return this->match_(state, next, proto::matches<Predicate, AssertionFunctor>());
}
private:
template<typename BidiIter, typename Next>
bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const
{
sub_match<BidiIter> const &sub = state.sub_match(this->sub_);
return proto::value(proto::child_c<1>(this->predicate_))(sub) && next.match(state);
}
template<typename BidiIter, typename Next>
bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const
{
predicate_context<BidiIter> ctx(this->sub_, state.sub_matches_, state.action_args_);
return proto::eval(proto::child_c<1>(this->predicate_), ctx) && next.match(state);
}
};
}}}
#endif // BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_PREDICATE_MATCHER_HPP_EAN_03_22_2007

View File

@@ -0,0 +1,87 @@
///////////////////////////////////////////////////////////////////////////////
// range_matcher.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_CORE_MATCHER_RANGE_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_RANGE_MATCHER_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 : 4100) // unreferenced formal parameter
#endif
#include <boost/mpl/bool.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// range_matcher
//
template<typename Traits, typename ICase>
struct range_matcher
: quant_style_fixed_width<1>
{
typedef typename Traits::char_type char_type;
typedef ICase icase_type;
char_type ch_min_;
char_type ch_max_;
bool not_;
range_matcher(char_type ch_min, char_type ch_max, bool no, Traits const &)
: ch_min_(ch_min)
, ch_max_(ch_max)
, not_(no)
{
}
void inverse()
{
this->not_ = !this->not_;
}
bool in_range(Traits const &tr, char_type ch, mpl::false_) const // case-sensitive
{
return tr.in_range(this->ch_min_, this->ch_max_, ch);
}
bool in_range(Traits const &tr, char_type ch, mpl::true_) const // case-insensitive
{
return tr.in_range_nocase(this->ch_min_, this->ch_max_, ch);
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
if(state.eos() || this->not_ ==
this->in_range(traits_cast<Traits>(state), *state.cur_, icase_type()))
{
return false;
}
++state.cur_;
if(next.match(state))
{
return true;
}
--state.cur_;
return false;
}
};
}}}
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma warning(pop)
#endif
#endif

View File

@@ -0,0 +1,77 @@
///////////////////////////////////////////////////////////////////////////////
// regex_byref_matcher.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_CORE_MATCHER_REGEX_BYREF_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_REGEX_BYREF_MATCHER_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/shared_ptr.hpp>
#include <boost/xpressive/regex_error.hpp>
#include <boost/xpressive/regex_constants.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/core/regex_impl.hpp>
#include <boost/xpressive/detail/core/adaptor.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// regex_byref_matcher
//
template<typename BidiIter>
struct regex_byref_matcher
: quant_style<quant_variable_width, unknown_width::value, false>
{
// avoid cyclic references by holding a weak_ptr to the
// regex_impl struct
weak_ptr<regex_impl<BidiIter> > wimpl_;
// the basic_regex object holds a ref-count to this regex_impl, so
// we don't have to worry about it going away.
regex_impl<BidiIter> const *pimpl_;
regex_byref_matcher(shared_ptr<regex_impl<BidiIter> > const &impl)
: wimpl_(impl)
, pimpl_(impl.get())
{
BOOST_ASSERT(this->pimpl_);
}
template<typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
BOOST_ASSERT(this->pimpl_ == this->wimpl_.lock().get());
BOOST_XPR_ENSURE_(this->pimpl_->xpr_, regex_constants::error_badref, "bad regex reference");
return push_context_match(*this->pimpl_, state, this->wrap_(next, is_static_xpression<Next>()));
}
private:
template<typename Next>
static xpression_adaptor<reference_wrapper<Next const>, matchable<BidiIter> > wrap_(Next const &next, mpl::true_)
{
// wrap the static xpression in a matchable interface
return xpression_adaptor<reference_wrapper<Next const>, matchable<BidiIter> >(boost::cref(next));
}
template<typename Next>
static Next const &wrap_(Next const &next, mpl::false_)
{
return next;
}
};
}}}
#endif

View File

@@ -0,0 +1,63 @@
///////////////////////////////////////////////////////////////////////////////
// regex_matcher.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_CORE_MATCHER_REGEX_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_REGEX_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/mpl/assert.hpp>
#include <boost/xpressive/regex_error.hpp>
#include <boost/xpressive/regex_constants.hpp>
#include <boost/xpressive/detail/core/regex_impl.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/core/adaptor.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// regex_matcher
//
template<typename BidiIter>
struct regex_matcher
: quant_style<quant_variable_width, unknown_width::value, false>
{
regex_impl<BidiIter> impl_;
regex_matcher(shared_ptr<regex_impl<BidiIter> > const &impl)
: impl_()
{
this->impl_.xpr_ = impl->xpr_;
this->impl_.traits_ = impl->traits_;
this->impl_.mark_count_ = impl->mark_count_;
this->impl_.hidden_mark_count_ = impl->hidden_mark_count_;
BOOST_XPR_ENSURE_(this->impl_.xpr_, regex_constants::error_badref, "bad regex reference");
}
template<typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
// regex_matcher is used for embeding a dynamic regex in a static regex. As such,
// Next will always point to a static regex.
BOOST_MPL_ASSERT((is_static_xpression<Next>));
// wrap the static xpression in a matchable interface
xpression_adaptor<reference_wrapper<Next const>, matchable<BidiIter> > adaptor(boost::cref(next));
return push_context_match(this->impl_, state, adaptor);
}
};
}}}
#endif

View File

@@ -0,0 +1,69 @@
///////////////////////////////////////////////////////////////////////////////
// repeat_end_matcher.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_CORE_MATCHER_REPEAT_BEGIN_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_REPEAT_BEGIN_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
//
// Note: here is the variable-width xpression quantifier. It always
// matches at least once, so if the min is 0, it is the responsibility
// of the parser to make it alternate with an epsilon matcher.
//
///////////////////////////////////////////////////////////////////////////////
// repeat_begin_matcher
//
struct repeat_begin_matcher
: quant_style<quant_variable_width, unknown_width::value, false>
{
int mark_number_;
repeat_begin_matcher(int mark_number)
: mark_number_(mark_number)
{
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
sub_match_impl<BidiIter> &br = state.sub_match(this->mark_number_);
unsigned int old_repeat_count = br.repeat_count_;
bool old_zero_width = br.zero_width_;
br.repeat_count_ = 1;
br.zero_width_ = false;
// "push" next onto the stack, so it can be "popped" in
// repeat_end_matcher and used to loop back.
if(next.BOOST_NESTED_TEMPLATE push_match<Next>(state))
{
return true;
}
br.repeat_count_ = old_repeat_count;
br.zero_width_ = old_zero_width;
return false;
}
};
}}}
#endif

View File

@@ -0,0 +1,121 @@
///////////////////////////////////////////////////////////////////////////////
// repeat_end_matcher.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_CORE_MATCHER_REPEAT_END_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_REPEAT_END_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/mpl/bool.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// repeat_end_matcher
//
template<typename Greedy>
struct repeat_end_matcher
: quant_style<quant_none, 0, false>
{
typedef Greedy greedy_type;
int mark_number_;
unsigned int min_, max_;
mutable void const *back_;
repeat_end_matcher(int mark_nbr, unsigned int min, unsigned int max)
: mark_number_(mark_nbr)
, min_(min)
, max_(max)
, back_(0)
{
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
// prevent repeated zero-width sub-matches from causing infinite recursion
sub_match_impl<BidiIter> &br = state.sub_match(this->mark_number_);
if(br.zero_width_ && br.begin_ == state.cur_)
{
return next.skip_match(state);
}
bool old_zero_width = br.zero_width_;
br.zero_width_ = (br.begin_ == state.cur_);
if(this->match_(state, next, greedy_type()))
{
return true;
}
br.zero_width_ = old_zero_width;
return false;
}
// greedy, variable-width quantifier
template<typename BidiIter, typename Next>
bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const
{
sub_match_impl<BidiIter> &br = state.sub_match(this->mark_number_);
if(this->max_ > br.repeat_count_)
{
++br.repeat_count_;
// loop back to the expression "pushed" in repeat_begin_matcher::match
if(next.top_match(state, this->back_))
{
return true;
}
else if(--br.repeat_count_ < this->min_)
{
return false;
}
}
// looping finished, continue matching the rest of the pattern
return next.skip_match(state);
}
// non-greedy, variable-width quantifier
template<typename BidiIter, typename Next>
bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const
{
sub_match_impl<BidiIter> &br = state.sub_match(this->mark_number_);
if(this->min_ <= br.repeat_count_)
{
if(next.skip_match(state))
{
return true;
}
}
if(this->max_ > br.repeat_count_)
{
++br.repeat_count_;
if(next.top_match(state, this->back_))
{
return true;
}
--br.repeat_count_;
}
return false;
}
};
}}}
#endif

View File

@@ -0,0 +1,100 @@
///////////////////////////////////////////////////////////////////////////////
// set.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_SET_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_SET_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 constant
# pragma warning(disable : 4100) // unreferenced formal parameter
# pragma warning(disable : 4351) // vc8 new behavior: elements of array 'foo' will be default initialized
#endif
#include <algorithm>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/same_traits.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// set_matcher
//
template<typename Traits, typename Size>
struct set_matcher
: quant_style_fixed_width<1>
{
typedef typename Traits::char_type char_type;
char_type set_[ Size::value ];
bool not_;
bool icase_;
set_matcher()
: set_()
, not_(false)
, icase_(false)
{
}
void inverse()
{
this->not_ = !this->not_;
}
void nocase(Traits const &tr)
{
this->icase_ = true;
for(int i = 0; i < Size::value; ++i)
{
this->set_[i] = tr.translate_nocase(this->set_[i]);
}
}
bool in_set(Traits const &tr, char_type ch) const
{
char_type const *begin = &this->set_[0], *end = begin + Size::value;
ch = this->icase_ ? tr.translate_nocase(ch) : tr.translate(ch);
return end != std::find(begin, end, ch);
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
if(state.eos() || this->not_ == this->in_set(traits_cast<Traits>(state), *state.cur_))
{
return false;
}
if(++state.cur_, next.match(state))
{
return true;
}
return --state.cur_, false;
}
};
///////////////////////////////////////////////////////////////////////////////
// set_initializer
struct set_initializer
{
};
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma warning(pop)
#endif
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,234 @@
///////////////////////////////////////////////////////////////////////////////
// simple_repeat_matcher.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_CORE_MATCHER_SIMPLE_REPEAT_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_SIMPLE_REPEAT_MATCHER_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/if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/next_prior.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/static/type_traits.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// simple_repeat_traits
//
struct greedy_slow_tag {};
struct greedy_fast_tag {};
struct non_greedy_tag {};
typedef static_xpression<any_matcher, true_xpression> any_sxpr;
typedef matcher_wrapper<any_matcher> any_dxpr;
template<typename Xpr, typename Greedy, typename Random>
struct simple_repeat_traits
{
typedef typename mpl::if_c<Greedy::value, greedy_slow_tag, non_greedy_tag>::type tag_type;
};
template<>
struct simple_repeat_traits<any_sxpr, mpl::true_, mpl::true_>
{
typedef greedy_fast_tag tag_type;
};
template<>
struct simple_repeat_traits<any_dxpr, mpl::true_, mpl::true_>
{
typedef greedy_fast_tag tag_type;
};
///////////////////////////////////////////////////////////////////////////////
// simple_repeat_matcher
//
template<typename Xpr, typename Greedy>
struct simple_repeat_matcher
: quant_style_variable_width
{
typedef Xpr xpr_type;
typedef Greedy greedy_type;
Xpr xpr_;
unsigned int min_, max_;
std::size_t width_;
mutable bool leading_;
simple_repeat_matcher(Xpr const &xpr, unsigned int min, unsigned int max, std::size_t width)
: xpr_(xpr)
, min_(min)
, max_(max)
, width_(width)
, leading_(false)
{
// it is the job of the parser to make sure this never happens
BOOST_ASSERT(min <= max);
BOOST_ASSERT(0 != max);
BOOST_ASSERT(0 != width && unknown_width() != width);
BOOST_ASSERT(Xpr::width == unknown_width() || Xpr::width == width);
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
typedef mpl::bool_<is_random<BidiIter>::value> is_rand;
typedef typename simple_repeat_traits<Xpr, greedy_type, is_rand>::tag_type tag_type;
return this->match_(state, next, tag_type());
}
// greedy, fixed-width quantifier
template<typename BidiIter, typename Next>
bool match_(match_state<BidiIter> &state, Next const &next, greedy_slow_tag) const
{
int const diff = -static_cast<int>(Xpr::width == unknown_width::value ? this->width_ : Xpr::width);
unsigned int matches = 0;
BidiIter const tmp = state.cur_;
// greedily match as much as we can
while(matches < this->max_ && this->xpr_.match(state))
{
++matches;
}
// If this repeater is at the front of the pattern, note
// how much of the input we consumed so that a repeated search
// doesn't have to cover the same ground again.
if(this->leading_)
{
state.next_search_ = (matches && matches < this->max_)
? state.cur_
: (tmp == state.end_) ? tmp : boost::next(tmp);
}
if(this->min_ > matches)
{
state.cur_ = tmp;
return false;
}
// try matching the rest of the pattern, and back off if necessary
for(; ; --matches, std::advance(state.cur_, diff))
{
if(next.match(state))
{
return true;
}
else if(this->min_ == matches)
{
state.cur_ = tmp;
return false;
}
}
}
// non-greedy fixed-width quantification
template<typename BidiIter, typename Next>
bool match_(match_state<BidiIter> &state, Next const &next, non_greedy_tag) const
{
BOOST_ASSERT(!this->leading_);
BidiIter const tmp = state.cur_;
unsigned int matches = 0;
for(; matches < this->min_; ++matches)
{
if(!this->xpr_.match(state))
{
state.cur_ = tmp;
return false;
}
}
do
{
if(next.match(state))
{
return true;
}
}
while(matches++ < this->max_ && this->xpr_.match(state));
state.cur_ = tmp;
return false;
}
// when greedily matching any character, skip to the end instead of iterating there.
template<typename BidiIter, typename Next>
bool match_(match_state<BidiIter> &state, Next const &next, greedy_fast_tag) const
{
BidiIter const tmp = state.cur_;
std::size_t const diff_to_end = static_cast<std::size_t>(state.end_ - tmp);
// is there enough room?
if(this->min_ > diff_to_end)
{
if(this->leading_)
{
state.next_search_ = (tmp == state.end_) ? tmp : boost::next(tmp);
}
return false;
}
BidiIter const min_iter = tmp + this->min_;
state.cur_ += (std::min)((std::size_t)this->max_, diff_to_end);
if(this->leading_)
{
state.next_search_ = (diff_to_end && diff_to_end < this->max_)
? state.cur_
: (tmp == state.end_) ? tmp : boost::next(tmp);
}
for(;; --state.cur_)
{
if(next.match(state))
{
return true;
}
else if(min_iter == state.cur_)
{
state.cur_ = tmp;
return false;
}
}
}
detail::width get_width() const
{
if(this->min_ != this->max_)
{
return unknown_width::value;
}
return this->min_ * this->width_;
}
private:
simple_repeat_matcher &operator =(simple_repeat_matcher const &);
};
// BUGBUG can all non-greedy quantification be done with the fixed width quantifier?
// BUGBUG matchers are chained together using static_xpression so that matchers to
// the left can invoke matchers to the right. This is so that if the left matcher
// succeeds but the right matcher fails, the left matcher is given the opportunity
// to try something else. This is how backtracking works. However, if the left matcher
// can succeed only one way (as with any_matcher, for example), it does not need
// backtracking. In this case, leaving its stack frame active is a waste of stack
// space. Can something be done?
}}}
#endif

View File

@@ -0,0 +1,90 @@
///////////////////////////////////////////////////////////////////////////////
// string_matcher.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_CORE_MATCHER_STRING_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_STRING_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <string>
#include <boost/mpl/bool.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
#include <boost/xpressive/detail/utility/algorithm.hpp>
#include <boost/xpressive/detail/utility/traits_utils.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// string_matcher
//
template<typename Traits, typename ICase>
struct string_matcher
: quant_style_fixed_unknown_width
{
typedef typename Traits::char_type char_type;
typedef typename Traits::string_type string_type;
typedef ICase icase_type;
string_type str_;
char_type const *end_;
string_matcher(string_type const &str, Traits const &tr)
: str_(str)
, end_()
{
typename range_iterator<string_type>::type cur = boost::begin(this->str_);
typename range_iterator<string_type>::type end = boost::end(this->str_);
for(; cur != end; ++cur)
{
*cur = detail::translate(*cur, tr, icase_type());
}
this->end_ = detail::data_end(str_);
}
string_matcher(string_matcher<Traits, ICase> const &that)
: str_(that.str_)
, end_(detail::data_end(str_))
{
}
template<typename BidiIter, typename Next>
bool match(match_state<BidiIter> &state, Next const &next) const
{
BidiIter const tmp = state.cur_;
char_type const *begin = detail::data_begin(this->str_);
for(; begin != this->end_; ++begin, ++state.cur_)
{
if(state.eos() ||
(detail::translate(*state.cur_, traits_cast<Traits>(state), icase_type()) != *begin))
{
state.cur_ = tmp;
return false;
}
}
if(next.match(state))
{
return true;
}
state.cur_ = tmp;
return false;
}
detail::width get_width() const
{
return boost::size(this->str_);
}
};
}}}
#endif

View File

@@ -0,0 +1,38 @@
///////////////////////////////////////////////////////////////////////////////
// true_matcher.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_CORE_MATCHER_TRUE_MATCHER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_TRUE_MATCHER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/core/state.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// true_matcher
//
struct true_matcher
: quant_style_assertion
{
template<typename BidiIter, typename Next>
static bool match(match_state<BidiIter> &, Next const &)
{
return true;
}
};
}}}
#endif

View File

@@ -0,0 +1,50 @@
///////////////////////////////////////////////////////////////////////////////
// matchers.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_CORE_MATCHERS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHERS_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//#include <boost/xpressive/detail/core/matcher/action_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/alternate_end_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/alternate_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/any_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/assert_bol_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/assert_bos_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/assert_eol_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/assert_eos_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/assert_word_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/attr_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/charset_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/end_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/epsilon_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/keeper_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/literal_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/logical_newline_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/lookahead_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/lookbehind_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/mark_begin_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/mark_end_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/mark_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/optional_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/posix_charset_matcher.hpp>
//#include <boost/xpressive/detail/core/matcher/predicate_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/range_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/regex_byref_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/regex_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/repeat_begin_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/repeat_end_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/set_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/simple_repeat_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/string_matcher.hpp>
#include <boost/xpressive/detail/core/matcher/true_matcher.hpp>
#endif

View File

@@ -0,0 +1,116 @@
///////////////////////////////////////////////////////////////////////////////
// optimize.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_CORE_OPTIMIZE_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_OPTIMIZE_HPP_EAN_10_04_2005
#include <string>
#include <utility>
#include <boost/mpl/bool.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/xpressive/detail/core/finder.hpp>
#include <boost/xpressive/detail/core/linker.hpp>
#include <boost/xpressive/detail/core/peeker.hpp>
#include <boost/xpressive/detail/core/regex_impl.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// optimize_regex
//
template<typename BidiIter, typename Traits>
intrusive_ptr<finder<BidiIter> > optimize_regex
(
xpression_peeker<typename iterator_value<BidiIter>::type> const &peeker
, Traits const &tr
, mpl::false_
)
{
if(peeker.line_start())
{
return intrusive_ptr<finder<BidiIter> >
(
new line_start_finder<BidiIter, Traits>(tr)
);
}
else if(peeker.leading_simple_repeat())
{
return intrusive_ptr<finder<BidiIter> >
(
new leading_simple_repeat_finder<BidiIter>()
);
}
else if(256 != peeker.bitset().count())
{
return intrusive_ptr<finder<BidiIter> >
(
new hash_peek_finder<BidiIter, Traits>(peeker.bitset())
);
}
return intrusive_ptr<finder<BidiIter> >();
}
///////////////////////////////////////////////////////////////////////////////
// optimize_regex
//
template<typename BidiIter, typename Traits>
intrusive_ptr<finder<BidiIter> > optimize_regex
(
xpression_peeker<typename iterator_value<BidiIter>::type> const &peeker
, Traits const &tr
, mpl::true_
)
{
typedef typename iterator_value<BidiIter>::type char_type;
// if we have a leading string literal, initialize a boyer-moore struct with it
peeker_string<char_type> const &str = peeker.get_string();
if(str.begin_ != str.end_)
{
BOOST_ASSERT(1 == peeker.bitset().count());
return intrusive_ptr<finder<BidiIter> >
(
new boyer_moore_finder<BidiIter, Traits>(str.begin_, str.end_, tr, str.icase_)
);
}
return optimize_regex<BidiIter>(peeker, tr, mpl::false_());
}
///////////////////////////////////////////////////////////////////////////////
// common_compile
//
template<typename BidiIter, typename Traits>
void common_compile
(
intrusive_ptr<matchable_ex<BidiIter> const> const &regex
, regex_impl<BidiIter> &impl
, Traits const &tr
)
{
typedef typename iterator_value<BidiIter>::type char_type;
// "link" the regex
xpression_linker<char_type> linker(tr);
regex->link(linker);
// "peek" into the compiled regex to see if there are optimization opportunities
hash_peek_bitset<char_type> bset;
xpression_peeker<char_type> peeker(bset, tr, linker.has_backrefs());
regex->peek(peeker);
// optimization: get the peek chars OR the boyer-moore search string
impl.finder_ = optimize_regex<BidiIter>(peeker, tr, is_random<BidiIter>());
impl.xpr_ = regex;
}
}}} // namespace boost::xpressive
#endif

View File

@@ -0,0 +1,284 @@
///////////////////////////////////////////////////////////////////////////////
// peeker.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_CORE_PEEKER_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_PEEKER_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <string>
#include <typeinfo>
#include <boost/assert.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/size_t.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/matchers.hpp>
#include <boost/xpressive/detail/utility/hash_peek_bitset.hpp>
#include <boost/xpressive/detail/utility/never_true.hpp>
#include <boost/xpressive/detail/utility/algorithm.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// peeker_string
//
template<typename Char>
struct peeker_string
{
Char const *begin_;
Char const *end_;
bool icase_;
};
///////////////////////////////////////////////////////////////////////////////
// char_sink
//
template<typename Traits, bool ICase>
struct char_sink
{
typedef typename Traits::char_type char_type;
char_sink(hash_peek_bitset<char_type> &bset, Traits const &tr)
: bset_(bset)
, traits_(tr)
{}
void operator()(char_type ch) const
{
this->bset_.set_char(ch, ICase, this->traits_);
}
hash_peek_bitset<char_type> &bset_;
Traits const &traits_;
private:
char_sink &operator =(char_sink const &);
};
///////////////////////////////////////////////////////////////////////////////
// xpression_peeker
//
template<typename Char>
struct xpression_peeker
{
template<typename Traits>
xpression_peeker(hash_peek_bitset<Char> &bset, Traits const &tr, bool has_backrefs = false)
: bset_(bset)
, str_()
, line_start_(false)
, traits_(0)
, traits_type_(0)
, leading_simple_repeat_(0)
, has_backrefs_(has_backrefs)
{
this->set_traits(tr);
}
///////////////////////////////////////////////////////////////////////////////
// accessors
peeker_string<Char> const &get_string() const
{
return this->str_;
}
bool line_start() const
{
return this->line_start_;
}
bool leading_simple_repeat() const
{
return 0 < this->leading_simple_repeat_;
}
hash_peek_bitset<Char> const &bitset() const
{
return this->bset_;
}
///////////////////////////////////////////////////////////////////////////////
// modifiers
void fail()
{
this->bset_.set_all();
}
template<typename Matcher>
mpl::false_ accept(Matcher const &)
{
this->fail();
return mpl::false_();
}
mpl::true_ accept(mark_begin_matcher const &)
{
if(this->has_backrefs_)
{
--this->leading_simple_repeat_;
}
return mpl::true_();
}
mpl::true_ accept(repeat_begin_matcher const &)
{
--this->leading_simple_repeat_;
return mpl::true_();
}
template<typename Traits>
mpl::true_ accept(assert_bol_matcher<Traits> const &)
{
this->line_start_ = true;
return mpl::true_();
}
template<typename Traits, typename ICase>
mpl::false_ accept(literal_matcher<Traits, ICase, mpl::false_> const &xpr)
{
this->bset_.set_char(xpr.ch_, ICase(), this->get_traits_<Traits>());
return mpl::false_();
}
template<typename Traits, typename ICase>
mpl::false_ accept(string_matcher<Traits, ICase> const &xpr)
{
this->bset_.set_char(xpr.str_[0], ICase(), this->get_traits_<Traits>());
this->str_.begin_ = detail::data_begin(xpr.str_);
this->str_.end_ = detail::data_end(xpr.str_);
this->str_.icase_ = ICase::value;
return mpl::false_();
}
template<typename Alternates, typename Traits>
mpl::false_ accept(alternate_matcher<Alternates, Traits> const &xpr)
{
BOOST_ASSERT(0 != xpr.bset_.count());
this->bset_.set_bitset(xpr.bset_);
return mpl::false_();
}
template<typename Matcher, typename Traits, typename ICase>
mpl::false_ accept(attr_matcher<Matcher, Traits, ICase> const &xpr)
{
xpr.sym_.peek(char_sink<Traits, ICase::value>(this->bset_, this->get_traits_<Traits>()));
return mpl::false_();
}
template<typename Xpr, typename Greedy>
mpl::false_ accept(optional_matcher<Xpr, Greedy> const &)
{
this->fail(); // a union of xpr and next
return mpl::false_();
}
template<typename Xpr, typename Greedy>
mpl::false_ accept(optional_mark_matcher<Xpr, Greedy> const &)
{
this->fail(); // a union of xpr and next
return mpl::false_();
}
//template<typename Xpr, typename Greedy>
//mpl::true_ accept(optional_matcher<Xpr, Greedy> const &xpr)
//{
// xpr.xpr_.peek(*this); // a union of xpr and next
// return mpl::true_();
//}
//template<typename Xpr, typename Greedy>
//mpl::true_ accept(optional_mark_matcher<Xpr, Greedy> const &xpr)
//{
// xpr.xpr_.peek(*this); // a union of xpr and next
// return mpl::true_();
//}
template<typename Traits>
mpl::false_ accept(posix_charset_matcher<Traits> const &xpr)
{
this->bset_.set_class(xpr.mask_, xpr.not_, this->get_traits_<Traits>());
return mpl::false_();
}
template<typename ICase, typename Traits>
typename enable_if<is_narrow_char<typename Traits::char_type>, mpl::false_>::type
accept(charset_matcher<Traits, ICase, basic_chset<Char> > const &xpr)
{
BOOST_ASSERT(0 != xpr.charset_.base().count());
this->bset_.set_charset(xpr.charset_, ICase());
return mpl::false_();
}
template<typename Traits, typename ICase>
mpl::false_ accept(range_matcher<Traits, ICase> const &xpr)
{
this->bset_.set_range(xpr.ch_min_, xpr.ch_max_, xpr.not_, ICase(), this->get_traits_<Traits>());
return mpl::false_();
}
template<typename Xpr, typename Greedy>
mpl::false_ accept(simple_repeat_matcher<Xpr, Greedy> const &xpr)
{
if(Greedy() && 1U == xpr.width_)
{
++this->leading_simple_repeat_;
xpr.leading_ = this->leading_simple_repeat();
}
0 != xpr.min_ ? xpr.xpr_.peek(*this) : this->fail(); // could be a union of xpr and next
return mpl::false_();
}
template<typename Xpr>
mpl::false_ accept(keeper_matcher<Xpr> const &xpr)
{
xpr.xpr_.peek(*this);
return mpl::false_();
}
template<typename Traits>
void set_traits(Traits const &tr)
{
if(0 == this->traits_)
{
this->traits_ = &tr;
this->traits_type_ = &typeid(Traits);
}
else if(*this->traits_type_ != typeid(Traits) || this->get_traits_<Traits>() != tr)
{
this->fail(); // traits mis-match! set all and bail
}
}
private:
xpression_peeker(xpression_peeker const &);
xpression_peeker &operator =(xpression_peeker const &);
template<typename Traits>
Traits const &get_traits_() const
{
BOOST_ASSERT(!!(*this->traits_type_ == typeid(Traits)));
return *static_cast<Traits const *>(this->traits_);
}
hash_peek_bitset<Char> &bset_;
peeker_string<Char> str_;
bool str_icase_;
bool line_start_;
void const *traits_;
std::type_info const *traits_type_;
int leading_simple_repeat_;
bool has_backrefs_;
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,129 @@
///////////////////////////////////////////////////////////////////////////////
// quant_style.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_CORE_QUANT_STYLE_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_QUANT_STYLE_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/config.hpp>
#include <boost/mpl/has_xxx.hpp>
#include <boost/xpressive/detail/utility/width.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
namespace boost { namespace xpressive { namespace detail
{
BOOST_MPL_HAS_XXX_TRAIT_DEF(is_boost_xpressive_xpression_)
///////////////////////////////////////////////////////////////////////////////
// is_xpr
//
template<typename Xpr>
struct is_xpr
: has_is_boost_xpressive_xpression_<Xpr>
{};
///////////////////////////////////////////////////////////////////////////////
// quant_enum
//
enum quant_enum
{
quant_none,
quant_fixed_width,
quant_variable_width
};
///////////////////////////////////////////////////////////////////////////////
// quant_style
//
template<quant_enum QuantStyle, std::size_t Width = unknown_width::value, bool Pure = true>
struct quant_style
{
typedef void is_boost_xpressive_xpression_;
// Which quantification strategy to use?
BOOST_STATIC_CONSTANT(int, quant = QuantStyle);
// how many characters this matcher consumes
BOOST_STATIC_CONSTANT(std::size_t, width = Width);
// whether this matcher has observable side-effects
BOOST_STATIC_CONSTANT(bool, pure = Pure);
static detail::width get_width()
{
return width;
}
};
#define BOOST_XPR_QUANT_STYLE(Style, Width, Pure) \
typedef void is_boost_xpressive_xpression_; \
BOOST_STATIC_CONSTANT(int, quant = Style); \
BOOST_STATIC_CONSTANT(std::size_t, width = Width); \
BOOST_STATIC_CONSTANT(bool, pure = Pure); \
static detail::width get_width() { return width; } \
/**/
// // Replace transmogrify stupidity with rebindable matchers/placeholders
//#define BOOST_XPR_IDENTITY_REBIND(TYPE) \/
// template<typename BidiIter, typename ICase, typename Traits> \/
// struct rebind \/
// { \/
// typedef TYPE type; \/
// }; \/
// /**/
///////////////////////////////////////////////////////////////////////////////
// quant_style_none
// this sub-expression cannot be quantified
typedef quant_style<quant_none> quant_style_none;
///////////////////////////////////////////////////////////////////////////////
// quant_style_fixed_unknown_width
// this sub-expression is fixed width for the purpose of quantification, but
// the width cannot be determined at compile time. An example would be the
// string_matcher or the mark_matcher.
typedef quant_style<quant_fixed_width> quant_style_fixed_unknown_width;
///////////////////////////////////////////////////////////////////////////////
// quant_style_variable_width
// this sub-expression can match a variable number of characters
typedef quant_style<quant_variable_width> quant_style_variable_width;
///////////////////////////////////////////////////////////////////////////////
// quant_style_fixed_width
// for when the sub-expression has a fixed width that is known at compile time
template<std::size_t Width>
struct quant_style_fixed_width
: quant_style<quant_fixed_width, Width>
{
};
///////////////////////////////////////////////////////////////////////////////
// quant_style_assertion
// a zero-width assertion.
struct quant_style_assertion
: quant_style<quant_none, 0>
{
};
///////////////////////////////////////////////////////////////////////////////
// quant_type
//
template<typename Matcher>
struct quant_type
: mpl::int_<Matcher::quant>
{
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,24 @@
///////////////////////////////////////////////////////////////////////////////
/// \file regex_domain.hpp
/// Contains the definition of the regex_domain type
//
// Copyright 2009 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_CORE_REGEX_DOMAIN_HPP_EAN_12_12_2009
#define BOOST_XPRESSIVE_DETAIL_CORE_REGEX_DOMAIN_HPP_EAN_12_12_2009
#include <boost/xpressive/xpressive_fwd.hpp>
#include <boost/proto/traits.hpp>
#include <boost/proto/domain.hpp>
#include <boost/proto/generate.hpp>
namespace boost { namespace xpressive { namespace detail
{
struct regex_domain
: proto::domain<proto::default_generator, proto::not_<proto::address_of<proto::_> > >
{};
}}}
#endif

View File

@@ -0,0 +1,212 @@
///////////////////////////////////////////////////////////////////////////////
// regex_impl.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_CORE_REGEX_IMPL_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_REGEX_IMPL_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <vector>
#include <boost/intrusive_ptr.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/utility/tracking_ptr.hpp>
#include <boost/xpressive/detail/utility/counted_base.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// finder
template<typename BidiIter>
struct finder
: counted_base<finder<BidiIter> >
{
virtual ~finder() {}
virtual bool ok_for_partial_matches() const { return true; }
virtual bool operator ()(match_state<BidiIter> &state) const = 0;
};
///////////////////////////////////////////////////////////////////////////////
// traits
template<typename Char>
struct traits
: counted_base<traits<Char> >
{
virtual ~traits() {}
virtual Char tolower(Char ch) const = 0;
virtual Char toupper(Char ch) const = 0;
virtual bool in_range(Char from, Char to, Char ch) const = 0;
virtual int value(Char ch, int radix) const = 0;
};
///////////////////////////////////////////////////////////////////////////////
// named_mark
template<typename Char>
struct named_mark
{
typedef typename detail::string_type<Char>::type string_type;
named_mark(string_type name, std::size_t mark_nbr)
: name_(name)
, mark_nbr_(mark_nbr)
{}
string_type name_;
std::size_t mark_nbr_;
};
///////////////////////////////////////////////////////////////////////////////
// traits_holder
template<typename Traits>
struct traits_holder
: traits<typename Traits::char_type>
{
typedef typename Traits::char_type char_type;
explicit traits_holder(Traits const &tr)
: traits_(tr)
{
}
Traits const &traits() const
{
return this->traits_;
}
char_type tolower(char_type ch) const
{
return this->tolower_(ch, typename Traits::version_tag());
}
char_type toupper(char_type ch) const
{
return this->toupper_(ch, typename Traits::version_tag());
}
int value(char_type ch, int radix) const
{
return this->traits_.value(ch, radix);
}
bool in_range(char_type from, char_type to, char_type ch) const
{
return this->traits_.in_range(from, to, ch);
}
private:
char_type tolower_(char_type ch, regex_traits_version_1_tag) const
{
return ch;
}
char_type toupper_(char_type ch, regex_traits_version_1_tag) const
{
return ch;
}
char_type tolower_(char_type ch, regex_traits_version_2_tag) const
{
return this->traits_.tolower(ch);
}
char_type toupper_(char_type ch, regex_traits_version_2_tag) const
{
return this->traits_.toupper(ch);
}
Traits traits_;
};
///////////////////////////////////////////////////////////////////////////////
// regex_impl
//
template<typename BidiIter>
struct regex_impl
: enable_reference_tracking<regex_impl<BidiIter> >
{
typedef typename iterator_value<BidiIter>::type char_type;
regex_impl()
: enable_reference_tracking<regex_impl<BidiIter> >()
, xpr_()
, traits_()
, finder_()
, named_marks_()
, mark_count_(0)
, hidden_mark_count_(0)
{
#ifdef BOOST_XPRESSIVE_DEBUG_CYCLE_TEST
++instances;
#endif
}
regex_impl(regex_impl<BidiIter> const &that)
: enable_reference_tracking<regex_impl<BidiIter> >(that)
, xpr_(that.xpr_)
, traits_(that.traits_)
, finder_(that.finder_)
, named_marks_(that.named_marks_)
, mark_count_(that.mark_count_)
, hidden_mark_count_(that.hidden_mark_count_)
{
#ifdef BOOST_XPRESSIVE_DEBUG_CYCLE_TEST
++instances;
#endif
}
~regex_impl()
{
#ifdef BOOST_XPRESSIVE_DEBUG_CYCLE_TEST
--instances;
#endif
}
void swap(regex_impl<BidiIter> &that)
{
enable_reference_tracking<regex_impl<BidiIter> >::swap(that);
this->xpr_.swap(that.xpr_);
this->traits_.swap(that.traits_);
this->finder_.swap(that.finder_);
this->named_marks_.swap(that.named_marks_);
std::swap(this->mark_count_, that.mark_count_);
std::swap(this->hidden_mark_count_, that.hidden_mark_count_);
}
intrusive_ptr<matchable_ex<BidiIter> const> xpr_;
intrusive_ptr<traits<char_type> const> traits_;
intrusive_ptr<finder<BidiIter> > finder_;
std::vector<named_mark<char_type> > named_marks_;
std::size_t mark_count_;
std::size_t hidden_mark_count_;
#ifdef BOOST_XPRESSIVE_DEBUG_CYCLE_TEST
static int instances;
#endif
private:
regex_impl &operator =(regex_impl const &);
};
template<typename BidiIter>
void swap(regex_impl<BidiIter> &left, regex_impl<BidiIter> &right)
{
left.swap(right);
}
#ifdef BOOST_XPRESSIVE_DEBUG_CYCLE_TEST
template<typename BidiIter>
int regex_impl<BidiIter>::instances = 0;
#endif
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,134 @@
///////////////////////////////////////////////////////////////////////////////
// results_cache.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_CORE_RESULTS_CACHE_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_RESULTS_CACHE_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <cstddef>
#include <boost/detail/workaround.hpp>
#include <boost/assert.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/list.hpp>
#include <boost/xpressive/detail/core/access.hpp>
#include <boost/xpressive/match_results.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// nested_results
#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
template<typename BidiIter>
struct nested_results
: detail::list<match_results<BidiIter> >
{
friend struct results_cache<BidiIter>;
friend struct match_results<BidiIter>;
};
#else
template<typename BidiIter>
struct nested_results
: private detail::list<match_results<BidiIter> >
{
friend struct results_cache<BidiIter>;
friend struct xpressive::match_results<BidiIter>;
typedef list<xpressive::match_results<BidiIter> > base_type;
typedef typename base_type::iterator iterator;
typedef typename base_type::const_iterator const_iterator;
typedef typename base_type::pointer pointer;
typedef typename base_type::const_pointer const_pointer;
typedef typename base_type::reference reference;
typedef typename base_type::const_reference const_reference;
typedef typename base_type::size_type size_type;
using base_type::begin;
using base_type::end;
using base_type::size;
using base_type::empty;
using base_type::front;
using base_type::back;
};
#endif
///////////////////////////////////////////////////////////////////////////////
// results_cache
//
// cache storage for reclaimed match_results structs
template<typename BidiIter>
struct results_cache
{
typedef core_access<BidiIter> access;
match_results<BidiIter> &append_new(nested_results<BidiIter> &out)
{
if(this->cache_.empty())
{
out.push_back(match_results<BidiIter>());
}
else
{
BOOST_ASSERT(access::get_nested_results(this->cache_.back()).empty());
out.splice(out.end(), this->cache_, --this->cache_.end());
}
return out.back();
}
// move the last match_results struct into the cache
void reclaim_last(nested_results<BidiIter> &out)
{
BOOST_ASSERT(!out.empty());
// first, reclaim any nested results
nested_results<BidiIter> &nested = access::get_nested_results(out.back());
if(!nested.empty())
{
this->reclaim_all(nested);
}
// then, reclaim the last match_results
this->cache_.splice(this->cache_.end(), out, --out.end());
}
// move the last n match_results structs into the cache
void reclaim_last_n(nested_results<BidiIter> &out, std::size_t count)
{
for(; 0 != count; --count)
{
this->reclaim_last(out);
}
}
void reclaim_all(nested_results<BidiIter> &out)
{
typedef typename nested_results<BidiIter>::iterator iter_type;
// first, recursively reclaim all the nested results
for(iter_type begin = out.begin(); begin != out.end(); ++begin)
{
nested_results<BidiIter> &nested = access::get_nested_results(*begin);
if(!nested.empty())
{
this->reclaim_all(nested);
}
}
// next, reclaim the results themselves
this->cache_.splice(this->cache_.end(), out);
}
private:
nested_results<BidiIter> cache_;
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,401 @@
///////////////////////////////////////////////////////////////////////////////
// state.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_CORE_STATE_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_STATE_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/noncopyable.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/access.hpp>
#include <boost/xpressive/detail/core/action.hpp>
#include <boost/xpressive/detail/core/sub_match_vector.hpp>
#include <boost/xpressive/detail/utility/sequence_stack.hpp>
#include <boost/xpressive/detail/core/regex_impl.hpp>
#include <boost/xpressive/regex_constants.hpp>
namespace boost { namespace xpressive { namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// match_context
//
template<typename BidiIter>
struct match_context
{
typedef typename iterator_value<BidiIter>::type char_type;
match_context()
: results_ptr_(0)
, prev_context_(0)
, next_ptr_(0)
, traits_(0)
{
}
// pointer to the current match results, passed to actions as a parameter.
match_results<BidiIter> *results_ptr_;
// The previous match context, if this match_context corresponds to a nested regex invocation
match_context<BidiIter> *prev_context_;
// If this is a nested match, the "next" sub-expression to execute after the nested match
matchable<BidiIter> const *next_ptr_;
// A pointer to the current traits object
detail::traits<char_type> const *traits_;
};
///////////////////////////////////////////////////////////////////////////////
// attr_context
//
struct attr_context
{
// Slots for holding type-erased pointers to attributes
void const **attr_slots_;
// The previous attr context, if one exists
attr_context *prev_attr_context_;
};
///////////////////////////////////////////////////////////////////////////////
// match_flags
//
struct match_flags
{
bool match_all_;
bool match_prev_avail_;
bool match_bol_;
bool match_eol_;
bool match_not_bow_;
bool match_not_eow_;
bool match_not_null_;
bool match_continuous_;
bool match_partial_;
explicit match_flags(regex_constants::match_flag_type flags)
: match_all_(false)
, match_prev_avail_(0 != (flags & regex_constants::match_prev_avail))
, match_bol_(match_prev_avail_ || 0 == (flags & regex_constants::match_not_bol))
, match_eol_(0 == (flags & regex_constants::match_not_eol))
, match_not_bow_(!match_prev_avail_ && 0 != (flags & regex_constants::match_not_bow))
, match_not_eow_(0 != (flags & regex_constants::match_not_eow))
, match_not_null_(0 != (flags & regex_constants::match_not_null))
, match_continuous_(0 != (flags & regex_constants::match_continuous))
, match_partial_(0 != (flags & regex_constants::match_partial))
{
}
};
///////////////////////////////////////////////////////////////////////////////
// match_state
//
template<typename BidiIter>
struct match_state
: noncopyable
{
typedef BidiIter iterator;
typedef core_access<BidiIter> access;
typedef detail::match_context<BidiIter> match_context;
typedef detail::results_extras<BidiIter> results_extras;
typedef detail::regex_impl<BidiIter> regex_impl;
typedef detail::matchable<BidiIter> matchable;
typedef xpressive::match_results<BidiIter> match_results;
typedef detail::sub_match_impl<BidiIter> sub_match_impl;
typedef detail::actionable actionable;
BidiIter cur_;
sub_match_impl *sub_matches_;
std::size_t mark_count_;
BidiIter begin_;
BidiIter end_;
match_flags flags_;
bool found_partial_match_;
match_context context_;
results_extras *extras_;
actionable action_list_;
actionable const **action_list_tail_;
action_args_type *action_args_;
attr_context attr_context_;
BidiIter next_search_;
///////////////////////////////////////////////////////////////////////////////
//
match_state
(
BidiIter begin
, BidiIter end
, match_results &what
, regex_impl const &impl
, regex_constants::match_flag_type flags
)
: cur_(begin)
, sub_matches_(0)
, mark_count_(0)
, begin_(begin)
, end_(end)
, flags_(flags)
, found_partial_match_(false)
, context_() // zero-initializes the fields of context_
, extras_(&core_access<BidiIter>::get_extras(what))
, action_list_()
, action_list_tail_(&action_list_.next)
, action_args_(&core_access<BidiIter>::get_action_args(what))
, attr_context_() // zero-initializes the fields of attr_context_
, next_search_(begin)
{
// reclaim any cached memory in the match_results struct
this->extras_->sub_match_stack_.unwind();
// initialize the context_ struct
this->init_(impl, what);
// move all the nested match_results structs into the match_results cache
this->extras_->results_cache_.reclaim_all(access::get_nested_results(what));
}
///////////////////////////////////////////////////////////////////////////////
// reset
void reset(match_results &what, regex_impl const &impl)
{
this->extras_ = &core_access<BidiIter>::get_extras(what);
this->action_list_.next = 0;
this->action_list_tail_ = &action_list_.next;
this->action_args_ = &core_access<BidiIter>::get_action_args(what);
this->attr_context_ = attr_context();
this->context_.prev_context_ = 0;
this->found_partial_match_ = false;
this->extras_->sub_match_stack_.unwind();
this->init_(impl, what);
this->extras_->results_cache_.reclaim_all(access::get_nested_results(what));
}
///////////////////////////////////////////////////////////////////////////////
// push_context
// called to prepare the state object for a regex match
match_context push_context(regex_impl const &impl, matchable const &next, match_context &prev)
{
// save state
match_context context = this->context_;
// create a new nested match_results for this regex
nested_results<BidiIter> &nested = access::get_nested_results(*context.results_ptr_);
match_results &what = this->extras_->results_cache_.append_new(nested);
// (re)initialize the match context
this->init_(impl, what);
// create a linked list of match_context structs
this->context_.prev_context_ = &prev;
this->context_.next_ptr_ = &next;
// record the start of the zero-th sub-match
this->sub_matches_[0].begin_ = this->cur_;
return context;
}
///////////////////////////////////////////////////////////////////////////////
// pop_context
// called after a nested match failed to restore the context
bool pop_context(regex_impl const &impl, bool success)
{
match_context &context = *this->context_.prev_context_;
if(!success)
{
match_results &what = *context.results_ptr_;
this->uninit_(impl, what);
// send the match_results struct back to the cache
nested_results<BidiIter> &nested = access::get_nested_results(what);
this->extras_->results_cache_.reclaim_last(nested);
}
// restore the state
this->context_ = context;
match_results &results = *this->context_.results_ptr_;
this->sub_matches_ = access::get_sub_matches(access::get_sub_match_vector(results));
this->mark_count_ = results.size();
return success;
}
///////////////////////////////////////////////////////////////////////////////
// swap_context
void swap_context(match_context &context)
{
std::swap(this->context_, context);
match_results &results = *this->context_.results_ptr_;
this->sub_matches_ = access::get_sub_matches(access::get_sub_match_vector(results));
this->mark_count_ = results.size();
}
// beginning of buffer
bool bos() const
{
return this->cur_ == this->begin_;
}
// end of buffer
bool eos()
{
return this->cur_ == this->end_ && this->found_partial_match();
}
// is this the regex that is currently executing?
bool is_active_regex(regex_impl const &impl) const
{
return impl.xpr_.get() == this->context_.results_ptr_->regex_id();
}
// fetch the n-th sub_match
sub_match_impl &sub_match(int n)
{
return this->sub_matches_[n];
}
// called when a partial match has succeeded
void set_partial_match()
{
sub_match_impl &sub0 = this->sub_match(0);
sub0.first = sub0.begin_;
sub0.second = this->end_;
sub0.matched = false;
}
template<typename Traits>
Traits const &get_traits() const
{
return static_cast<traits_holder<Traits> const *>(this->context_.traits_)->traits();
}
private:
void init_(regex_impl const &impl, match_results &what)
{
regex_id_type const id = impl.xpr_.get();
std::size_t const total_mark_count = impl.mark_count_ + impl.hidden_mark_count_ + 1;
// initialize the context and the sub_match vector
this->context_.results_ptr_ = &what;
this->context_.traits_ = impl.traits_.get();
this->mark_count_ = impl.mark_count_ + 1;
this->sub_matches_ = this->extras_->sub_match_stack_.push_sequence(total_mark_count, sub_match_impl(begin_), detail::fill);
this->sub_matches_ += impl.hidden_mark_count_;
// initialize the match_results struct
access::init_match_results(what, id, impl.traits_, this->sub_matches_, this->mark_count_, impl.named_marks_);
}
void uninit_(regex_impl const &impl, match_results &)
{
extras_->sub_match_stack_.unwind_to(this->sub_matches_ - impl.hidden_mark_count_);
}
bool found_partial_match()
{
this->found_partial_match_ = true;
return true;
}
};
///////////////////////////////////////////////////////////////////////////////
// memento
//
template<typename BidiIter>
struct memento
{
sub_match_impl<BidiIter> *old_sub_matches_;
std::size_t nested_results_count_;
actionable const *action_list_head_;
actionable const **action_list_tail_;
attr_context attr_context_;
};
///////////////////////////////////////////////////////////////////////////////
// save_sub_matches
//
template<typename BidiIter>
inline memento<BidiIter> save_sub_matches(match_state<BidiIter> &state)
{
memento<BidiIter> mem =
{
state.extras_->sub_match_stack_.push_sequence(state.mark_count_, sub_match_impl<BidiIter>(state.begin_))
, state.context_.results_ptr_->nested_results().size()
, state.action_list_.next
, state.action_list_tail_
, state.attr_context_
};
state.action_list_.next = 0;
state.action_list_tail_ = &state.action_list_.next;
std::copy(state.sub_matches_, state.sub_matches_ + state.mark_count_, mem.old_sub_matches_);
return mem;
}
///////////////////////////////////////////////////////////////////////////////
// restore_action_queue
//
template<typename BidiIter>
inline void restore_action_queue(memento<BidiIter> const &mem, match_state<BidiIter> &state)
{
state.action_list_.next = mem.action_list_head_;
state.action_list_tail_ = mem.action_list_tail_;
*state.action_list_tail_ = 0;
}
///////////////////////////////////////////////////////////////////////////////
// restore_sub_matches
//
template<typename BidiIter>
inline void restore_sub_matches(memento<BidiIter> const &mem, match_state<BidiIter> &state)
{
typedef core_access<BidiIter> access;
nested_results<BidiIter> &nested = access::get_nested_results(*state.context_.results_ptr_);
std::size_t count = nested.size() - mem.nested_results_count_;
state.extras_->results_cache_.reclaim_last_n(nested, count);
std::copy(mem.old_sub_matches_, mem.old_sub_matches_ + state.mark_count_, state.sub_matches_);
state.extras_->sub_match_stack_.unwind_to(mem.old_sub_matches_);
state.attr_context_ = mem.attr_context_;
}
///////////////////////////////////////////////////////////////////////////////
// reclaim_sub_matches
//
template<typename BidiIter>
inline void reclaim_sub_matches(memento<BidiIter> const &mem, match_state<BidiIter> &state, bool success)
{
std::size_t count = state.context_.results_ptr_->nested_results().size() - mem.nested_results_count_;
if(count == 0)
{
state.extras_->sub_match_stack_.unwind_to(mem.old_sub_matches_);
}
// else we have we must orphan this block of backrefs because we are using the stack
// space above it.
if(!success)
{
state.attr_context_ = mem.attr_context_;
}
}
///////////////////////////////////////////////////////////////////////////////
// traits_cast
//
template<typename Traits, typename BidiIter>
inline Traits const &traits_cast(match_state<BidiIter> const &state)
{
return state.template get_traits<Traits>();
}
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,47 @@
///////////////////////////////////////////////////////////////////////////////
// sub_match_impl.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_CORE_SUB_MATCH_IMPL_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_SUB_MATCH_IMPL_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/xpressive/sub_match.hpp>
namespace boost { namespace xpressive { namespace detail
{
// TODO: sub_match_impl is a POD IFF BidiIter is POD. Pool allocation
// of them can be made more efficient if they are. Or maybe all they
// need is trivial constructor/destructor. (???)
///////////////////////////////////////////////////////////////////////////////
// sub_match_impl
//
template<typename BidiIter>
struct sub_match_impl
: sub_match<BidiIter>
{
unsigned int repeat_count_;
BidiIter begin_;
bool zero_width_;
sub_match_impl(BidiIter const &begin)
: sub_match<BidiIter>(begin, begin)
, repeat_count_(0)
, begin_(begin)
, zero_width_(false)
{
}
};
}}} // namespace boost::xpressive::detail
#endif

View File

@@ -0,0 +1,171 @@
///////////////////////////////////////////////////////////////////////////////
// sub_match_vector.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_CORE_SUB_MATCH_VECTOR_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_SUB_MATCH_VECTOR_HPP_EAN_10_04_2005
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/noncopyable.hpp>
#include <boost/iterator_adaptors.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/sub_match_impl.hpp>
namespace boost { namespace xpressive { namespace detail
{
#if BOOST_ITERATOR_ADAPTORS_VERSION >= 0x0200
//////////////////////////////////////////////////////////////////////////
// sub_match_iterator
//
template<typename Value, typename MainIter>
struct sub_match_iterator
: iterator_adaptor
<
sub_match_iterator<Value, MainIter>
, MainIter
, Value
, std::random_access_iterator_tag
>
{
typedef iterator_adaptor
<
sub_match_iterator<Value, MainIter>
, MainIter
, Value
, std::random_access_iterator_tag
> base_t;
sub_match_iterator(MainIter baseiter)
: base_t(baseiter)
{
}
};
#endif
//////////////////////////////////////////////////////////////////////////
// sub_match_vector
//
template<typename BidiIter>
struct sub_match_vector
: private noncopyable
{
private:
struct dummy { int i_; };
typedef int dummy::*bool_type;
public:
typedef sub_match<BidiIter> value_type;
typedef std::size_t size_type;
typedef value_type const &const_reference;
typedef const_reference reference;
typedef typename iterator_difference<BidiIter>::type difference_type;
typedef typename iterator_value<BidiIter>::type char_type;
typedef typename sub_match<BidiIter>::string_type string_type;
#if BOOST_ITERATOR_ADAPTORS_VERSION >= 0x0200
typedef sub_match_iterator
<
value_type const
, sub_match_impl<BidiIter> const *
> const_iterator;
#else
typedef iterator_adaptor
<
sub_match_impl<BidiIter> const *
, default_iterator_policies
, value_type
, value_type const &
, value_type const *
> const_iterator;
#endif // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
typedef const_iterator iterator;
sub_match_vector()
: size_(0)
, sub_matches_(0)
{
}
const_reference operator [](size_type index) const
{
static value_type const s_null;
return (index >= this->size_)
? s_null
: *static_cast<value_type const *>(&this->sub_matches_[ index ]);
}
size_type size() const
{
return this->size_;
}
bool empty() const
{
return 0 == this->size();
}
const_iterator begin() const
{
return const_iterator(this->sub_matches_);
}
const_iterator end() const
{
return const_iterator(this->sub_matches_ + this->size_);
}
operator bool_type() const
{
return (!this->empty() && (*this)[0].matched) ? &dummy::i_ : 0;
}
bool operator !() const
{
return this->empty() || !(*this)[0].matched;
}
void swap(sub_match_vector<BidiIter> &that)
{
std::swap(this->size_, that.size_);
std::swap(this->sub_matches_, that.sub_matches_);
}
private:
friend struct detail::core_access<BidiIter>;
void init_(sub_match_impl<BidiIter> *sub_matches, size_type size)
{
this->size_ = size;
this->sub_matches_ = sub_matches;
}
void init_(sub_match_impl<BidiIter> *sub_matches, size_type size, sub_match_vector<BidiIter> const &that)
{
BOOST_ASSERT(size == that.size_);
this->size_ = size;
this->sub_matches_ = sub_matches;
std::copy(that.sub_matches_, that.sub_matches_ + that.size_, this->sub_matches_);
}
size_type size_;
sub_match_impl<BidiIter> *sub_matches_;
};
}}} // namespace boost::xpressive::detail
#endif