os/ossrv/ossrv_pub/boost_apis/boost/spirit/utility/loops.hpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*=============================================================================
     2     Copyright (c) 1998-2003 Joel de Guzman
     3     Copyright (c) 2002 Raghavendra Satish
     4     Copyright (c) 2002 Jeff Westfahl
     5     http://spirit.sourceforge.net/
     6 
     7     Use, modification and distribution is subject to the Boost Software
     8     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
     9     http://www.boost.org/LICENSE_1_0.txt)
    10 =============================================================================*/
    11 #if !defined(BOOST_SPIRIT_LOOPS_HPP)
    12 #define BOOST_SPIRIT_LOOPS_HPP
    13 
    14 ///////////////////////////////////////////////////////////////////////////////
    15 #include <boost/spirit/core/parser.hpp>
    16 #include <boost/spirit/core/composite/composite.hpp>
    17 
    18 ///////////////////////////////////////////////////////////////////////////////
    19 namespace boost { namespace spirit {
    20 
    21     ///////////////////////////////////////////////////////////////////////////
    22     //
    23     //  fixed_loop class
    24     //
    25     //      This class takes care of the construct:
    26     //
    27     //          repeat_p (exact) [p]
    28     //
    29     //      where 'p' is a parser and 'exact' is the number of times to
    30     //      repeat. The parser iterates over the input exactly 'exact' times.
    31     //      The parse function fails if the parser does not match the input
    32     //      exactly 'exact' times.
    33     //
    34     //      This class is parametizable and can accept constant arguments
    35     //      (e.g. repeat_p (5) [p]) as well as references to variables (e.g.
    36     //      repeat_p (ref (n)) [p]).
    37     //
    38     ///////////////////////////////////////////////////////////////////////////
    39     template <typename ParserT, typename ExactT>
    40     class fixed_loop
    41     : public unary<ParserT, parser <fixed_loop <ParserT, ExactT> > >
    42     {
    43     public:
    44 
    45         typedef fixed_loop<ParserT, ExactT>     self_t;
    46         typedef unary<ParserT, parser<self_t> >  base_t;
    47 
    48         fixed_loop (ParserT const & subject, ExactT const & exact)
    49         : base_t(subject), m_exact(exact) {}
    50 
    51         template <typename ScannerT>
    52         typename parser_result <self_t, ScannerT>::type
    53         parse (ScannerT const & scan) const
    54         {
    55             typedef typename parser_result<self_t, ScannerT>::type result_t;
    56             result_t hit = scan.empty_match();
    57             std::size_t n = m_exact;
    58 
    59             for (std::size_t i = 0; i < n; ++i)
    60             {
    61                 if (result_t next = this->subject().parse(scan))
    62                 {
    63                     scan.concat_match(hit, next);
    64                 }
    65                 else
    66                 {
    67                     return scan.no_match();
    68                 }
    69             }
    70 
    71             return hit;
    72         }
    73 
    74         template <typename ScannerT>
    75         struct result
    76         {
    77             typedef typename match_result<ScannerT, nil_t>::type type;
    78         };
    79 
    80     private:
    81 
    82         ExactT m_exact;
    83     };
    84 
    85     ///////////////////////////////////////////////////////////////////////////////
    86     //
    87     //  finite_loop class
    88     //
    89     //      This class takes care of the construct:
    90     //
    91     //          repeat_p (min, max) [p]
    92     //
    93     //      where 'p' is a parser, 'min' and 'max' specifies the minimum and
    94     //      maximum iterations over 'p'. The parser iterates over the input
    95     //      at least 'min' times and at most 'max' times. The parse function
    96     //      fails if the parser does not match the input at least 'min' times
    97     //      and at most 'max' times.
    98     //
    99     //      This class is parametizable and can accept constant arguments
   100     //      (e.g. repeat_p (5, 10) [p]) as well as references to variables
   101     //      (e.g. repeat_p (ref (n1), ref (n2)) [p]).
   102     //
   103     ///////////////////////////////////////////////////////////////////////////////
   104     template <typename ParserT, typename MinT, typename MaxT>
   105     class finite_loop
   106     : public unary<ParserT, parser<finite_loop<ParserT, MinT, MaxT> > >
   107     {
   108     public:
   109 
   110         typedef finite_loop <ParserT, MinT, MaxT> self_t;
   111         typedef unary<ParserT, parser<self_t> >   base_t;
   112 
   113         finite_loop (ParserT const & subject, MinT const & min, MaxT const & max)
   114         : base_t(subject), m_min(min), m_max(max) {}
   115 
   116         template <typename ScannerT>
   117         typename parser_result <self_t, ScannerT>::type
   118         parse(ScannerT const & scan) const
   119         {
   120             BOOST_SPIRIT_ASSERT(m_min <= m_max);
   121             typedef typename parser_result<self_t, ScannerT>::type result_t;
   122             result_t hit = scan.empty_match();
   123 
   124             std::size_t n1 = m_min;
   125             std::size_t n2 = m_max;
   126 
   127             for (std::size_t i = 0; i < n2; ++i)
   128             {
   129                 typename ScannerT::iterator_t save = scan.first;
   130                 result_t next = this->subject().parse(scan);
   131  
   132                 if (!next)
   133                 {
   134                     if (i >= n1)
   135                     {
   136                         scan.first = save;
   137                         break;
   138                     }
   139                     else
   140                     {
   141                         return scan.no_match();
   142                     }
   143                 }
   144 
   145                 scan.concat_match(hit, next);
   146             }
   147 
   148             return hit;
   149         }
   150 
   151         template <typename ScannerT>
   152         struct result
   153         {
   154             typedef typename match_result<ScannerT, nil_t>::type type;
   155         };
   156 
   157     private:
   158 
   159         MinT    m_min;
   160         MaxT    m_max;
   161     };
   162 
   163     ///////////////////////////////////////////////////////////////////////////////
   164     //
   165     //  infinite_loop class
   166     //
   167     //      This class takes care of the construct:
   168     //
   169     //          repeat_p (min, more) [p]
   170     //
   171     //      where 'p' is a parser, 'min' is the minimum iteration over 'p'
   172     //      and more specifies that the iteration should proceed
   173     //      indefinitely. The parser iterates over the input at least 'min'
   174     //      times and continues indefinitely until 'p' fails or all of the
   175     //      input is parsed. The parse function fails if the parser does not
   176     //      match the input at least 'min' times.
   177     //
   178     //      This class is parametizable and can accept constant arguments
   179     //      (e.g. repeat_p (5, more) [p]) as well as references to variables
   180     //      (e.g. repeat_p (ref (n), more) [p]).
   181     //
   182     ///////////////////////////////////////////////////////////////////////////////
   183 
   184     struct more_t {};
   185     more_t const more = more_t ();
   186 
   187     template <typename ParserT, typename MinT>
   188     class infinite_loop
   189      : public unary<ParserT, parser<infinite_loop<ParserT, MinT> > >
   190     {
   191     public:
   192 
   193         typedef infinite_loop <ParserT, MinT>   self_t;
   194         typedef unary<ParserT, parser<self_t> > base_t;
   195 
   196         infinite_loop (
   197             ParserT const& subject,
   198             MinT const& min,
   199             more_t const&
   200         )
   201         : base_t(subject), m_min(min) {}
   202 
   203         template <typename ScannerT>
   204         typename parser_result <self_t, ScannerT>::type
   205         parse(ScannerT const & scan) const
   206         {
   207             typedef typename parser_result<self_t, ScannerT>::type result_t;
   208             result_t hit = scan.empty_match();
   209             std::size_t n = m_min;
   210 
   211             for (std::size_t i = 0; ; ++i)
   212             {
   213                 typename ScannerT::iterator_t save = scan.first;
   214                 result_t next = this->subject().parse(scan);
   215 
   216                 if (!next)
   217                 {
   218                     if (i >= n)
   219                     {
   220                         scan.first = save;
   221                         break;
   222                     }
   223                     else
   224                     {
   225                         return scan.no_match();
   226                     }
   227                 }
   228 
   229                 scan.concat_match(hit, next);
   230             }
   231 
   232             return hit;
   233         }
   234 
   235         template <typename ScannerT>
   236         struct result
   237         {
   238             typedef typename match_result<ScannerT, nil_t>::type type;
   239         };
   240 
   241         private:
   242 
   243         MinT m_min;
   244     };
   245 
   246     template <typename ExactT>
   247     struct fixed_loop_gen
   248     {
   249         fixed_loop_gen (ExactT const & exact)
   250         : m_exact (exact) {}
   251 
   252         template <typename ParserT>
   253         fixed_loop <ParserT, ExactT>
   254         operator[](parser <ParserT> const & subject) const
   255         {
   256             return fixed_loop <ParserT, ExactT> (subject.derived (), m_exact);
   257         }
   258 
   259         ExactT m_exact;
   260     };
   261 
   262     namespace impl {
   263 
   264         template <typename ParserT, typename MinT, typename MaxT>
   265         struct loop_traits
   266         {
   267             typedef typename mpl::if_<
   268                 boost::is_same<MaxT, more_t>,
   269                 infinite_loop<ParserT, MinT>,
   270                 finite_loop<ParserT, MinT, MaxT>
   271             >::type type;
   272         };
   273 
   274     } // namespace impl
   275 
   276     template <typename MinT, typename MaxT>
   277     struct nonfixed_loop_gen
   278     {
   279        nonfixed_loop_gen (MinT min, MaxT max)
   280         : m_min (min), m_max (max) {}
   281 
   282        template <typename ParserT>
   283        typename impl::loop_traits<ParserT, MinT, MaxT>::type
   284        operator[](parser <ParserT> const & subject) const
   285        {
   286            typedef typename impl::loop_traits<ParserT, MinT, MaxT>::type ret_t;
   287            return ret_t(
   288                 subject.derived(),
   289                 m_min,
   290                 m_max);
   291        }
   292 
   293        MinT m_min;
   294        MaxT m_max;
   295     };
   296 
   297     template <typename ExactT>
   298     fixed_loop_gen <ExactT>
   299     repeat_p(ExactT const & exact)
   300     {
   301         return fixed_loop_gen <ExactT> (exact);
   302     }
   303 
   304     template <typename MinT, typename MaxT>
   305     nonfixed_loop_gen <MinT, MaxT>
   306     repeat_p(MinT const & min, MaxT const & max)
   307     {
   308         return nonfixed_loop_gen <MinT, MaxT> (min, max);
   309     }
   310 
   311 }} // namespace boost::spirit
   312 
   313 #endif // #if !defined(BOOST_SPIRIT_LOOPS_HPP)