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