repeat.hpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Copyright (c) 2001-2011 Hartmut Kaiser
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. =============================================================================*/
  7. #if !defined(SPIRIT_REPEAT_NOVEMBER_14_2008_1148AM)
  8. #define SPIRIT_REPEAT_NOVEMBER_14_2008_1148AM
  9. #if defined(_MSC_VER)
  10. #pragma once
  11. #endif
  12. #include <boost/spirit/home/qi/meta_compiler.hpp>
  13. #include <boost/spirit/home/qi/parser.hpp>
  14. #include <boost/spirit/home/qi/auxiliary/lazy.hpp>
  15. #include <boost/spirit/home/qi/operator/kleene.hpp>
  16. #include <boost/spirit/home/support/container.hpp>
  17. #include <boost/spirit/home/support/common_terminals.hpp>
  18. #include <boost/spirit/home/qi/detail/attributes.hpp>
  19. #include <boost/spirit/home/qi/detail/fail_function.hpp>
  20. #include <boost/spirit/home/qi/detail/pass_container.hpp>
  21. #include <boost/spirit/home/support/info.hpp>
  22. #include <boost/spirit/home/support/has_semantic_action.hpp>
  23. #include <boost/spirit/home/support/handles_container.hpp>
  24. #include <boost/fusion/include/at.hpp>
  25. #include <vector>
  26. namespace boost { namespace spirit
  27. {
  28. ///////////////////////////////////////////////////////////////////////////
  29. // Enablers
  30. ///////////////////////////////////////////////////////////////////////////
  31. template <>
  32. struct use_directive<qi::domain, tag::repeat> // enables repeat[p]
  33. : mpl::true_ {};
  34. template <typename T>
  35. struct use_directive<qi::domain
  36. , terminal_ex<tag::repeat // enables repeat(exact)[p]
  37. , fusion::vector1<T> >
  38. > : mpl::true_ {};
  39. template <typename T>
  40. struct use_directive<qi::domain
  41. , terminal_ex<tag::repeat // enables repeat(min, max)[p]
  42. , fusion::vector2<T, T> >
  43. > : mpl::true_ {};
  44. template <typename T>
  45. struct use_directive<qi::domain
  46. , terminal_ex<tag::repeat // enables repeat(min, inf)[p]
  47. , fusion::vector2<T, inf_type> >
  48. > : mpl::true_ {};
  49. template <> // enables *lazy* repeat(exact)[p]
  50. struct use_lazy_directive<
  51. qi::domain
  52. , tag::repeat
  53. , 1 // arity
  54. > : mpl::true_ {};
  55. template <> // enables *lazy* repeat(min, max)[p]
  56. struct use_lazy_directive< // and repeat(min, inf)[p]
  57. qi::domain
  58. , tag::repeat
  59. , 2 // arity
  60. > : mpl::true_ {};
  61. }}
  62. namespace boost { namespace spirit { namespace qi
  63. {
  64. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  65. using spirit::repeat;
  66. using spirit::inf;
  67. #endif
  68. using spirit::repeat_type;
  69. using spirit::inf_type;
  70. template <typename T>
  71. struct exact_iterator // handles repeat(exact)[p]
  72. {
  73. exact_iterator(T const exact_)
  74. : exact(exact_) {}
  75. typedef T type;
  76. T start() const { return 0; }
  77. bool got_max(T i) const { return i >= exact; }
  78. bool got_min(T i) const { return i >= exact; }
  79. T const exact;
  80. // silence MSVC warning C4512: assignment operator could not be generated
  81. BOOST_DELETED_FUNCTION(exact_iterator& operator= (exact_iterator const&))
  82. };
  83. template <typename T>
  84. struct finite_iterator // handles repeat(min, max)[p]
  85. {
  86. finite_iterator(T const min_, T const max_)
  87. : min BOOST_PREVENT_MACRO_SUBSTITUTION (min_)
  88. , max BOOST_PREVENT_MACRO_SUBSTITUTION (max_) {}
  89. typedef T type;
  90. T start() const { return 0; }
  91. bool got_max(T i) const { return i >= max; }
  92. bool got_min(T i) const { return i >= min; }
  93. T const min;
  94. T const max;
  95. // silence MSVC warning C4512: assignment operator could not be generated
  96. BOOST_DELETED_FUNCTION(finite_iterator& operator= (finite_iterator const&))
  97. };
  98. template <typename T>
  99. struct infinite_iterator // handles repeat(min, inf)[p]
  100. {
  101. infinite_iterator(T const min_)
  102. : min BOOST_PREVENT_MACRO_SUBSTITUTION (min_) {}
  103. typedef T type;
  104. T start() const { return 0; }
  105. bool got_max(T /*i*/) const { return false; }
  106. bool got_min(T i) const { return i >= min; }
  107. T const min;
  108. // silence MSVC warning C4512: assignment operator could not be generated
  109. BOOST_DELETED_FUNCTION(infinite_iterator& operator= (infinite_iterator const&))
  110. };
  111. template <typename Subject, typename LoopIter>
  112. struct repeat_parser : unary_parser<repeat_parser<Subject, LoopIter> >
  113. {
  114. typedef Subject subject_type;
  115. template <typename Context, typename Iterator>
  116. struct attribute
  117. {
  118. // Build a std::vector from the subject's attribute. Note
  119. // that build_std_vector may return unused_type if the
  120. // subject's attribute is an unused_type.
  121. typedef typename
  122. traits::build_std_vector<
  123. typename traits::attribute_of<
  124. Subject, Context, Iterator>::type
  125. >::type
  126. type;
  127. };
  128. repeat_parser(Subject const& subject_, LoopIter const& iter_)
  129. : subject(subject_), iter(iter_) {}
  130. template <typename F>
  131. bool parse_container(F f) const
  132. {
  133. typename LoopIter::type i = iter.start();
  134. for (/**/; !iter.got_min(i); ++i)
  135. {
  136. if (f (subject))
  137. return false;
  138. }
  139. // parse some more up to the maximum specified
  140. typename F::iterator_type save = f.f.first;
  141. for (/**/; !iter.got_max(i); ++i)
  142. {
  143. if (f (subject))
  144. break;
  145. save = f.f.first;
  146. }
  147. f.f.first = save;
  148. return true;
  149. }
  150. template <typename Iterator, typename Context
  151. , typename Skipper, typename Attribute>
  152. bool parse(Iterator& first, Iterator const& last
  153. , Context& context, Skipper const& skipper
  154. , Attribute& attr_) const
  155. {
  156. typedef detail::fail_function<Iterator, Context, Skipper>
  157. fail_function;
  158. // ensure the attribute is actually a container type
  159. traits::make_container(attr_);
  160. Iterator iter_local = first;
  161. fail_function f(iter_local, last, context, skipper);
  162. if (!parse_container(detail::make_pass_container(f, attr_)))
  163. return false;
  164. first = f.first;
  165. return true;
  166. }
  167. template <typename Context>
  168. info what(Context& context) const
  169. {
  170. return info("repeat", subject.what(context));
  171. }
  172. Subject subject;
  173. LoopIter iter;
  174. // silence MSVC warning C4512: assignment operator could not be generated
  175. BOOST_DELETED_FUNCTION(repeat_parser& operator= (repeat_parser const&))
  176. };
  177. ///////////////////////////////////////////////////////////////////////////
  178. // Parser generators: make_xxx function (objects)
  179. ///////////////////////////////////////////////////////////////////////////
  180. template <typename Subject, typename Modifiers>
  181. struct make_directive<tag::repeat, Subject, Modifiers>
  182. {
  183. typedef kleene<Subject> result_type;
  184. result_type operator()(unused_type, Subject const& subject, unused_type) const
  185. {
  186. return result_type(subject);
  187. }
  188. };
  189. template <typename T, typename Subject, typename Modifiers>
  190. struct make_directive<
  191. terminal_ex<tag::repeat, fusion::vector1<T> >, Subject, Modifiers>
  192. {
  193. typedef exact_iterator<T> iterator_type;
  194. typedef repeat_parser<Subject, iterator_type> result_type;
  195. template <typename Terminal>
  196. result_type operator()(
  197. Terminal const& term, Subject const& subject, unused_type) const
  198. {
  199. return result_type(subject, fusion::at_c<0>(term.args));
  200. }
  201. };
  202. template <typename T, typename Subject, typename Modifiers>
  203. struct make_directive<
  204. terminal_ex<tag::repeat, fusion::vector2<T, T> >, Subject, Modifiers>
  205. {
  206. typedef finite_iterator<T> iterator_type;
  207. typedef repeat_parser<Subject, iterator_type> result_type;
  208. template <typename Terminal>
  209. result_type operator()(
  210. Terminal const& term, Subject const& subject, unused_type) const
  211. {
  212. return result_type(subject,
  213. iterator_type(
  214. fusion::at_c<0>(term.args)
  215. , fusion::at_c<1>(term.args)
  216. )
  217. );
  218. }
  219. };
  220. template <typename T, typename Subject, typename Modifiers>
  221. struct make_directive<
  222. terminal_ex<tag::repeat
  223. , fusion::vector2<T, inf_type> >, Subject, Modifiers>
  224. {
  225. typedef infinite_iterator<T> iterator_type;
  226. typedef repeat_parser<Subject, iterator_type> result_type;
  227. template <typename Terminal>
  228. result_type operator()(
  229. Terminal const& term, Subject const& subject, unused_type) const
  230. {
  231. return result_type(subject, fusion::at_c<0>(term.args));
  232. }
  233. };
  234. }}}
  235. namespace boost { namespace spirit { namespace traits
  236. {
  237. ///////////////////////////////////////////////////////////////////////////
  238. template <typename Subject, typename LoopIter>
  239. struct has_semantic_action<qi::repeat_parser<Subject, LoopIter> >
  240. : unary_has_semantic_action<Subject> {};
  241. ///////////////////////////////////////////////////////////////////////////
  242. template <typename Subject, typename LoopIter, typename Attribute
  243. , typename Context, typename Iterator>
  244. struct handles_container<qi::repeat_parser<Subject, LoopIter>
  245. , Attribute, Context, Iterator>
  246. : mpl::true_ {};
  247. }}}
  248. #endif