linker.hpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // linker.hpp
  3. //
  4. // Copyright 2008 Eric Niebler. Distributed under the Boost
  5. // Software License, Version 1.0. (See accompanying file
  6. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_XPRESSIVE_DETAIL_CORE_LINKER_HPP_EAN_10_04_2005
  8. #define BOOST_XPRESSIVE_DETAIL_CORE_LINKER_HPP_EAN_10_04_2005
  9. // MS compatible compilers support #pragma once
  10. #if defined(_MSC_VER)
  11. # pragma once
  12. #endif
  13. #include <boost/config.hpp>
  14. #ifndef BOOST_NO_STD_LOCALE
  15. # include <locale>
  16. #endif
  17. #include <stack>
  18. #include <limits>
  19. #include <typeinfo>
  20. #include <boost/shared_ptr.hpp>
  21. #include <boost/type_traits/is_same.hpp>
  22. #include <boost/version.hpp>
  23. #if BOOST_VERSION >= 103500
  24. # include <boost/fusion/include/for_each.hpp>
  25. #else
  26. # include <boost/spirit/fusion/algorithm/for_each.hpp>
  27. #endif
  28. #include <boost/xpressive/detail/detail_fwd.hpp>
  29. #include <boost/xpressive/detail/dynamic/matchable.hpp>
  30. #include <boost/xpressive/detail/core/matchers.hpp>
  31. #include <boost/xpressive/detail/core/peeker.hpp>
  32. #include <boost/xpressive/detail/utility/never_true.hpp>
  33. namespace boost { namespace xpressive { namespace detail
  34. {
  35. ///////////////////////////////////////////////////////////////////////////////
  36. // icase_modifier
  37. //
  38. // wrapped by the modifier<> template and inserted into the xpression
  39. // template with the icase() helper function. icase_modifier morphs
  40. // a case-sensitive visitor into a case-insensitive visitor, which
  41. // causes all matchers visited to become case-insensitive.
  42. //
  43. struct icase_modifier
  44. {
  45. template<typename Visitor>
  46. struct apply {};
  47. template<typename BidiIter, typename ICase, typename Traits>
  48. struct apply<xpression_visitor<BidiIter, ICase, Traits> >
  49. {
  50. typedef xpression_visitor<BidiIter, mpl::true_, Traits> type;
  51. };
  52. template<typename Visitor>
  53. static typename apply<Visitor>::type
  54. call(Visitor &visitor)
  55. {
  56. return typename apply<Visitor>::type(visitor.traits(), visitor.self());
  57. }
  58. };
  59. ///////////////////////////////////////////////////////////////////////////////
  60. // regex_traits_type : wrap a locale in the appropriate regex_traits
  61. //
  62. template<typename Locale, typename BidiIter>
  63. struct regex_traits_type
  64. {
  65. #ifndef BOOST_NO_STD_LOCALE
  66. typedef typename iterator_value<BidiIter>::type char_type;
  67. // if Locale is std::locale, wrap it in a cpp_regex_traits<Char>
  68. typedef typename mpl::if_c
  69. <
  70. is_same<Locale, std::locale>::value
  71. , cpp_regex_traits<char_type>
  72. , Locale
  73. >::type type;
  74. #else
  75. typedef Locale type;
  76. #endif
  77. };
  78. ///////////////////////////////////////////////////////////////////////////////
  79. // locale_modifier
  80. //
  81. // wrapped by the modifier<> template and inserted into the xpression
  82. // template with the imbue() helper function. Causes a sub-xpression to
  83. // use the specified Locale
  84. //
  85. template<typename Locale>
  86. struct locale_modifier
  87. {
  88. typedef Locale locale_type;
  89. locale_modifier(Locale const &loc)
  90. : loc_(loc)
  91. {
  92. }
  93. template<typename Visitor>
  94. struct apply {};
  95. template<typename BidiIter, typename ICase, typename OtherTraits>
  96. struct apply<xpression_visitor<BidiIter, ICase, OtherTraits> >
  97. {
  98. typedef typename regex_traits_type<Locale, BidiIter>::type traits_type;
  99. typedef xpression_visitor<BidiIter, ICase, traits_type> type;
  100. };
  101. template<typename Visitor>
  102. typename apply<Visitor>::type
  103. call(Visitor &visitor) const
  104. {
  105. return typename apply<Visitor>::type(this->loc_, visitor.self());
  106. }
  107. Locale getloc() const
  108. {
  109. return this->loc_;
  110. }
  111. private:
  112. Locale loc_;
  113. };
  114. ///////////////////////////////////////////////////////////////////////////////
  115. // xpression_linker
  116. //
  117. template<typename Char>
  118. struct xpression_linker
  119. {
  120. template<typename Traits>
  121. explicit xpression_linker(Traits const &tr)
  122. : back_stack_()
  123. , traits_(&tr)
  124. , traits_type_(&typeid(Traits))
  125. , has_backrefs_(false)
  126. {
  127. }
  128. template<typename Matcher>
  129. void accept(Matcher const &, void const *)
  130. {
  131. // no-op
  132. }
  133. template<typename Traits, typename ICase>
  134. void accept(mark_matcher<Traits, ICase> const &, void const *)
  135. {
  136. this->has_backrefs_ = true;
  137. }
  138. template<typename Action>
  139. void accept(action_matcher<Action> const &, void const *)
  140. {
  141. this->has_backrefs_ = true;
  142. }
  143. template<typename Predicate>
  144. void accept(predicate_matcher<Predicate> const &, void const *)
  145. {
  146. this->has_backrefs_ = true;
  147. }
  148. void accept(repeat_begin_matcher const &, void const *next)
  149. {
  150. this->back_stack_.push(next);
  151. }
  152. template<typename Greedy>
  153. void accept(repeat_end_matcher<Greedy> const &matcher, void const *)
  154. {
  155. matcher.back_ = this->back_stack_.top();
  156. this->back_stack_.pop();
  157. }
  158. template<typename Alternates, typename Traits>
  159. void accept(alternate_matcher<Alternates, Traits> const &matcher, void const *next)
  160. {
  161. xpression_peeker<Char> peeker(matcher.bset_, this->get_traits<Traits>());
  162. this->alt_link(matcher.alternates_, next, &peeker);
  163. }
  164. void accept(alternate_end_matcher const &matcher, void const *)
  165. {
  166. matcher.back_ = this->back_stack_.top();
  167. this->back_stack_.pop();
  168. }
  169. template<typename Xpr, typename Greedy>
  170. void accept(optional_matcher<Xpr, Greedy> const &matcher, void const *next)
  171. {
  172. this->back_stack_.push(next);
  173. matcher.xpr_.link(*this);
  174. }
  175. template<typename Xpr, typename Greedy>
  176. void accept(optional_mark_matcher<Xpr, Greedy> const &matcher, void const *next)
  177. {
  178. this->back_stack_.push(next);
  179. matcher.xpr_.link(*this);
  180. }
  181. template<typename Xpr>
  182. void accept(keeper_matcher<Xpr> const &matcher, void const *)
  183. {
  184. matcher.xpr_.link(*this);
  185. }
  186. template<typename Xpr>
  187. void accept(lookahead_matcher<Xpr> const &matcher, void const *)
  188. {
  189. matcher.xpr_.link(*this);
  190. }
  191. template<typename Xpr>
  192. void accept(lookbehind_matcher<Xpr> const &matcher, void const *)
  193. {
  194. matcher.xpr_.link(*this);
  195. }
  196. template<typename Xpr, typename Greedy>
  197. void accept(simple_repeat_matcher<Xpr, Greedy> const &matcher, void const *)
  198. {
  199. matcher.xpr_.link(*this);
  200. }
  201. // accessors
  202. bool has_backrefs() const
  203. {
  204. return this->has_backrefs_;
  205. }
  206. // for use by alt_link_pred below
  207. template<typename Xpr>
  208. void alt_branch_link(Xpr const &xpr, void const *next, xpression_peeker<Char> *peeker)
  209. {
  210. this->back_stack_.push(next);
  211. xpr.link(*this);
  212. xpr.peek(*peeker);
  213. }
  214. private:
  215. ///////////////////////////////////////////////////////////////////////////////
  216. // alt_link_pred
  217. //
  218. struct alt_link_pred
  219. {
  220. xpression_linker<Char> *linker_;
  221. xpression_peeker<Char> *peeker_;
  222. void const *next_;
  223. alt_link_pred
  224. (
  225. xpression_linker<Char> *linker
  226. , xpression_peeker<Char> *peeker
  227. , void const *next
  228. )
  229. : linker_(linker)
  230. , peeker_(peeker)
  231. , next_(next)
  232. {
  233. }
  234. template<typename Xpr>
  235. void operator ()(Xpr const &xpr) const
  236. {
  237. this->linker_->alt_branch_link(xpr, this->next_, this->peeker_);
  238. }
  239. };
  240. template<typename BidiIter>
  241. void alt_link
  242. (
  243. alternates_vector<BidiIter> const &alternates
  244. , void const *next
  245. , xpression_peeker<Char> *peeker
  246. )
  247. {
  248. std::for_each(alternates.begin(), alternates.end(), alt_link_pred(this, peeker, next));
  249. }
  250. template<typename Alternates>
  251. void alt_link
  252. (
  253. fusion::sequence_base<Alternates> const &alternates
  254. , void const *next
  255. , xpression_peeker<Char> *peeker
  256. )
  257. {
  258. #if BOOST_VERSION >= 103500
  259. fusion::for_each(alternates.derived(), alt_link_pred(this, peeker, next));
  260. #else
  261. fusion::for_each(alternates.cast(), alt_link_pred(this, peeker, next));
  262. #endif
  263. }
  264. template<typename Traits>
  265. Traits const &get_traits() const
  266. {
  267. BOOST_ASSERT(*this->traits_type_ == typeid(Traits));
  268. return *static_cast<Traits const *>(this->traits_);
  269. }
  270. std::stack<void const *> back_stack_;
  271. void const *traits_;
  272. std::type_info const *traits_type_;
  273. bool has_backrefs_;
  274. };
  275. }}} // namespace boost::xpressive::detail
  276. #endif