]> git.lyx.org Git - features.git/blob - boost/boost/spirit/utility/loops.hpp
update to boost 1.34
[features.git] / boost / boost / spirit / utility / loops.hpp
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
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
13
14 ///////////////////////////////////////////////////////////////////////////////
15 #include <boost/spirit/core/parser.hpp>
16 #include <boost/spirit/core/composite/composite.hpp>
17
18 ///////////////////////////////////////////////////////////////////////////////
19 namespace boost { namespace spirit {
20
21     ///////////////////////////////////////////////////////////////////////////
22     //
23     //  fixed_loop class
24     //
25     //      This class takes care of the construct:
26     //
27     //          repeat_p (exact) [p]
28     //
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.
33     //
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]).
37     //
38     ///////////////////////////////////////////////////////////////////////////
39     template <typename ParserT, typename ExactT>
40     class fixed_loop
41     : public unary<ParserT, parser <fixed_loop <ParserT, ExactT> > >
42     {
43     public:
44
45         typedef fixed_loop<ParserT, ExactT>     self_t;
46         typedef unary<ParserT, parser<self_t> >  base_t;
47
48         fixed_loop (ParserT const & subject, ExactT const & exact)
49         : base_t(subject), m_exact(exact) {}
50
51         template <typename ScannerT>
52         typename parser_result <self_t, ScannerT>::type
53         parse (ScannerT const & scan) const
54         {
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;
58
59             for (std::size_t i = 0; i < n; ++i)
60             {
61                 if (result_t next = this->subject().parse(scan))
62                 {
63                     scan.concat_match(hit, next);
64                 }
65                 else
66                 {
67                     return scan.no_match();
68                 }
69             }
70
71             return hit;
72         }
73
74         template <typename ScannerT>
75         struct result
76         {
77             typedef typename match_result<ScannerT, nil_t>::type type;
78         };
79
80     private:
81
82         ExactT m_exact;
83     };
84
85     ///////////////////////////////////////////////////////////////////////////////
86     //
87     //  finite_loop class
88     //
89     //      This class takes care of the construct:
90     //
91     //          repeat_p (min, max) [p]
92     //
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.
98     //
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]).
102     //
103     ///////////////////////////////////////////////////////////////////////////////
104     template <typename ParserT, typename MinT, typename MaxT>
105     class finite_loop
106     : public unary<ParserT, parser<finite_loop<ParserT, MinT, MaxT> > >
107     {
108     public:
109
110         typedef finite_loop <ParserT, MinT, MaxT> self_t;
111         typedef unary<ParserT, parser<self_t> >   base_t;
112
113         finite_loop (ParserT const & subject, MinT const & min, MaxT const & max)
114         : base_t(subject), m_min(min), m_max(max) {}
115
116         template <typename ScannerT>
117         typename parser_result <self_t, ScannerT>::type
118         parse(ScannerT const & scan) const
119         {
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();
123
124             std::size_t n1 = m_min;
125             std::size_t n2 = m_max;
126
127             for (std::size_t i = 0; i < n2; ++i)
128             {
129                 typename ScannerT::iterator_t save = scan.first;
130                 result_t next = this->subject().parse(scan);
131  
132                 if (!next)
133                 {
134                     if (i >= n1)
135                     {
136                         scan.first = save;
137                         break;
138                     }
139                     else
140                     {
141                         return scan.no_match();
142                     }
143                 }
144
145                 scan.concat_match(hit, next);
146             }
147
148             return hit;
149         }
150
151         template <typename ScannerT>
152         struct result
153         {
154             typedef typename match_result<ScannerT, nil_t>::type type;
155         };
156
157     private:
158
159         MinT    m_min;
160         MaxT    m_max;
161     };
162
163     ///////////////////////////////////////////////////////////////////////////////
164     //
165     //  infinite_loop class
166     //
167     //      This class takes care of the construct:
168     //
169     //          repeat_p (min, more) [p]
170     //
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.
177     //
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]).
181     //
182     ///////////////////////////////////////////////////////////////////////////////
183
184     struct more_t {};
185     more_t const more = more_t ();
186
187     template <typename ParserT, typename MinT>
188     class infinite_loop
189      : public unary<ParserT, parser<infinite_loop<ParserT, MinT> > >
190     {
191     public:
192
193         typedef infinite_loop <ParserT, MinT>   self_t;
194         typedef unary<ParserT, parser<self_t> > base_t;
195
196         infinite_loop (
197             ParserT const& subject,
198             MinT const& min,
199             more_t const&
200         )
201         : base_t(subject), m_min(min) {}
202
203         template <typename ScannerT>
204         typename parser_result <self_t, ScannerT>::type
205         parse(ScannerT const & scan) const
206         {
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;
210
211             for (std::size_t i = 0; ; ++i)
212             {
213                 typename ScannerT::iterator_t save = scan.first;
214                 result_t next = this->subject().parse(scan);
215
216                 if (!next)
217                 {
218                     if (i >= n)
219                     {
220                         scan.first = save;
221                         break;
222                     }
223                     else
224                     {
225                         return scan.no_match();
226                     }
227                 }
228
229                 scan.concat_match(hit, next);
230             }
231
232             return hit;
233         }
234
235         template <typename ScannerT>
236         struct result
237         {
238             typedef typename match_result<ScannerT, nil_t>::type type;
239         };
240
241         private:
242
243         MinT m_min;
244     };
245
246     template <typename ExactT>
247     struct fixed_loop_gen
248     {
249         fixed_loop_gen (ExactT const & exact)
250         : m_exact (exact) {}
251
252         template <typename ParserT>
253         fixed_loop <ParserT, ExactT>
254         operator[](parser <ParserT> const & subject) const
255         {
256             return fixed_loop <ParserT, ExactT> (subject.derived (), m_exact);
257         }
258
259         ExactT m_exact;
260     };
261
262     namespace impl {
263
264         template <typename ParserT, typename MinT, typename MaxT>
265         struct loop_traits
266         {
267             typedef typename mpl::if_<
268                 boost::is_same<MaxT, more_t>,
269                 infinite_loop<ParserT, MinT>,
270                 finite_loop<ParserT, MinT, MaxT>
271             >::type type;
272         };
273
274     } // namespace impl
275
276     template <typename MinT, typename MaxT>
277     struct nonfixed_loop_gen
278     {
279        nonfixed_loop_gen (MinT min, MaxT max)
280         : m_min (min), m_max (max) {}
281
282        template <typename ParserT>
283        typename impl::loop_traits<ParserT, MinT, MaxT>::type
284        operator[](parser <ParserT> const & subject) const
285        {
286            typedef typename impl::loop_traits<ParserT, MinT, MaxT>::type ret_t;
287            return ret_t(
288                 subject.derived(),
289                 m_min,
290                 m_max);
291        }
292
293        MinT m_min;
294        MaxT m_max;
295     };
296
297     template <typename ExactT>
298     fixed_loop_gen <ExactT>
299     repeat_p(ExactT const & exact)
300     {
301         return fixed_loop_gen <ExactT> (exact);
302     }
303
304     template <typename MinT, typename MaxT>
305     nonfixed_loop_gen <MinT, MaxT>
306     repeat_p(MinT const & min, MaxT const & max)
307     {
308         return nonfixed_loop_gen <MinT, MaxT> (min, max);
309     }
310
311 }} // namespace boost::spirit
312
313 #endif // #if !defined(BOOST_SPIRIT_LOOPS_HPP)