source: NonGTP/Boost/boost/spirit/utility/loops.hpp @ 857

Revision 857, 9.8 KB checked in by igarcia, 18 years ago (diff)
Line 
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///////////////////////////////////////////////////////////////////////////////
19namespace 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)
Note: See TracBrowser for help on using the repository browser.