123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- /*=============================================================================
- Copyright (c) 1998-2003 Joel de Guzman
- Copyright (c) 2002 Raghavendra Satish
- Copyright (c) 2002 Jeff Westfahl
- http://spirit.sourceforge.net/
- Distributed under the Boost Software License, Version 1.0. (See accompanying
- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- =============================================================================*/
- #if !defined(BOOST_SPIRIT_LOOPS_HPP)
- #define BOOST_SPIRIT_LOOPS_HPP
- ///////////////////////////////////////////////////////////////////////////////
- #include <boost/spirit/home/classic/namespace.hpp>
- #include <boost/spirit/home/classic/core/parser.hpp>
- #include <boost/spirit/home/classic/core/composite/composite.hpp>
- #include <boost/mpl/if.hpp>
- #include <boost/type_traits/is_same.hpp>
- ///////////////////////////////////////////////////////////////////////////////
- namespace boost { namespace spirit {
- BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
- ///////////////////////////////////////////////////////////////////////////
- //
- // fixed_loop class
- //
- // This class takes care of the construct:
- //
- // repeat_p (exact) [p]
- //
- // where 'p' is a parser and 'exact' is the number of times to
- // repeat. The parser iterates over the input exactly 'exact' times.
- // The parse function fails if the parser does not match the input
- // exactly 'exact' times.
- //
- // This class is parametizable and can accept constant arguments
- // (e.g. repeat_p (5) [p]) as well as references to variables (e.g.
- // repeat_p (ref (n)) [p]).
- //
- ///////////////////////////////////////////////////////////////////////////
- template <typename ParserT, typename ExactT>
- class fixed_loop
- : public unary<ParserT, parser <fixed_loop <ParserT, ExactT> > >
- {
- public:
- typedef fixed_loop<ParserT, ExactT> self_t;
- typedef unary<ParserT, parser<self_t> > base_t;
- fixed_loop (ParserT const & subject_, ExactT const & exact)
- : base_t(subject_), m_exact(exact) {}
- template <typename ScannerT>
- typename parser_result <self_t, ScannerT>::type
- parse (ScannerT const & scan) const
- {
- typedef typename parser_result<self_t, ScannerT>::type result_t;
- result_t hit = scan.empty_match();
- std::size_t n = m_exact;
- for (std::size_t i = 0; i < n; ++i)
- {
- if (result_t next = this->subject().parse(scan))
- {
- scan.concat_match(hit, next);
- }
- else
- {
- return scan.no_match();
- }
- }
- return hit;
- }
- template <typename ScannerT>
- struct result
- {
- typedef typename match_result<ScannerT, nil_t>::type type;
- };
- private:
- ExactT m_exact;
- };
- ///////////////////////////////////////////////////////////////////////////////
- //
- // finite_loop class
- //
- // This class takes care of the construct:
- //
- // repeat_p (min, max) [p]
- //
- // where 'p' is a parser, 'min' and 'max' specifies the minimum and
- // maximum iterations over 'p'. The parser iterates over the input
- // at least 'min' times and at most 'max' times. The parse function
- // fails if the parser does not match the input at least 'min' times
- // and at most 'max' times.
- //
- // This class is parametizable and can accept constant arguments
- // (e.g. repeat_p (5, 10) [p]) as well as references to variables
- // (e.g. repeat_p (ref (n1), ref (n2)) [p]).
- //
- ///////////////////////////////////////////////////////////////////////////////
- template <typename ParserT, typename MinT, typename MaxT>
- class finite_loop
- : public unary<ParserT, parser<finite_loop<ParserT, MinT, MaxT> > >
- {
- public:
- typedef finite_loop <ParserT, MinT, MaxT> self_t;
- typedef unary<ParserT, parser<self_t> > base_t;
- finite_loop (ParserT const & subject_, MinT const & min, MaxT const & max)
- : base_t(subject_), m_min(min), m_max(max) {}
- template <typename ScannerT>
- typename parser_result <self_t, ScannerT>::type
- parse(ScannerT const & scan) const
- {
- BOOST_SPIRIT_ASSERT(m_min <= m_max);
- typedef typename parser_result<self_t, ScannerT>::type result_t;
- result_t hit = scan.empty_match();
- std::size_t n1 = m_min;
- std::size_t n2 = m_max;
- for (std::size_t i = 0; i < n2; ++i)
- {
- typename ScannerT::iterator_t save = scan.first;
- result_t next = this->subject().parse(scan);
-
- if (!next)
- {
- if (i >= n1)
- {
- scan.first = save;
- break;
- }
- else
- {
- return scan.no_match();
- }
- }
- scan.concat_match(hit, next);
- }
- return hit;
- }
- template <typename ScannerT>
- struct result
- {
- typedef typename match_result<ScannerT, nil_t>::type type;
- };
- private:
- MinT m_min;
- MaxT m_max;
- };
- ///////////////////////////////////////////////////////////////////////////////
- //
- // infinite_loop class
- //
- // This class takes care of the construct:
- //
- // repeat_p (min, more) [p]
- //
- // where 'p' is a parser, 'min' is the minimum iteration over 'p'
- // and more specifies that the iteration should proceed
- // indefinitely. The parser iterates over the input at least 'min'
- // times and continues indefinitely until 'p' fails or all of the
- // input is parsed. The parse function fails if the parser does not
- // match the input at least 'min' times.
- //
- // This class is parametizable and can accept constant arguments
- // (e.g. repeat_p (5, more) [p]) as well as references to variables
- // (e.g. repeat_p (ref (n), more) [p]).
- //
- ///////////////////////////////////////////////////////////////////////////////
- struct more_t {};
- more_t const more = more_t ();
- template <typename ParserT, typename MinT>
- class infinite_loop
- : public unary<ParserT, parser<infinite_loop<ParserT, MinT> > >
- {
- public:
- typedef infinite_loop <ParserT, MinT> self_t;
- typedef unary<ParserT, parser<self_t> > base_t;
- infinite_loop (
- ParserT const& subject_,
- MinT const& min,
- more_t const&
- )
- : base_t(subject_), m_min(min) {}
- template <typename ScannerT>
- typename parser_result <self_t, ScannerT>::type
- parse(ScannerT const & scan) const
- {
- typedef typename parser_result<self_t, ScannerT>::type result_t;
- result_t hit = scan.empty_match();
- std::size_t n = m_min;
- for (std::size_t i = 0; ; ++i)
- {
- typename ScannerT::iterator_t save = scan.first;
- result_t next = this->subject().parse(scan);
- if (!next)
- {
- if (i >= n)
- {
- scan.first = save;
- break;
- }
- else
- {
- return scan.no_match();
- }
- }
- scan.concat_match(hit, next);
- }
- return hit;
- }
- template <typename ScannerT>
- struct result
- {
- typedef typename match_result<ScannerT, nil_t>::type type;
- };
- private:
- MinT m_min;
- };
- template <typename ExactT>
- struct fixed_loop_gen
- {
- fixed_loop_gen (ExactT const & exact)
- : m_exact (exact) {}
- template <typename ParserT>
- fixed_loop <ParserT, ExactT>
- operator[](parser <ParserT> const & subject_) const
- {
- return fixed_loop <ParserT, ExactT> (subject_.derived (), m_exact);
- }
- ExactT m_exact;
- };
- namespace impl {
- template <typename ParserT, typename MinT, typename MaxT>
- struct loop_traits
- {
- typedef typename mpl::if_<
- boost::is_same<MaxT, more_t>,
- infinite_loop<ParserT, MinT>,
- finite_loop<ParserT, MinT, MaxT>
- >::type type;
- };
- } // namespace impl
- template <typename MinT, typename MaxT>
- struct nonfixed_loop_gen
- {
- nonfixed_loop_gen (MinT min, MaxT max)
- : m_min (min), m_max (max) {}
- template <typename ParserT>
- typename impl::loop_traits<ParserT, MinT, MaxT>::type
- operator[](parser <ParserT> const & subject_) const
- {
- typedef typename impl::loop_traits<ParserT, MinT, MaxT>::type ret_t;
- return ret_t(
- subject_.derived(),
- m_min,
- m_max);
- }
- MinT m_min;
- MaxT m_max;
- };
- template <typename ExactT>
- fixed_loop_gen <ExactT>
- repeat_p(ExactT const & exact)
- {
- return fixed_loop_gen <ExactT> (exact);
- }
- template <typename MinT, typename MaxT>
- nonfixed_loop_gen <MinT, MaxT>
- repeat_p(MinT const & min, MaxT const & max)
- {
- return nonfixed_loop_gen <MinT, MaxT> (min, max);
- }
- BOOST_SPIRIT_CLASSIC_NAMESPACE_END
- }} // namespace BOOST_SPIRIT_CLASSIC_NS
- #endif // #if !defined(BOOST_SPIRIT_LOOPS_HPP)
|