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