PageRenderTime 32ms CodeModel.GetById 10ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 1ms

/Src/Dependencies/Boost/boost/spirit/home/classic/utility/loops.hpp

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