static.hpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // static.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_STATIC_STATIC_HPP_EAN_10_04_2005
  8. #define BOOST_XPRESSIVE_DETAIL_STATIC_STATIC_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/mpl/assert.hpp>
  14. #include <boost/xpressive/detail/detail_fwd.hpp>
  15. #include <boost/xpressive/detail/core/state.hpp>
  16. #include <boost/xpressive/detail/core/linker.hpp>
  17. #include <boost/xpressive/detail/core/peeker.hpp>
  18. #include <boost/xpressive/detail/static/placeholders.hpp>
  19. #include <boost/xpressive/detail/utility/width.hpp>
  20. // Random thoughts:
  21. // - must support indirect repeat counts {$n,$m}
  22. // - add ws to eat whitespace (make *ws illegal)
  23. // - a{n,m} -> repeat<n,m>(a)
  24. // - a{$n,$m} -> repeat(n,m)(a)
  25. // - add nil to match nothing
  26. // - instead of s1, s2, etc., how about s[1], s[2], etc.? Needlessly verbose?
  27. namespace boost { namespace xpressive { namespace detail
  28. {
  29. ///////////////////////////////////////////////////////////////////////////////
  30. // stacked_xpression
  31. //
  32. template<typename Top, typename Next>
  33. struct stacked_xpression
  34. : Next
  35. {
  36. // match
  37. // delegates to Next
  38. template<typename BidiIter>
  39. bool match(match_state<BidiIter> &state) const
  40. {
  41. return static_cast<Next const *>(this)->
  42. BOOST_NESTED_TEMPLATE push_match<Top>(state);
  43. }
  44. // top_match
  45. // jump back to the xpression on top of the xpression stack,
  46. // and keep the xpression on the stack.
  47. template<typename BidiIter>
  48. static bool top_match(match_state<BidiIter> &state, void const *top)
  49. {
  50. return static_cast<Top const *>(top)->
  51. BOOST_NESTED_TEMPLATE push_match<Top>(state);
  52. }
  53. // pop_match
  54. // jump back to the xpression on top of the xpression stack,
  55. // pop the xpression off the stack.
  56. template<typename BidiIter>
  57. static bool pop_match(match_state<BidiIter> &state, void const *top)
  58. {
  59. return static_cast<Top const *>(top)->match(state);
  60. }
  61. // skip_match
  62. // pop the xpression off the top of the stack and ignore it; call
  63. // match on next.
  64. template<typename BidiIter>
  65. bool skip_match(match_state<BidiIter> &state) const
  66. {
  67. // could be static_xpression::skip_impl or stacked_xpression::skip_impl
  68. // depending on if there is 1 or more than 1 xpression on the
  69. // xpression stack
  70. return Top::skip_impl(*static_cast<Next const *>(this), state);
  71. }
  72. //protected:
  73. // skip_impl
  74. // implementation of skip_match.
  75. template<typename That, typename BidiIter>
  76. static bool skip_impl(That const &that, match_state<BidiIter> &state)
  77. {
  78. return that.BOOST_NESTED_TEMPLATE push_match<Top>(state);
  79. }
  80. };
  81. ///////////////////////////////////////////////////////////////////////////////
  82. // stacked_xpression_cast
  83. //
  84. template<typename Top, typename Next>
  85. inline stacked_xpression<Top, Next> const &stacked_xpression_cast(Next const &next)
  86. {
  87. // NOTE: this is a little white lie. The "next" object doesn't really have
  88. // the type to which we're casting it. It is harmless, though. We are only using
  89. // the cast to decorate the next object with type information. It is done
  90. // this way to save stack space.
  91. BOOST_MPL_ASSERT_RELATION(sizeof(stacked_xpression<Top, Next>), ==, sizeof(Next));
  92. return *static_cast<stacked_xpression<Top, Next> const *>(&next);
  93. }
  94. ///////////////////////////////////////////////////////////////////////////////
  95. // static_xpression
  96. //
  97. template<typename Matcher, typename Next>
  98. struct static_xpression
  99. : Matcher
  100. {
  101. Next next_;
  102. BOOST_STATIC_CONSTANT(bool, pure = Matcher::pure && Next::pure);
  103. BOOST_STATIC_CONSTANT(
  104. std::size_t
  105. , width =
  106. Matcher::width != unknown_width::value && Next::width != unknown_width::value
  107. ? Matcher::width + Next::width
  108. : unknown_width::value
  109. );
  110. static_xpression(Matcher const &matcher = Matcher(), Next const &next = Next())
  111. : Matcher(matcher)
  112. , next_(next)
  113. {
  114. }
  115. // match
  116. // delegates to the Matcher
  117. template<typename BidiIter>
  118. bool match(match_state<BidiIter> &state) const
  119. {
  120. return this->Matcher::match(state, this->next_);
  121. }
  122. // push_match
  123. // call match on this, but also push "Top" onto the xpression
  124. // stack so we know what we are jumping back to later.
  125. template<typename Top, typename BidiIter>
  126. bool push_match(match_state<BidiIter> &state) const
  127. {
  128. return this->Matcher::match(state, stacked_xpression_cast<Top>(this->next_));
  129. }
  130. // skip_impl
  131. // implementation of skip_match, called from stacked_xpression::skip_match
  132. template<typename That, typename BidiIter>
  133. static bool skip_impl(That const &that, match_state<BidiIter> &state)
  134. {
  135. return that.match(state);
  136. }
  137. // for linking a compiled regular xpression
  138. template<typename Char>
  139. void link(xpression_linker<Char> &linker) const
  140. {
  141. linker.accept(*static_cast<Matcher const *>(this), &this->next_);
  142. this->next_.link(linker);
  143. }
  144. // for building a lead-follow
  145. template<typename Char>
  146. void peek(xpression_peeker<Char> &peeker) const
  147. {
  148. this->peek_next_(peeker.accept(*static_cast<Matcher const *>(this)), peeker);
  149. }
  150. // for getting xpression width
  151. detail::width get_width() const
  152. {
  153. return this->get_width_(mpl::size_t<width>());
  154. }
  155. private:
  156. static_xpression &operator =(static_xpression const &);
  157. template<typename Char>
  158. void peek_next_(mpl::true_, xpression_peeker<Char> &peeker) const
  159. {
  160. this->next_.peek(peeker);
  161. }
  162. template<typename Char>
  163. void peek_next_(mpl::false_, xpression_peeker<Char> &) const
  164. {
  165. // no-op
  166. }
  167. template<std::size_t Width>
  168. detail::width get_width_(mpl::size_t<Width>) const
  169. {
  170. return Width;
  171. }
  172. detail::width get_width_(unknown_width) const
  173. {
  174. // Should only be called in contexts where the width is
  175. // known to be fixed.
  176. return this->Matcher::get_width() + this->next_.get_width();
  177. }
  178. };
  179. ///////////////////////////////////////////////////////////////////////////////
  180. // make_static
  181. //
  182. template<typename Matcher>
  183. inline static_xpression<Matcher> const
  184. make_static(Matcher const &matcher)
  185. {
  186. return static_xpression<Matcher>(matcher);
  187. }
  188. template<typename Matcher, typename Next>
  189. inline static_xpression<Matcher, Next> const
  190. make_static(Matcher const &matcher, Next const &next)
  191. {
  192. return static_xpression<Matcher, Next>(matcher, next);
  193. }
  194. ///////////////////////////////////////////////////////////////////////////////
  195. // no_next
  196. //
  197. struct no_next
  198. {
  199. BOOST_STATIC_CONSTANT(std::size_t, width = 0);
  200. BOOST_STATIC_CONSTANT(bool, pure = true);
  201. template<typename Char>
  202. void link(xpression_linker<Char> &) const
  203. {
  204. }
  205. template<typename Char>
  206. void peek(xpression_peeker<Char> &peeker) const
  207. {
  208. peeker.fail();
  209. }
  210. detail::width get_width() const
  211. {
  212. return 0;
  213. }
  214. };
  215. ///////////////////////////////////////////////////////////////////////////////
  216. // get_mark_number
  217. //
  218. inline int get_mark_number(basic_mark_tag const &mark)
  219. {
  220. return proto::value(mark).mark_number_;
  221. }
  222. }}} // namespace boost::xpressive::detail
  223. #endif