/src/contrib/boost/spirit/home/qi/directive/repeat.hpp

http://pythonocc.googlecode.com/ · C++ Header · 327 lines · 254 code · 43 blank · 30 comment · 7 complexity · 5cf9f871db06d197ca7e113f6265e05f MD5 · raw file

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