summaryrefslogtreecommitdiff
path: root/boost/spirit/home/x3/directive/repeat.hpp
blob: 9c4d92325538e3d95972d1697e6e57f9d029e59e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*=============================================================================
    Copyright (c) 2001-2011 Joel de Guzman
    Copyright (c) 2001-2011 Hartmut Kaiser
    Copyright (c) 2014 Thomas Bernard

    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(SPIRIT_X3_REPEAT_APRIL_16_2014_0848AM)
#define SPIRIT_X3_REPEAT_APRIL_16_2014_0848AM

#include <boost/spirit/home/x3/core/parser.hpp>
#include <boost/spirit/home/x3/operator/kleene.hpp>

namespace boost { namespace spirit { namespace x3 { namespace detail
{
    template <typename T>
    struct exact_count // handles repeat(exact)[p]
    {
        typedef T type;
        bool got_max(T i) const { return i >= exact_value; }
        bool got_min(T i) const { return i >= exact_value; }

        T const exact_value;
    };

    template <typename T>
    struct finite_count // handles repeat(min, max)[p]
    {
        typedef T type;
        bool got_max(T i) const { return i >= max_value; }
        bool got_min(T i) const { return i >= min_value; }

        T const min_value;
        T const max_value;
    };

    template <typename T>
    struct infinite_count // handles repeat(min, inf)[p]
    {
        typedef T type;
        bool got_max(T /*i*/) const { return false; }
        bool got_min(T i) const { return i >= min_value; }

        T const min_value;
    };
}}}}

namespace boost { namespace spirit { namespace x3
{
    template<typename Subject, typename RepeatCountLimit>
    struct repeat_directive : unary_parser<Subject, repeat_directive<Subject,RepeatCountLimit>>
    {
        typedef unary_parser<Subject, repeat_directive<Subject,RepeatCountLimit>> base_type;
        static bool const is_pass_through_unary = true;
        static bool const handles_container = true;

        repeat_directive(Subject const& subject, RepeatCountLimit const& repeat_limit_)
          : base_type(subject)
          , repeat_limit(repeat_limit_)
        {}

        template<typename Iterator, typename Context
          , typename RContext, typename Attribute>
        bool parse(
            Iterator& first, Iterator const& last
          , Context const& context, RContext& rcontext, Attribute& attr) const
        {
            Iterator local_iterator = first;
            typename RepeatCountLimit::type i{};
            for (/**/; !repeat_limit.got_min(i); ++i)
            {
                if (!detail::parse_into_container(
                      this->subject, local_iterator, last, context, rcontext, attr))
                    return false;
            }

            first = local_iterator;
            // parse some more up to the maximum specified
            for (/**/; !repeat_limit.got_max(i); ++i)
            {
                if (!detail::parse_into_container(
                      this->subject, first, last, context, rcontext, attr))
                    break;
            }
            return true;
        }

        RepeatCountLimit repeat_limit;
    };

    // Infinite loop tag type
    struct inf_type {};
    const inf_type inf = inf_type();

    struct repeat_gen
    {
        template<typename Subject>
        auto operator[](Subject const& subject) const
        {
            return *as_parser(subject);
        }

        template <typename T>
        struct repeat_gen_lvl1
        {
            repeat_gen_lvl1(T&& repeat_limit_)
              : repeat_limit(repeat_limit_)
            {}

            template<typename Subject>
            repeat_directive< typename extension::as_parser<Subject>::value_type, T>
            operator[](Subject const& subject) const
            {
                return { as_parser(subject),repeat_limit };
            }

            T repeat_limit;
        };

        template <typename T>
        repeat_gen_lvl1<detail::exact_count<T>>
        operator()(T const exact) const
        {
            return { detail::exact_count<T>{exact} };
        }

        template <typename T>
        repeat_gen_lvl1<detail::finite_count<T>>
        operator()(T const min_val, T const max_val) const
        {
            return { detail::finite_count<T>{min_val,max_val} };
        }

        template <typename T>
        repeat_gen_lvl1<detail::infinite_count<T>>
        operator()(T const min_val, inf_type const &) const
        {
            return { detail::infinite_count<T>{min_val} };
        }
    };

    auto const repeat = repeat_gen{};
}}}

namespace boost { namespace spirit { namespace x3 { namespace traits
{
    template <typename Subject, typename RepeatCountLimit, typename Context>
    struct attribute_of<x3::repeat_directive<Subject,RepeatCountLimit>, Context>
      : build_container<typename attribute_of<Subject, Context>::type> {};
}}}}


#endif