/Src/Dependencies/Boost/boost/spirit/home/qi/directive/repeat.hpp

http://hadesmem.googlecode.com/ · C++ Header · 297 lines · 229 code · 44 blank · 24 comment · 5 complexity · 4c3bd0a96b11b5d8dcf8dde358e52fd7 MD5 · raw file

  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. private:
  81. // silence MSVC warning C4512: assignment operator could not be generated
  82. exact_iterator& operator= (exact_iterator const&);
  83. };
  84. template <typename T>
  85. struct finite_iterator // handles repeat(min, max)[p]
  86. {
  87. finite_iterator(T const min, T const max)
  88. : min BOOST_PREVENT_MACRO_SUBSTITUTION (min)
  89. , max BOOST_PREVENT_MACRO_SUBSTITUTION (max) {}
  90. typedef T type;
  91. T start() const { return 0; }
  92. bool got_max(T i) const { return i >= max; }
  93. bool got_min(T i) const { return i >= min; }
  94. T const min;
  95. T const max;
  96. private:
  97. // silence MSVC warning C4512: assignment operator could not be generated
  98. finite_iterator& operator= (finite_iterator const&);
  99. };
  100. template <typename T>
  101. struct infinite_iterator // handles repeat(min, inf)[p]
  102. {
  103. infinite_iterator(T const min)
  104. : min BOOST_PREVENT_MACRO_SUBSTITUTION (min) {}
  105. typedef T type;
  106. T start() const { return 0; }
  107. bool got_max(T /*i*/) const { return false; }
  108. bool got_min(T i) const { return i >= min; }
  109. T const min;
  110. private:
  111. // silence MSVC warning C4512: assignment operator could not be generated
  112. infinite_iterator& operator= (infinite_iterator const&);
  113. };
  114. template <typename Subject, typename LoopIter>
  115. struct repeat_parser : unary_parser<repeat_parser<Subject, LoopIter> >
  116. {
  117. typedef Subject subject_type;
  118. template <typename Context, typename Iterator>
  119. struct attribute
  120. {
  121. // Build a std::vector from the subject's attribute. Note
  122. // that build_std_vector may return unused_type if the
  123. // subject's attribute is an unused_type.
  124. typedef typename
  125. traits::build_std_vector<
  126. typename traits::attribute_of<
  127. Subject, Context, Iterator>::type
  128. >::type
  129. type;
  130. };
  131. repeat_parser(Subject const& subject, LoopIter const& iter)
  132. : subject(subject), iter(iter) {}
  133. template <typename F>
  134. bool parse_container(F f) const
  135. {
  136. typename LoopIter::type i = iter.start();
  137. for (/**/; !iter.got_min(i); ++i)
  138. {
  139. if (f (subject))
  140. return false;
  141. }
  142. // parse some more up to the maximum specified
  143. typename F::iterator_type save = f.f.first;
  144. for (/**/; !iter.got_max(i); ++i)
  145. {
  146. if (f (subject))
  147. break;
  148. save = f.f.first;
  149. }
  150. f.f.first = save;
  151. return true;
  152. }
  153. template <typename Iterator, typename Context
  154. , typename Skipper, typename Attribute>
  155. bool parse(Iterator& first, Iterator const& last
  156. , Context& context, Skipper const& skipper
  157. , Attribute& attr) const
  158. {
  159. typedef detail::fail_function<Iterator, Context, Skipper>
  160. fail_function;
  161. // ensure the attribute is actually a container type
  162. traits::make_container(attr);
  163. Iterator iter = first;
  164. fail_function f(iter, last, context, skipper);
  165. if (!parse_container(detail::make_pass_container(f, attr)))
  166. return false;
  167. first = f.first;
  168. return true;
  169. }
  170. template <typename Context>
  171. info what(Context& context) const
  172. {
  173. return info("repeat", subject.what(context));
  174. }
  175. Subject subject;
  176. LoopIter iter;
  177. private:
  178. // silence MSVC warning C4512: assignment operator could not be generated
  179. repeat_parser& operator= (repeat_parser const&);
  180. };
  181. ///////////////////////////////////////////////////////////////////////////
  182. // Parser generators: make_xxx function (objects)
  183. ///////////////////////////////////////////////////////////////////////////
  184. template <typename Subject, typename Modifiers>
  185. struct make_directive<tag::repeat, Subject, Modifiers>
  186. {
  187. typedef kleene<Subject> result_type;
  188. result_type operator()(unused_type, Subject const& subject, unused_type) const
  189. {
  190. return result_type(subject);
  191. }
  192. };
  193. template <typename T, typename Subject, typename Modifiers>
  194. struct make_directive<
  195. terminal_ex<tag::repeat, fusion::vector1<T> >, Subject, Modifiers>
  196. {
  197. typedef exact_iterator<T> iterator_type;
  198. typedef repeat_parser<Subject, iterator_type> result_type;
  199. template <typename Terminal>
  200. result_type operator()(
  201. Terminal const& term, Subject const& subject, unused_type) const
  202. {
  203. return result_type(subject, fusion::at_c<0>(term.args));
  204. }
  205. };
  206. template <typename T, typename Subject, typename Modifiers>
  207. struct make_directive<
  208. terminal_ex<tag::repeat, fusion::vector2<T, T> >, Subject, Modifiers>
  209. {
  210. typedef finite_iterator<T> iterator_type;
  211. typedef repeat_parser<Subject, iterator_type> result_type;
  212. template <typename Terminal>
  213. result_type operator()(
  214. Terminal const& term, Subject const& subject, unused_type) const
  215. {
  216. return result_type(subject,
  217. iterator_type(
  218. fusion::at_c<0>(term.args)
  219. , fusion::at_c<1>(term.args)
  220. )
  221. );
  222. }
  223. };
  224. template <typename T, typename Subject, typename Modifiers>
  225. struct make_directive<
  226. terminal_ex<tag::repeat
  227. , fusion::vector2<T, inf_type> >, Subject, Modifiers>
  228. {
  229. typedef infinite_iterator<T> iterator_type;
  230. typedef repeat_parser<Subject, iterator_type> result_type;
  231. template <typename Terminal>
  232. result_type operator()(
  233. Terminal const& term, Subject const& subject, unused_type) const
  234. {
  235. return result_type(subject, fusion::at_c<0>(term.args));
  236. }
  237. };
  238. }}}
  239. namespace boost { namespace spirit { namespace traits
  240. {
  241. ///////////////////////////////////////////////////////////////////////////
  242. template <typename Subject, typename LoopIter>
  243. struct has_semantic_action<qi::repeat_parser<Subject, LoopIter> >
  244. : unary_has_semantic_action<Subject> {};
  245. ///////////////////////////////////////////////////////////////////////////
  246. template <typename Subject, typename LoopIter, typename Attribute
  247. , typename Context, typename Iterator>
  248. struct handles_container<qi::repeat_parser<Subject, LoopIter>
  249. , Attribute, Context, Iterator>
  250. : mpl::true_ {};
  251. }}}
  252. #endif