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/
7 Distributed under the Boost Software License, Version 1.0. (See accompanying
8 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 =============================================================================*/
10 #if !defined(BOOST_SPIRIT_LOOPS_HPP)
11 #define BOOST_SPIRIT_LOOPS_HPP
13 ///////////////////////////////////////////////////////////////////////////////
14 #include <boost/spirit/home/classic/namespace.hpp>
15 #include <boost/spirit/home/classic/core/parser.hpp>
16 #include <boost/spirit/home/classic/core/composite/composite.hpp>
17 #include <boost/mpl/if.hpp>
18 #include <boost/type_traits/is_same.hpp>
20 ///////////////////////////////////////////////////////////////////////////////
21 namespace boost { namespace spirit {
23 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
25 ///////////////////////////////////////////////////////////////////////////
29 // This class takes care of the construct:
31 // repeat_p (exact) [p]
33 // where 'p' is a parser and 'exact' is the number of times to
34 // repeat. The parser iterates over the input exactly 'exact' times.
35 // The parse function fails if the parser does not match the input
36 // exactly 'exact' times.
38 // This class is parametizable and can accept constant arguments
39 // (e.g. repeat_p (5) [p]) as well as references to variables (e.g.
40 // repeat_p (ref (n)) [p]).
42 ///////////////////////////////////////////////////////////////////////////
43 template <typename ParserT, typename ExactT>
45 : public unary<ParserT, parser <fixed_loop <ParserT, ExactT> > >
49 typedef fixed_loop<ParserT, ExactT> self_t;
50 typedef unary<ParserT, parser<self_t> > base_t;
52 fixed_loop (ParserT const & subject_, ExactT const & exact)
53 : base_t(subject_), m_exact(exact) {}
55 template <typename ScannerT>
56 typename parser_result <self_t, ScannerT>::type
57 parse (ScannerT const & scan) const
59 typedef typename parser_result<self_t, ScannerT>::type result_t;
60 result_t hit = scan.empty_match();
61 std::size_t n = m_exact;
63 for (std::size_t i = 0; i < n; ++i)
65 if (result_t next = this->subject().parse(scan))
67 scan.concat_match(hit, next);
71 return scan.no_match();
78 template <typename ScannerT>
81 typedef typename match_result<ScannerT, nil_t>::type type;
89 ///////////////////////////////////////////////////////////////////////////////
93 // This class takes care of the construct:
95 // repeat_p (min, max) [p]
97 // where 'p' is a parser, 'min' and 'max' specifies the minimum and
98 // maximum iterations over 'p'. The parser iterates over the input
99 // at least 'min' times and at most 'max' times. The parse function
100 // fails if the parser does not match the input at least 'min' times
101 // and at most 'max' times.
103 // This class is parametizable and can accept constant arguments
104 // (e.g. repeat_p (5, 10) [p]) as well as references to variables
105 // (e.g. repeat_p (ref (n1), ref (n2)) [p]).
107 ///////////////////////////////////////////////////////////////////////////////
108 template <typename ParserT, typename MinT, typename MaxT>
110 : public unary<ParserT, parser<finite_loop<ParserT, MinT, MaxT> > >
114 typedef finite_loop <ParserT, MinT, MaxT> self_t;
115 typedef unary<ParserT, parser<self_t> > base_t;
117 finite_loop (ParserT const & subject_, MinT const & min, MaxT const & max)
118 : base_t(subject_), m_min(min), m_max(max) {}
120 template <typename ScannerT>
121 typename parser_result <self_t, ScannerT>::type
122 parse(ScannerT const & scan) const
124 BOOST_SPIRIT_ASSERT(m_min <= m_max);
125 typedef typename parser_result<self_t, ScannerT>::type result_t;
126 result_t hit = scan.empty_match();
128 std::size_t n1 = m_min;
129 std::size_t n2 = m_max;
131 for (std::size_t i = 0; i < n2; ++i)
133 typename ScannerT::iterator_t save = scan.first;
134 result_t next = this->subject().parse(scan);
145 return scan.no_match();
149 scan.concat_match(hit, next);
155 template <typename ScannerT>
158 typedef typename match_result<ScannerT, nil_t>::type type;
167 ///////////////////////////////////////////////////////////////////////////////
169 // infinite_loop class
171 // This class takes care of the construct:
173 // repeat_p (min, more) [p]
175 // where 'p' is a parser, 'min' is the minimum iteration over 'p'
176 // and more specifies that the iteration should proceed
177 // indefinitely. The parser iterates over the input at least 'min'
178 // times and continues indefinitely until 'p' fails or all of the
179 // input is parsed. The parse function fails if the parser does not
180 // match the input at least 'min' times.
182 // This class is parametizable and can accept constant arguments
183 // (e.g. repeat_p (5, more) [p]) as well as references to variables
184 // (e.g. repeat_p (ref (n), more) [p]).
186 ///////////////////////////////////////////////////////////////////////////////
189 more_t const more = more_t ();
191 template <typename ParserT, typename MinT>
193 : public unary<ParserT, parser<infinite_loop<ParserT, MinT> > >
197 typedef infinite_loop <ParserT, MinT> self_t;
198 typedef unary<ParserT, parser<self_t> > base_t;
201 ParserT const& subject_,
205 : base_t(subject_), m_min(min) {}
207 template <typename ScannerT>
208 typename parser_result <self_t, ScannerT>::type
209 parse(ScannerT const & scan) const
211 typedef typename parser_result<self_t, ScannerT>::type result_t;
212 result_t hit = scan.empty_match();
213 std::size_t n = m_min;
215 for (std::size_t i = 0; ; ++i)
217 typename ScannerT::iterator_t save = scan.first;
218 result_t next = this->subject().parse(scan);
229 return scan.no_match();
233 scan.concat_match(hit, next);
239 template <typename ScannerT>
242 typedef typename match_result<ScannerT, nil_t>::type type;
250 template <typename ExactT>
251 struct fixed_loop_gen
253 fixed_loop_gen (ExactT const & exact)
256 template <typename ParserT>
257 fixed_loop <ParserT, ExactT>
258 operator[](parser <ParserT> const & subject_) const
260 return fixed_loop <ParserT, ExactT> (subject_.derived (), m_exact);
268 template <typename ParserT, typename MinT, typename MaxT>
271 typedef typename mpl::if_<
272 boost::is_same<MaxT, more_t>,
273 infinite_loop<ParserT, MinT>,
274 finite_loop<ParserT, MinT, MaxT>
280 template <typename MinT, typename MaxT>
281 struct nonfixed_loop_gen
283 nonfixed_loop_gen (MinT min, MaxT max)
284 : m_min (min), m_max (max) {}
286 template <typename ParserT>
287 typename impl::loop_traits<ParserT, MinT, MaxT>::type
288 operator[](parser <ParserT> const & subject_) const
290 typedef typename impl::loop_traits<ParserT, MinT, MaxT>::type ret_t;
301 template <typename ExactT>
302 fixed_loop_gen <ExactT>
303 repeat_p(ExactT const & exact)
305 return fixed_loop_gen <ExactT> (exact);
308 template <typename MinT, typename MaxT>
309 nonfixed_loop_gen <MinT, MaxT>
310 repeat_p(MinT const & min, MaxT const & max)
312 return nonfixed_loop_gen <MinT, MaxT> (min, max);
315 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
317 }} // namespace BOOST_SPIRIT_CLASSIC_NS
319 #endif // #if !defined(BOOST_SPIRIT_LOOPS_HPP)