/////////////////////////////////////////////////////////////////////////////// // 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) # pragma once #endif #include #ifndef BOOST_NO_STD_LOCALE # include #endif #include #include #include #include #include #include #if BOOST_VERSION >= 103500 # include #else # include #endif #include #include #include #include #include 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 struct apply {}; template struct apply > { typedef xpression_visitor type; }; template static typename apply::type call(Visitor &visitor) { return typename apply::type(visitor.traits(), visitor.self()); } }; /////////////////////////////////////////////////////////////////////////////// // regex_traits_type : wrap a locale in the appropriate regex_traits // template struct regex_traits_type { #ifndef BOOST_NO_STD_LOCALE typedef typename iterator_value::type char_type; // if Locale is std::locale, wrap it in a cpp_regex_traits typedef typename mpl::if_c < is_same::value , cpp_regex_traits , 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 struct locale_modifier { typedef Locale locale_type; locale_modifier(Locale const &loc) : loc_(loc) { } template struct apply {}; template struct apply > { typedef typename regex_traits_type::type traits_type; typedef xpression_visitor type; }; template typename apply::type call(Visitor &visitor) const { return typename apply::type(this->loc_, visitor.self()); } Locale getloc() const { return this->loc_; } private: Locale loc_; }; /////////////////////////////////////////////////////////////////////////////// // xpression_linker // template struct xpression_linker { template explicit xpression_linker(Traits const &tr) : back_stack_() , traits_(&tr) , traits_type_(&typeid(Traits)) , has_backrefs_(false) { } template void accept(Matcher const &, void const *) { // no-op } template void accept(mark_matcher const &, void const *) { this->has_backrefs_ = true; } template void accept(action_matcher const &, void const *) { this->has_backrefs_ = true; } template void accept(predicate_matcher const &, void const *) { this->has_backrefs_ = true; } void accept(repeat_begin_matcher const &, void const *next) { this->back_stack_.push(next); } template void accept(repeat_end_matcher const &matcher, void const *) { matcher.back_ = this->back_stack_.top(); this->back_stack_.pop(); } template void accept(alternate_matcher const &matcher, void const *next) { xpression_peeker peeker(matcher.bset_, this->get_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 void accept(optional_matcher const &matcher, void const *next) { this->back_stack_.push(next); matcher.xpr_.link(*this); } template void accept(optional_mark_matcher const &matcher, void const *next) { this->back_stack_.push(next); matcher.xpr_.link(*this); } template void accept(keeper_matcher const &matcher, void const *) { matcher.xpr_.link(*this); } template void accept(lookahead_matcher const &matcher, void const *) { matcher.xpr_.link(*this); } template void accept(lookbehind_matcher const &matcher, void const *) { matcher.xpr_.link(*this); } template void accept(simple_repeat_matcher 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 void alt_branch_link(Xpr const &xpr, void const *next, xpression_peeker *peeker) { this->back_stack_.push(next); xpr.link(*this); xpr.peek(*peeker); } private: /////////////////////////////////////////////////////////////////////////////// // alt_link_pred // struct alt_link_pred { xpression_linker *linker_; xpression_peeker *peeker_; void const *next_; alt_link_pred ( xpression_linker *linker , xpression_peeker *peeker , void const *next ) : linker_(linker) , peeker_(peeker) , next_(next) { } template void operator ()(Xpr const &xpr) const { this->linker_->alt_branch_link(xpr, this->next_, this->peeker_); } }; template void alt_link ( alternates_vector const &alternates , void const *next , xpression_peeker *peeker ) { std::for_each(alternates.begin(), alternates.end(), alt_link_pred(this, peeker, next)); } template void alt_link ( fusion::sequence_base const &alternates , void const *next , xpression_peeker *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 Traits const &get_traits() const { BOOST_ASSERT(*this->traits_type_ == typeid(Traits)); return *static_cast(this->traits_); } std::stack back_stack_; void const *traits_; std::type_info const *traits_type_; bool has_backrefs_; }; }}} // namespace boost::xpressive::detail #endif