]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Copyright (c) 2001-2011 Joel de Guzman | |
3 | Copyright (c) 2001-2011 Hartmut Kaiser | |
4 | Copyright (c) 2014 Thomas Bernard | |
5 | ||
6 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
7 | file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
8 | ==============================================================================*/ | |
9 | #if !defined(SPIRIT_X3_REPEAT_APRIL_16_2014_0848AM) | |
10 | #define SPIRIT_X3_REPEAT_APRIL_16_2014_0848AM | |
11 | ||
12 | #include <boost/function_types/function_type.hpp> | |
13 | #include <boost/function_types/parameter_types.hpp> | |
14 | #include <boost/spirit/home/x3/core/parser.hpp> | |
15 | #include <boost/spirit/home/x3/operator/kleene.hpp> | |
16 | ||
17 | namespace boost { namespace spirit { namespace x3 { namespace detail | |
18 | { | |
19 | template <typename T> | |
20 | struct exact_count // handles repeat(exact)[p] | |
21 | { | |
22 | typedef T type; | |
23 | bool got_max(T i) const { return i >= exact_value; } | |
24 | bool got_min(T i) const { return i >= exact_value; } | |
25 | ||
26 | T const exact_value; | |
27 | }; | |
28 | ||
29 | template <typename T> | |
30 | struct finite_count // handles repeat(min, max)[p] | |
31 | { | |
32 | typedef T type; | |
33 | bool got_max(T i) const { return i >= max_value; } | |
34 | bool got_min(T i) const { return i >= min_value; } | |
35 | ||
36 | T const min_value; | |
37 | T const max_value; | |
38 | }; | |
39 | ||
40 | template <typename T> | |
41 | struct infinite_count // handles repeat(min, inf)[p] | |
42 | { | |
43 | typedef T type; | |
44 | bool got_max(T /*i*/) const { return false; } | |
45 | bool got_min(T i) const { return i >= min_value; } | |
46 | ||
47 | T const min_value; | |
48 | }; | |
49 | }}}} | |
50 | ||
51 | namespace boost { namespace spirit { namespace x3 | |
52 | { | |
53 | template<typename Subject, typename RepeatCountLimit> | |
54 | struct repeat_directive : unary_parser<Subject, repeat_directive<Subject,RepeatCountLimit>> | |
55 | { | |
56 | typedef unary_parser<Subject, repeat_directive<Subject,RepeatCountLimit>> base_type; | |
57 | static bool const is_pass_through_unary = true; | |
58 | static bool const handles_container = true; | |
59 | ||
60 | repeat_directive(Subject const& subject, RepeatCountLimit const& repeat_limit_) | |
61 | : base_type(subject) | |
62 | , repeat_limit(repeat_limit_) | |
63 | {} | |
64 | ||
65 | template<typename Iterator, typename Context | |
66 | , typename RContext, typename Attribute> | |
67 | bool parse( | |
68 | Iterator& first, Iterator const& last | |
69 | , Context const& context, RContext& rcontext, Attribute& attr) const | |
70 | { | |
71 | Iterator local_iterator = first; | |
72 | typename RepeatCountLimit::type i{}; | |
73 | for (/**/; !repeat_limit.got_min(i); ++i) | |
74 | { | |
75 | if (!detail::parse_into_container( | |
76 | this->subject, local_iterator, last, context, rcontext, attr)) | |
77 | return false; | |
78 | } | |
79 | ||
80 | first = local_iterator; | |
81 | // parse some more up to the maximum specified | |
82 | for (/**/; !repeat_limit.got_max(i); ++i) | |
83 | { | |
84 | if (!detail::parse_into_container( | |
85 | this->subject, first, last, context, rcontext, attr)) | |
86 | break; | |
87 | } | |
88 | return true; | |
89 | } | |
90 | ||
91 | RepeatCountLimit repeat_limit; | |
92 | }; | |
93 | ||
94 | // Infinite loop tag type | |
95 | struct inf_type {}; | |
96 | const inf_type inf = inf_type(); | |
97 | ||
98 | struct repeat_gen | |
99 | { | |
100 | template<typename Subject> | |
101 | kleene<typename extension::as_parser<Subject>::value_type> | |
102 | operator[](Subject const& subject) const | |
103 | { | |
104 | return { as_parser(subject) }; | |
105 | } | |
106 | ||
107 | template <typename T> | |
108 | struct repeat_gen_lvl1 | |
109 | { | |
110 | repeat_gen_lvl1(T&& repeat_limit_) | |
111 | : repeat_limit(repeat_limit_) | |
112 | {} | |
113 | ||
114 | template<typename Subject> | |
115 | repeat_directive< typename extension::as_parser<Subject>::value_type, T> | |
116 | operator[](Subject const& subject) const | |
117 | { | |
118 | return { as_parser(subject),repeat_limit }; | |
119 | } | |
120 | ||
121 | T repeat_limit; | |
122 | }; | |
123 | ||
124 | template <typename T> | |
125 | repeat_gen_lvl1<detail::exact_count<T>> | |
126 | operator()(T const exact) const | |
127 | { | |
128 | return { detail::exact_count<T>{exact} }; | |
129 | } | |
130 | ||
131 | template <typename T> | |
132 | repeat_gen_lvl1<detail::finite_count<T>> | |
133 | operator()(T const min_val, T const max_val) const | |
134 | { | |
135 | return { detail::finite_count<T>{min_val,max_val} }; | |
136 | } | |
137 | ||
138 | template <typename T> | |
139 | repeat_gen_lvl1<detail::infinite_count<T>> | |
140 | operator()(T const min_val, inf_type const &) const | |
141 | { | |
142 | return { detail::infinite_count<T>{min_val} }; | |
143 | } | |
144 | }; | |
145 | ||
146 | auto const repeat = repeat_gen{}; | |
147 | }}} | |
148 | ||
149 | namespace boost { namespace spirit { namespace x3 { namespace traits | |
150 | { | |
151 | template <typename Subject, typename RepeatCountLimit, typename Context> | |
152 | struct attribute_of<x3::repeat_directive<Subject,RepeatCountLimit>, Context> | |
153 | : build_container<typename attribute_of<Subject, Context>::type> {}; | |
154 | }}}} | |
155 | ||
156 | ||
157 | #endif |