dynamic.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // dynamic.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_DYNAMIC_DYNAMIC_HPP_EAN_10_04_2005
  8. #define BOOST_XPRESSIVE_DETAIL_DYNAMIC_DYNAMIC_HPP_EAN_10_04_2005
  9. // MS compatible compilers support #pragma once
  10. #if defined(_MSC_VER)
  11. # pragma once
  12. #endif
  13. #include <vector>
  14. #include <utility>
  15. #include <algorithm>
  16. #include <boost/assert.hpp>
  17. #include <boost/mpl/int.hpp>
  18. #include <boost/mpl/assert.hpp>
  19. #include <boost/throw_exception.hpp>
  20. #include <boost/type_traits/is_same.hpp>
  21. #include <boost/xpressive/detail/detail_fwd.hpp>
  22. #include <boost/xpressive/detail/core/quant_style.hpp>
  23. #include <boost/xpressive/detail/dynamic/matchable.hpp>
  24. #include <boost/xpressive/detail/dynamic/sequence.hpp>
  25. #include <boost/xpressive/detail/core/icase.hpp>
  26. namespace boost { namespace xpressive { namespace detail
  27. {
  28. ///////////////////////////////////////////////////////////////////////////////
  29. // invalid_xpression
  30. template<typename BidiIter>
  31. struct invalid_xpression
  32. : matchable_ex<BidiIter>
  33. {
  34. invalid_xpression()
  35. : matchable_ex<BidiIter>()
  36. {
  37. intrusive_ptr_add_ref(this); // keep alive forever
  38. }
  39. bool match(match_state<BidiIter> &) const
  40. {
  41. BOOST_ASSERT(false);
  42. return false;
  43. }
  44. };
  45. ///////////////////////////////////////////////////////////////////////////////
  46. // get_invalid_xpression
  47. template<typename BidiIter>
  48. inline shared_matchable<BidiIter> const &get_invalid_xpression()
  49. {
  50. static invalid_xpression<BidiIter> const invalid_xpr;
  51. static intrusive_ptr<matchable_ex<BidiIter> const> const invalid_ptr(&invalid_xpr);
  52. static shared_matchable<BidiIter> const invalid_matchable(invalid_ptr);
  53. return invalid_matchable;
  54. }
  55. ///////////////////////////////////////////////////////////////////////////////
  56. // dynamic_xpression
  57. template<typename Matcher, typename BidiIter>
  58. struct dynamic_xpression
  59. : Matcher
  60. , matchable_ex<BidiIter>
  61. {
  62. typedef typename iterator_value<BidiIter>::type char_type;
  63. dynamic_xpression(Matcher const &matcher = Matcher())
  64. : Matcher(matcher)
  65. , next_(get_invalid_xpression<BidiIter>())
  66. {
  67. }
  68. virtual bool match(match_state<BidiIter> &state) const
  69. {
  70. return this->Matcher::match(state, *this->next_.matchable());
  71. }
  72. virtual void link(xpression_linker<char_type> &linker) const
  73. {
  74. linker.accept(*static_cast<Matcher const *>(this), this->next_.matchable().get());
  75. this->next_.link(linker);
  76. }
  77. virtual void peek(xpression_peeker<char_type> &peeker) const
  78. {
  79. this->peek_next_(peeker.accept(*static_cast<Matcher const *>(this)), peeker);
  80. }
  81. virtual void repeat(quant_spec const &spec, sequence<BidiIter> &seq) const
  82. {
  83. this->repeat_(spec, seq, quant_type<Matcher>(), is_same<Matcher, mark_begin_matcher>());
  84. }
  85. private:
  86. friend struct sequence<BidiIter>;
  87. void peek_next_(mpl::true_, xpression_peeker<char_type> &peeker) const
  88. {
  89. this->next_.peek(peeker);
  90. }
  91. void peek_next_(mpl::false_, xpression_peeker<char_type> &) const
  92. {
  93. // no-op
  94. }
  95. void repeat_(quant_spec const &spec, sequence<BidiIter> &seq, mpl::int_<quant_none>, mpl::false_) const
  96. {
  97. if(quant_none == seq.quant())
  98. {
  99. BOOST_THROW_EXCEPTION(
  100. regex_error(regex_constants::error_badrepeat, "expression cannot be quantified")
  101. );
  102. }
  103. else
  104. {
  105. this->repeat_(spec, seq, mpl::int_<quant_variable_width>(), mpl::false_());
  106. }
  107. }
  108. void repeat_(quant_spec const &spec, sequence<BidiIter> &seq, mpl::int_<quant_fixed_width>, mpl::false_) const
  109. {
  110. if(this->next_ == get_invalid_xpression<BidiIter>())
  111. {
  112. make_simple_repeat(spec, seq, matcher_wrapper<Matcher>(*this));
  113. }
  114. else
  115. {
  116. this->repeat_(spec, seq, mpl::int_<quant_variable_width>(), mpl::false_());
  117. }
  118. }
  119. void repeat_(quant_spec const &spec, sequence<BidiIter> &seq, mpl::int_<quant_variable_width>, mpl::false_) const
  120. {
  121. if(!is_unknown(seq.width()) && seq.pure())
  122. {
  123. make_simple_repeat(spec, seq);
  124. }
  125. else
  126. {
  127. make_repeat(spec, seq);
  128. }
  129. }
  130. void repeat_(quant_spec const &spec, sequence<BidiIter> &seq, mpl::int_<quant_fixed_width>, mpl::true_) const
  131. {
  132. make_repeat(spec, seq, this->mark_number_);
  133. }
  134. shared_matchable<BidiIter> next_;
  135. };
  136. ///////////////////////////////////////////////////////////////////////////////
  137. // make_dynamic
  138. template<typename BidiIter, typename Matcher>
  139. inline sequence<BidiIter> make_dynamic(Matcher const &matcher)
  140. {
  141. typedef dynamic_xpression<Matcher, BidiIter> xpression_type;
  142. intrusive_ptr<xpression_type> xpr(new xpression_type(matcher));
  143. return sequence<BidiIter>(xpr);
  144. }
  145. ///////////////////////////////////////////////////////////////////////////////
  146. // alternates_vector
  147. template<typename BidiIter>
  148. struct alternates_vector
  149. : std::vector<shared_matchable<BidiIter> >
  150. {
  151. BOOST_STATIC_CONSTANT(std::size_t, width = unknown_width::value);
  152. BOOST_STATIC_CONSTANT(bool, pure = false);
  153. };
  154. ///////////////////////////////////////////////////////////////////////////////
  155. // matcher_wrapper
  156. template<typename Matcher>
  157. struct matcher_wrapper
  158. : Matcher
  159. {
  160. matcher_wrapper(Matcher const &matcher = Matcher())
  161. : Matcher(matcher)
  162. {
  163. }
  164. template<typename BidiIter>
  165. bool match(match_state<BidiIter> &state) const
  166. {
  167. return this->Matcher::match(state, matcher_wrapper<true_matcher>());
  168. }
  169. template<typename Char>
  170. void link(xpression_linker<Char> &linker) const
  171. {
  172. linker.accept(*static_cast<Matcher const *>(this), 0);
  173. }
  174. template<typename Char>
  175. void peek(xpression_peeker<Char> &peeker) const
  176. {
  177. peeker.accept(*static_cast<Matcher const *>(this));
  178. }
  179. };
  180. //////////////////////////////////////////////////////////////////////////
  181. // make_simple_repeat
  182. template<typename BidiIter, typename Xpr>
  183. inline void
  184. make_simple_repeat(quant_spec const &spec, sequence<BidiIter> &seq, Xpr const &xpr)
  185. {
  186. if(spec.greedy_)
  187. {
  188. simple_repeat_matcher<Xpr, mpl::true_> quant(xpr, spec.min_, spec.max_, seq.width().value());
  189. seq = make_dynamic<BidiIter>(quant);
  190. }
  191. else
  192. {
  193. simple_repeat_matcher<Xpr, mpl::false_> quant(xpr, spec.min_, spec.max_, seq.width().value());
  194. seq = make_dynamic<BidiIter>(quant);
  195. }
  196. }
  197. //////////////////////////////////////////////////////////////////////////
  198. // make_simple_repeat
  199. template<typename BidiIter>
  200. inline void
  201. make_simple_repeat(quant_spec const &spec, sequence<BidiIter> &seq)
  202. {
  203. seq += make_dynamic<BidiIter>(true_matcher());
  204. make_simple_repeat(spec, seq, seq.xpr());
  205. }
  206. //////////////////////////////////////////////////////////////////////////
  207. // make_optional
  208. template<typename BidiIter>
  209. inline void
  210. make_optional(quant_spec const &spec, sequence<BidiIter> &seq)
  211. {
  212. typedef shared_matchable<BidiIter> xpr_type;
  213. seq += make_dynamic<BidiIter>(alternate_end_matcher());
  214. if(spec.greedy_)
  215. {
  216. optional_matcher<xpr_type, mpl::true_> opt(seq.xpr());
  217. seq = make_dynamic<BidiIter>(opt);
  218. }
  219. else
  220. {
  221. optional_matcher<xpr_type, mpl::false_> opt(seq.xpr());
  222. seq = make_dynamic<BidiIter>(opt);
  223. }
  224. }
  225. //////////////////////////////////////////////////////////////////////////
  226. // make_optional
  227. template<typename BidiIter>
  228. inline void
  229. make_optional(quant_spec const &spec, sequence<BidiIter> &seq, int mark_nbr)
  230. {
  231. typedef shared_matchable<BidiIter> xpr_type;
  232. seq += make_dynamic<BidiIter>(alternate_end_matcher());
  233. if(spec.greedy_)
  234. {
  235. optional_mark_matcher<xpr_type, mpl::true_> opt(seq.xpr(), mark_nbr);
  236. seq = make_dynamic<BidiIter>(opt);
  237. }
  238. else
  239. {
  240. optional_mark_matcher<xpr_type, mpl::false_> opt(seq.xpr(), mark_nbr);
  241. seq = make_dynamic<BidiIter>(opt);
  242. }
  243. }
  244. //////////////////////////////////////////////////////////////////////////
  245. // make_repeat
  246. template<typename BidiIter>
  247. inline void
  248. make_repeat(quant_spec const &spec, sequence<BidiIter> &seq)
  249. {
  250. // only bother creating a repeater if max is greater than one
  251. if(1 < spec.max_)
  252. {
  253. // create a hidden mark so this expression can be quantified
  254. int mark_nbr = -static_cast<int>(++*spec.hidden_mark_count_);
  255. seq = make_dynamic<BidiIter>(mark_begin_matcher(mark_nbr)) + seq
  256. + make_dynamic<BidiIter>(mark_end_matcher(mark_nbr));
  257. make_repeat(spec, seq, mark_nbr);
  258. return;
  259. }
  260. // if min is 0, the repeat must be made optional
  261. if(0 == spec.min_)
  262. {
  263. make_optional(spec, seq);
  264. }
  265. }
  266. //////////////////////////////////////////////////////////////////////////
  267. // make_repeat
  268. template<typename BidiIter>
  269. inline void
  270. make_repeat(quant_spec const &spec, sequence<BidiIter> &seq, int mark_nbr)
  271. {
  272. BOOST_ASSERT(spec.max_); // we should never get here if max is 0
  273. // only bother creating a repeater if max is greater than one
  274. if(1 < spec.max_)
  275. {
  276. // TODO: statically bind the repeat matchers to the mark matchers for better perf
  277. unsigned int min = spec.min_ ? spec.min_ : 1U;
  278. repeat_begin_matcher repeat_begin(mark_nbr);
  279. if(spec.greedy_)
  280. {
  281. repeat_end_matcher<mpl::true_> repeat_end(mark_nbr, min, spec.max_);
  282. seq = make_dynamic<BidiIter>(repeat_begin) + seq
  283. + make_dynamic<BidiIter>(repeat_end);
  284. }
  285. else
  286. {
  287. repeat_end_matcher<mpl::false_> repeat_end(mark_nbr, min, spec.max_);
  288. seq = make_dynamic<BidiIter>(repeat_begin) + seq
  289. + make_dynamic<BidiIter>(repeat_end);
  290. }
  291. }
  292. // if min is 0, the repeat must be made optional
  293. if(0 == spec.min_)
  294. {
  295. make_optional(spec, seq, mark_nbr);
  296. }
  297. }
  298. }}} // namespace boost::xpressive::detail
  299. #endif