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