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