/////////////////////////////////////////////////////////////////////////////// // linker.hpp // // Copyright 2004 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 #ifndef BOOST_NO_STD_LOCALE # include #endif #include #include #include #include #include #include #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_ < is_same , 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 { 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 &) const { return typename apply::type(this->loc_); } Locale getloc() const { return this->loc_; } private: Locale loc_; }; /////////////////////////////////////////////////////////////////////////////// // xpression_linker // template struct xpression_linker { template explicit xpression_linker(Traits const &traits) : back_stack_() , traits_(&traits) , traits_type_(&typeid(Traits)) { } template void link(Matcher const &, xpression_base const *) { // no-op } void link(repeat_begin_matcher const &, xpression_base const *next) { this->back_stack_.push(next); } template void link(repeat_end_matcher const &matcher, xpression_base const *) { matcher.back_ = this->back_stack_.top(); this->back_stack_.pop(); } template void link(alternate_matcher const &matcher, xpression_base const *next) { xpression_peeker peeker(&matcher.bset_, this->get_traits()); this->alt_link(matcher.alternates_, next, peeker); } void link(alternate_end_matcher const &matcher, xpression_base const *) { matcher.back_ = this->back_stack_.top(); this->back_stack_.pop(); } template void link(keeper_matcher const &matcher, xpression_base const *) { get_pointer(matcher.xpr_)->link(*this); } template void link(lookahead_matcher const &matcher, xpression_base const *) { get_pointer(matcher.xpr_)->link(*this); } template void link(lookbehind_matcher const &matcher, xpression_base const *) { get_pointer(matcher.xpr_)->link(*this); } template void link(simple_repeat_matcher const &matcher, xpression_base const *) { matcher.xpr_.link(*this); } // for use by alt_link_pred below template void alt_branch_link(Xpr const &xpr, xpression_base const *next, xpression_peeker &peeker) { this->back_stack_.push(next); get_pointer(xpr)->link(*this); get_pointer(xpr)->peek(peeker); } private: /////////////////////////////////////////////////////////////////////////////// // alt_link_pred // struct alt_link_pred { xpression_linker &linker_; xpression_peeker &peeker_; xpression_base const *next_; alt_link_pred ( xpression_linker &linker , xpression_peeker &peeker , xpression_base 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_); } private: alt_link_pred &operator =(alt_link_pred const &); }; template void alt_link ( std::vector const> > const &alternates , xpression_base 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 , xpression_base const *next , xpression_peeker &peeker ) { fusion::for_each(alternates.cast(), alt_link_pred(*this, peeker, next)); } 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_; }; }}} // namespace boost::xpressive::detail #endif