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