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