loops.hpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /*=============================================================================
  2. Copyright (c) 1998-2003 Joel de Guzman
  3. Copyright (c) 2002 Raghavendra Satish
  4. Copyright (c) 2002 Jeff Westfahl
  5. http://spirit.sourceforge.net/
  6. Distributed under the Boost Software License, Version 1.0. (See accompanying
  7. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  8. =============================================================================*/
  9. #if !defined(BOOST_SPIRIT_LOOPS_HPP)
  10. #define BOOST_SPIRIT_LOOPS_HPP
  11. ///////////////////////////////////////////////////////////////////////////////
  12. #include <boost/spirit/home/classic/namespace.hpp>
  13. #include <boost/spirit/home/classic/core/parser.hpp>
  14. #include <boost/spirit/home/classic/core/composite/composite.hpp>
  15. #include <boost/mpl/if.hpp>
  16. #include <boost/type_traits/is_same.hpp>
  17. ///////////////////////////////////////////////////////////////////////////////
  18. namespace boost { namespace spirit {
  19. BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
  20. ///////////////////////////////////////////////////////////////////////////
  21. //
  22. // fixed_loop class
  23. //
  24. // This class takes care of the construct:
  25. //
  26. // repeat_p (exact) [p]
  27. //
  28. // where 'p' is a parser and 'exact' is the number of times to
  29. // repeat. The parser iterates over the input exactly 'exact' times.
  30. // The parse function fails if the parser does not match the input
  31. // exactly 'exact' times.
  32. //
  33. // This class is parametizable and can accept constant arguments
  34. // (e.g. repeat_p (5) [p]) as well as references to variables (e.g.
  35. // repeat_p (ref (n)) [p]).
  36. //
  37. ///////////////////////////////////////////////////////////////////////////
  38. template <typename ParserT, typename ExactT>
  39. class fixed_loop
  40. : public unary<ParserT, parser <fixed_loop <ParserT, ExactT> > >
  41. {
  42. public:
  43. typedef fixed_loop<ParserT, ExactT> self_t;
  44. typedef unary<ParserT, parser<self_t> > base_t;
  45. fixed_loop (ParserT const & subject_, ExactT const & exact)
  46. : base_t(subject_), m_exact(exact) {}
  47. template <typename ScannerT>
  48. typename parser_result <self_t, ScannerT>::type
  49. parse (ScannerT const & scan) const
  50. {
  51. typedef typename parser_result<self_t, ScannerT>::type result_t;
  52. result_t hit = scan.empty_match();
  53. std::size_t n = m_exact;
  54. for (std::size_t i = 0; i < n; ++i)
  55. {
  56. if (result_t next = this->subject().parse(scan))
  57. {
  58. scan.concat_match(hit, next);
  59. }
  60. else
  61. {
  62. return scan.no_match();
  63. }
  64. }
  65. return hit;
  66. }
  67. template <typename ScannerT>
  68. struct result
  69. {
  70. typedef typename match_result<ScannerT, nil_t>::type type;
  71. };
  72. private:
  73. ExactT m_exact;
  74. };
  75. ///////////////////////////////////////////////////////////////////////////////
  76. //
  77. // finite_loop class
  78. //
  79. // This class takes care of the construct:
  80. //
  81. // repeat_p (min, max) [p]
  82. //
  83. // where 'p' is a parser, 'min' and 'max' specifies the minimum and
  84. // maximum iterations over 'p'. The parser iterates over the input
  85. // at least 'min' times and at most 'max' times. The parse function
  86. // fails if the parser does not match the input at least 'min' times
  87. // and at most 'max' times.
  88. //
  89. // This class is parametizable and can accept constant arguments
  90. // (e.g. repeat_p (5, 10) [p]) as well as references to variables
  91. // (e.g. repeat_p (ref (n1), ref (n2)) [p]).
  92. //
  93. ///////////////////////////////////////////////////////////////////////////////
  94. template <typename ParserT, typename MinT, typename MaxT>
  95. class finite_loop
  96. : public unary<ParserT, parser<finite_loop<ParserT, MinT, MaxT> > >
  97. {
  98. public:
  99. typedef finite_loop <ParserT, MinT, MaxT> self_t;
  100. typedef unary<ParserT, parser<self_t> > base_t;
  101. finite_loop (ParserT const & subject_, MinT const & min, MaxT const & max)
  102. : base_t(subject_), m_min(min), m_max(max) {}
  103. template <typename ScannerT>
  104. typename parser_result <self_t, ScannerT>::type
  105. parse(ScannerT const & scan) const
  106. {
  107. BOOST_SPIRIT_ASSERT(m_min <= m_max);
  108. typedef typename parser_result<self_t, ScannerT>::type result_t;
  109. result_t hit = scan.empty_match();
  110. std::size_t n1 = m_min;
  111. std::size_t n2 = m_max;
  112. for (std::size_t i = 0; i < n2; ++i)
  113. {
  114. typename ScannerT::iterator_t save = scan.first;
  115. result_t next = this->subject().parse(scan);
  116. if (!next)
  117. {
  118. if (i >= n1)
  119. {
  120. scan.first = save;
  121. break;
  122. }
  123. else
  124. {
  125. return scan.no_match();
  126. }
  127. }
  128. scan.concat_match(hit, next);
  129. }
  130. return hit;
  131. }
  132. template <typename ScannerT>
  133. struct result
  134. {
  135. typedef typename match_result<ScannerT, nil_t>::type type;
  136. };
  137. private:
  138. MinT m_min;
  139. MaxT m_max;
  140. };
  141. ///////////////////////////////////////////////////////////////////////////////
  142. //
  143. // infinite_loop class
  144. //
  145. // This class takes care of the construct:
  146. //
  147. // repeat_p (min, more) [p]
  148. //
  149. // where 'p' is a parser, 'min' is the minimum iteration over 'p'
  150. // and more specifies that the iteration should proceed
  151. // indefinitely. The parser iterates over the input at least 'min'
  152. // times and continues indefinitely until 'p' fails or all of the
  153. // input is parsed. The parse function fails if the parser does not
  154. // match the input at least 'min' times.
  155. //
  156. // This class is parametizable and can accept constant arguments
  157. // (e.g. repeat_p (5, more) [p]) as well as references to variables
  158. // (e.g. repeat_p (ref (n), more) [p]).
  159. //
  160. ///////////////////////////////////////////////////////////////////////////////
  161. struct more_t {};
  162. more_t const more = more_t ();
  163. template <typename ParserT, typename MinT>
  164. class infinite_loop
  165. : public unary<ParserT, parser<infinite_loop<ParserT, MinT> > >
  166. {
  167. public:
  168. typedef infinite_loop <ParserT, MinT> self_t;
  169. typedef unary<ParserT, parser<self_t> > base_t;
  170. infinite_loop (
  171. ParserT const& subject_,
  172. MinT const& min,
  173. more_t const&
  174. )
  175. : base_t(subject_), m_min(min) {}
  176. template <typename ScannerT>
  177. typename parser_result <self_t, ScannerT>::type
  178. parse(ScannerT const & scan) const
  179. {
  180. typedef typename parser_result<self_t, ScannerT>::type result_t;
  181. result_t hit = scan.empty_match();
  182. std::size_t n = m_min;
  183. for (std::size_t i = 0; ; ++i)
  184. {
  185. typename ScannerT::iterator_t save = scan.first;
  186. result_t next = this->subject().parse(scan);
  187. if (!next)
  188. {
  189. if (i >= n)
  190. {
  191. scan.first = save;
  192. break;
  193. }
  194. else
  195. {
  196. return scan.no_match();
  197. }
  198. }
  199. scan.concat_match(hit, next);
  200. }
  201. return hit;
  202. }
  203. template <typename ScannerT>
  204. struct result
  205. {
  206. typedef typename match_result<ScannerT, nil_t>::type type;
  207. };
  208. private:
  209. MinT m_min;
  210. };
  211. template <typename ExactT>
  212. struct fixed_loop_gen
  213. {
  214. fixed_loop_gen (ExactT const & exact)
  215. : m_exact (exact) {}
  216. template <typename ParserT>
  217. fixed_loop <ParserT, ExactT>
  218. operator[](parser <ParserT> const & subject_) const
  219. {
  220. return fixed_loop <ParserT, ExactT> (subject_.derived (), m_exact);
  221. }
  222. ExactT m_exact;
  223. };
  224. namespace impl {
  225. template <typename ParserT, typename MinT, typename MaxT>
  226. struct loop_traits
  227. {
  228. typedef typename mpl::if_<
  229. boost::is_same<MaxT, more_t>,
  230. infinite_loop<ParserT, MinT>,
  231. finite_loop<ParserT, MinT, MaxT>
  232. >::type type;
  233. };
  234. } // namespace impl
  235. template <typename MinT, typename MaxT>
  236. struct nonfixed_loop_gen
  237. {
  238. nonfixed_loop_gen (MinT min, MaxT max)
  239. : m_min (min), m_max (max) {}
  240. template <typename ParserT>
  241. typename impl::loop_traits<ParserT, MinT, MaxT>::type
  242. operator[](parser <ParserT> const & subject_) const
  243. {
  244. typedef typename impl::loop_traits<ParserT, MinT, MaxT>::type ret_t;
  245. return ret_t(
  246. subject_.derived(),
  247. m_min,
  248. m_max);
  249. }
  250. MinT m_min;
  251. MaxT m_max;
  252. };
  253. template <typename ExactT>
  254. fixed_loop_gen <ExactT>
  255. repeat_p(ExactT const & exact)
  256. {
  257. return fixed_loop_gen <ExactT> (exact);
  258. }
  259. template <typename MinT, typename MaxT>
  260. nonfixed_loop_gen <MinT, MaxT>
  261. repeat_p(MinT const & min, MaxT const & max)
  262. {
  263. return nonfixed_loop_gen <MinT, MaxT> (min, max);
  264. }
  265. BOOST_SPIRIT_CLASSIC_NAMESPACE_END
  266. }} // namespace BOOST_SPIRIT_CLASSIC_NS
  267. #endif // #if !defined(BOOST_SPIRIT_LOOPS_HPP)