/Src/Dependencies/Boost/boost/spirit/home/classic/utility/loops.hpp

http://hadesmem.googlecode.com/ · C++ Header · 317 lines · 198 code · 51 blank · 68 comment · 8 complexity · 7981acd8abb23af7749c701c138276fb MD5 · raw file

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