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