| /*============================================================================= |
| 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> |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| 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) |