Update contrib.
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 Use, modification and distribution is subject to the Boost Software
8 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9 http://www.boost.org/LICENSE_1_0.txt)
10 =============================================================================*/
11 #if !defined(BOOST_SPIRIT_LOOPS_HPP)
12 #define BOOST_SPIRIT_LOOPS_HPP
14 ///////////////////////////////////////////////////////////////////////////////
15 #include <boost/spirit/core/parser.hpp>
16 #include <boost/spirit/core/composite/composite.hpp>
18 ///////////////////////////////////////////////////////////////////////////////
19 namespace boost { namespace spirit {
21 ///////////////////////////////////////////////////////////////////////////
25 // This class takes care of the construct:
27 // repeat_p (exact) [p]
29 // where 'p' is a parser and 'exact' is the number of times to
30 // repeat. The parser iterates over the input exactly 'exact' times.
31 // The parse function fails if the parser does not match the input
32 // exactly 'exact' times.
34 // This class is parametizable and can accept constant arguments
35 // (e.g. repeat_p (5) [p]) as well as references to variables (e.g.
36 // repeat_p (ref (n)) [p]).
38 ///////////////////////////////////////////////////////////////////////////
39 template <typename ParserT, typename ExactT>
41 : public unary<ParserT, parser <fixed_loop <ParserT, ExactT> > >
45 typedef fixed_loop<ParserT, ExactT> self_t;
46 typedef unary<ParserT, parser<self_t> > base_t;
48 fixed_loop (ParserT const & subject, ExactT const & exact)
49 : base_t(subject), m_exact(exact) {}
51 template <typename ScannerT>
52 typename parser_result <self_t, ScannerT>::type
53 parse (ScannerT const & scan) const
55 typedef typename parser_result<self_t, ScannerT>::type result_t;
56 result_t hit = scan.empty_match();
57 std::size_t n = m_exact;
59 for (std::size_t i = 0; i < n; ++i)
61 if (result_t next = this->subject().parse(scan))
63 scan.concat_match(hit, next);
67 return scan.no_match();
74 template <typename ScannerT>
77 typedef typename match_result<ScannerT, nil_t>::type type;
85 ///////////////////////////////////////////////////////////////////////////////
89 // This class takes care of the construct:
91 // repeat_p (min, max) [p]
93 // where 'p' is a parser, 'min' and 'max' specifies the minimum and
94 // maximum iterations over 'p'. The parser iterates over the input
95 // at least 'min' times and at most 'max' times. The parse function
96 // fails if the parser does not match the input at least 'min' times
97 // and at most 'max' times.
99 // This class is parametizable and can accept constant arguments
100 // (e.g. repeat_p (5, 10) [p]) as well as references to variables
101 // (e.g. repeat_p (ref (n1), ref (n2)) [p]).
103 ///////////////////////////////////////////////////////////////////////////////
104 template <typename ParserT, typename MinT, typename MaxT>
106 : public unary<ParserT, parser<finite_loop<ParserT, MinT, MaxT> > >
110 typedef finite_loop <ParserT, MinT, MaxT> self_t;
111 typedef unary<ParserT, parser<self_t> > base_t;
113 finite_loop (ParserT const & subject, MinT const & min, MaxT const & max)
114 : base_t(subject), m_min(min), m_max(max) {}
116 template <typename ScannerT>
117 typename parser_result <self_t, ScannerT>::type
118 parse(ScannerT const & scan) const
120 BOOST_SPIRIT_ASSERT(m_min <= m_max);
121 typedef typename parser_result<self_t, ScannerT>::type result_t;
122 result_t hit = scan.empty_match();
124 std::size_t n1 = m_min;
125 std::size_t n2 = m_max;
127 for (std::size_t i = 0; i < n2; ++i)
129 typename ScannerT::iterator_t save = scan.first;
130 result_t next = this->subject().parse(scan);
141 return scan.no_match();
145 scan.concat_match(hit, next);
151 template <typename ScannerT>
154 typedef typename match_result<ScannerT, nil_t>::type type;
163 ///////////////////////////////////////////////////////////////////////////////
165 // infinite_loop class
167 // This class takes care of the construct:
169 // repeat_p (min, more) [p]
171 // where 'p' is a parser, 'min' is the minimum iteration over 'p'
172 // and more specifies that the iteration should proceed
173 // indefinitely. The parser iterates over the input at least 'min'
174 // times and continues indefinitely until 'p' fails or all of the
175 // input is parsed. The parse function fails if the parser does not
176 // match the input at least 'min' times.
178 // This class is parametizable and can accept constant arguments
179 // (e.g. repeat_p (5, more) [p]) as well as references to variables
180 // (e.g. repeat_p (ref (n), more) [p]).
182 ///////////////////////////////////////////////////////////////////////////////
185 more_t const more = more_t ();
187 template <typename ParserT, typename MinT>
189 : public unary<ParserT, parser<infinite_loop<ParserT, MinT> > >
193 typedef infinite_loop <ParserT, MinT> self_t;
194 typedef unary<ParserT, parser<self_t> > base_t;
197 ParserT const& subject,
201 : base_t(subject), m_min(min) {}
203 template <typename ScannerT>
204 typename parser_result <self_t, ScannerT>::type
205 parse(ScannerT const & scan) const
207 typedef typename parser_result<self_t, ScannerT>::type result_t;
208 result_t hit = scan.empty_match();
209 std::size_t n = m_min;
211 for (std::size_t i = 0; ; ++i)
213 typename ScannerT::iterator_t save = scan.first;
214 result_t next = this->subject().parse(scan);
225 return scan.no_match();
229 scan.concat_match(hit, next);
235 template <typename ScannerT>
238 typedef typename match_result<ScannerT, nil_t>::type type;
246 template <typename ExactT>
247 struct fixed_loop_gen
249 fixed_loop_gen (ExactT const & exact)
252 template <typename ParserT>
253 fixed_loop <ParserT, ExactT>
254 operator[](parser <ParserT> const & subject) const
256 return fixed_loop <ParserT, ExactT> (subject.derived (), m_exact);
264 template <typename ParserT, typename MinT, typename MaxT>
267 typedef typename mpl::if_<
268 boost::is_same<MaxT, more_t>,
269 infinite_loop<ParserT, MinT>,
270 finite_loop<ParserT, MinT, MaxT>
276 template <typename MinT, typename MaxT>
277 struct nonfixed_loop_gen
279 nonfixed_loop_gen (MinT min, MaxT max)
280 : m_min (min), m_max (max) {}
282 template <typename ParserT>
283 typename impl::loop_traits<ParserT, MinT, MaxT>::type
284 operator[](parser <ParserT> const & subject) const
286 typedef typename impl::loop_traits<ParserT, MinT, MaxT>::type ret_t;
297 template <typename ExactT>
298 fixed_loop_gen <ExactT>
299 repeat_p(ExactT const & exact)
301 return fixed_loop_gen <ExactT> (exact);
304 template <typename MinT, typename MaxT>
305 nonfixed_loop_gen <MinT, MaxT>
306 repeat_p(MinT const & min, MaxT const & max)
308 return nonfixed_loop_gen <MinT, MaxT> (min, max);
311 }} // namespace boost::spirit
313 #endif // #if !defined(BOOST_SPIRIT_LOOPS_HPP)