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