]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright Abel Sinkovics (abel@sinkovics.hu) 2012. |
2 | // Distributed under the Boost Software License, Version 1.0. | |
3 | // (See accompanying file LICENSE_1_0.txt or copy at | |
4 | // http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
6 | #include <boost/metaparse/sequence.hpp> | |
7 | #include <boost/metaparse/lit_c.hpp> | |
8 | #include <boost/metaparse/foldl.hpp> | |
9 | #include <boost/metaparse/entire_input.hpp> | |
10 | #include <boost/metaparse/string.hpp> | |
11 | #include <boost/metaparse/build_parser.hpp> | |
12 | #include <boost/metaparse/get_result.hpp> | |
13 | #include <boost/metaparse/start.hpp> | |
14 | #include <boost/metaparse/last_of.hpp> | |
15 | #include <boost/metaparse/iterate_c.hpp> | |
16 | #include <boost/metaparse/one_char.hpp> | |
17 | #include <boost/metaparse/return_.hpp> | |
18 | ||
19 | #include <boost/mpl/apply_wrap.hpp> | |
20 | #include <boost/mpl/at.hpp> | |
21 | #include <boost/mpl/int.hpp> | |
22 | #include <boost/mpl/plus.hpp> | |
23 | #include <boost/mpl/front.hpp> | |
24 | #include <boost/mpl/pop_front.hpp> | |
25 | #include <boost/mpl/size.hpp> | |
26 | ||
27 | #include <iostream> | |
28 | #include <string> | |
29 | ||
b32b8144 | 30 | #if BOOST_METAPARSE_STD < 2011 |
7c673cae FG |
31 | |
32 | int main() | |
33 | { | |
34 | std::cout | |
35 | << "This example focuses on constexpr, which is not supported" | |
36 | << std::endl; | |
37 | } | |
38 | ||
39 | #else | |
40 | ||
41 | using boost::metaparse::sequence; | |
42 | using boost::metaparse::lit_c; | |
43 | using boost::metaparse::build_parser; | |
44 | using boost::metaparse::foldl; | |
45 | using boost::metaparse::entire_input; | |
46 | using boost::metaparse::get_result; | |
47 | using boost::metaparse::start; | |
48 | using boost::metaparse::last_of; | |
49 | using boost::metaparse::iterate_c; | |
50 | using boost::metaparse::one_char; | |
51 | using boost::metaparse::return_; | |
52 | ||
53 | using boost::mpl::apply_wrap1; | |
54 | using boost::mpl::apply_wrap2; | |
55 | using boost::mpl::plus; | |
56 | using boost::mpl::int_; | |
57 | using boost::mpl::at_c; | |
58 | using boost::mpl::front; | |
59 | using boost::mpl::pop_front; | |
60 | using boost::mpl::size; | |
61 | ||
62 | using std::ostream; | |
63 | ||
64 | /* | |
65 | * The grammar | |
66 | * | |
67 | * S ::= a* b* a* | |
68 | */ | |
69 | ||
70 | struct parsed | |
71 | { | |
72 | template <class T> | |
73 | constexpr static parsed build() | |
74 | { | |
75 | return | |
76 | parsed( | |
77 | at_c<typename T::type, 0>::type::value, | |
78 | at_c<typename T::type, 1>::type::value, | |
79 | at_c<typename T::type, 2>::type::value | |
80 | ); | |
81 | } | |
82 | ||
83 | constexpr parsed(int a1, int b, int a2) : | |
84 | a_count1(a1), | |
85 | b_count(b), | |
86 | a_count2(a2) | |
87 | {}; | |
88 | ||
89 | int a_count1; | |
90 | int b_count; | |
91 | int a_count2; | |
92 | }; | |
93 | ||
94 | ostream& operator<<(ostream& o, const parsed& p) | |
95 | { | |
96 | return | |
97 | o << "(" << p.a_count1 << ", " << p.b_count << ", " << p.a_count2 << ")"; | |
98 | } | |
99 | ||
100 | // constexpr parser | |
101 | ||
102 | template <class T, int Len> | |
103 | struct const_list | |
104 | { | |
105 | T head; | |
106 | const_list<T, Len - 1> tail; | |
107 | ||
108 | constexpr const_list(const T& h, const const_list<T, Len - 1>& t) : | |
109 | head(h), | |
110 | tail(t) | |
111 | {} | |
112 | ||
113 | constexpr const_list<T, Len + 1> push_front(const T& t) const | |
114 | { | |
115 | return const_list<T, Len + 1>(t, *this); | |
116 | } | |
117 | ||
118 | constexpr T at(int n) const | |
119 | { | |
120 | return n == 0 ? head : tail.at(n - 1); | |
121 | } | |
122 | }; | |
123 | ||
124 | template <class T> | |
125 | struct const_list<T, 0> | |
126 | { | |
127 | constexpr const_list<T, 1> push_front(const T& t) const | |
128 | { | |
129 | return const_list<T, 1>(t, *this); | |
130 | } | |
131 | ||
132 | constexpr T at(int) const | |
133 | { | |
134 | return T(); | |
135 | } | |
136 | }; | |
137 | ||
138 | template <class T, int N, int from = 0> | |
139 | struct to_list | |
140 | { | |
141 | static constexpr const_list<T, N - from> run(const T (&s)[N]) | |
142 | { | |
143 | return const_list<T, N - from>(s[from], to_list<T, N, from + 1>::run(s)); | |
144 | } | |
145 | }; | |
146 | ||
147 | template <class T, int N> | |
148 | struct to_list<T, N, N> | |
149 | { | |
150 | static constexpr const_list<T, 0> run(const T (&s)[N]) | |
151 | { | |
152 | return const_list<T, 0>(); | |
153 | } | |
154 | }; | |
155 | ||
156 | struct presult | |
157 | { | |
158 | int value; | |
159 | int remaining_from; | |
160 | ||
161 | constexpr presult(int v, int r) : value(v), remaining_from(r) {} | |
162 | ||
163 | constexpr presult incr() const { return presult(value + 1, remaining_from); } | |
164 | }; | |
165 | ||
166 | template <char C, int N> | |
167 | constexpr presult parse_cs(const const_list<char, N>& s, int from) | |
168 | { | |
169 | return | |
170 | from < N ? | |
171 | (s.at(from) == C ? parse_cs<C, N>(s, from + 1).incr() : presult(0, from)) : | |
172 | presult(0, from); | |
173 | } | |
174 | ||
175 | template <int N> | |
176 | constexpr parsed parse_impl(const const_list<char, N>& s) | |
177 | { | |
178 | return | |
179 | parsed( | |
180 | parse_cs<'a', N>(s, 0).value, | |
181 | parse_cs<'b', N>(s, parse_cs<'a', N>(s, 0).remaining_from).value, | |
182 | parse_cs<'a', N>( | |
183 | s, | |
184 | parse_cs<'b', N>( | |
185 | s, | |
186 | parse_cs<'a', N>(s, 0).remaining_from | |
187 | ).remaining_from | |
188 | ).value | |
189 | ); | |
190 | } | |
191 | ||
192 | template <int N> | |
193 | constexpr parsed parse(const char (&s)[N]) | |
194 | { | |
195 | return parse_impl(to_list<char, N>::run(s)); | |
196 | } | |
197 | ||
198 | // TMP parser | |
199 | ||
200 | struct count | |
201 | { | |
202 | typedef count type; | |
203 | ||
204 | template <class State, class C> | |
205 | struct apply : plus<int_<1>, State> {}; | |
206 | }; | |
207 | ||
208 | typedef foldl<lit_c<'a'>, int_<0>, count> as; | |
209 | typedef foldl<lit_c<'b'>, int_<0>, count> bs; | |
210 | ||
211 | typedef sequence<as, bs, as> s; | |
212 | ||
213 | typedef build_parser<entire_input<s> > parser; | |
214 | ||
215 | #ifdef P | |
216 | #error P already defined | |
217 | #endif | |
218 | #define P(x) \ | |
219 | parsed::build<boost::mpl::apply_wrap1<parser, BOOST_METAPARSE_STRING(#x)> >() | |
220 | ||
221 | // Mixed parser | |
222 | ||
223 | template <class ValueType, class L, int Len> | |
224 | struct tmp_to_const_list_impl | |
225 | { | |
226 | constexpr static const_list<ValueType, Len> run() | |
227 | { | |
228 | return | |
229 | const_list<ValueType, Len>( | |
230 | front<L>::type::value, | |
231 | tmp_to_const_list_impl< | |
232 | ValueType, | |
233 | typename pop_front<L>::type, | |
234 | Len - 1 | |
235 | >::run() | |
236 | ); | |
237 | } | |
238 | }; | |
239 | ||
240 | template <class ValueType, class L> | |
241 | struct tmp_to_const_list_impl<ValueType, L, 0> | |
242 | { | |
243 | constexpr static const_list<ValueType, 0> run() | |
244 | { | |
245 | return const_list<ValueType, 0>(); | |
246 | } | |
247 | }; | |
248 | ||
249 | template <class ValueType, class L> | |
250 | struct tmp_to_const_list : | |
251 | tmp_to_const_list_impl<ValueType, L, size<L>::type::value> | |
252 | {}; | |
253 | ||
254 | template <char C> | |
255 | struct parse_with_constexpr | |
256 | { | |
257 | typedef parse_with_constexpr type; | |
258 | ||
259 | template <class S> | |
260 | static constexpr presult impl() | |
261 | { | |
262 | return | |
263 | parse_cs<C, size<S>::type::value>(tmp_to_const_list<char, S>::run(), 0); | |
264 | } | |
265 | ||
266 | template <class S, class Pos> | |
267 | struct apply : | |
268 | apply_wrap2< | |
269 | last_of< | |
270 | iterate_c<one_char, impl<S>().remaining_from>, | |
271 | return_<int_<impl<S>().value> > | |
272 | >, | |
273 | S, | |
274 | Pos | |
275 | > | |
276 | {}; | |
277 | }; | |
278 | ||
279 | typedef parse_with_constexpr<'b'> bs_mixed; | |
280 | ||
281 | typedef sequence<as, bs_mixed, as> s_mixed; | |
282 | ||
283 | typedef build_parser<entire_input<s_mixed> > parser_mixed; | |
284 | ||
285 | #ifdef P_MIXED | |
286 | #error P_MIXED already defined | |
287 | #endif | |
288 | #define P_MIXED(x) \ | |
289 | parsed::build< \ | |
290 | boost::mpl::apply_wrap1<parser_mixed, BOOST_METAPARSE_STRING(#x)> \ | |
291 | >() | |
292 | ||
293 | int main() | |
294 | { | |
295 | using std::cout; | |
296 | using std::endl; | |
297 | ||
298 | cout | |
299 | << "TMP only parsers:" << endl | |
7c673cae FG |
300 | << P(aba) << endl |
301 | << P(aaaaaaabbbbaaaa) << endl | |
302 | << endl | |
303 | ||
304 | << "constexpr only parsers:" << endl | |
305 | << parse("") << endl | |
306 | << parse("aba") << endl | |
307 | << parse("aaaaaaabbbbaaaa") << endl | |
308 | << endl | |
309 | ||
310 | << "mixed parsers:" << endl | |
7c673cae FG |
311 | << P_MIXED(aba) << endl |
312 | << P_MIXED(aaaaaaabbbbaaaa) << endl | |
313 | << endl | |
314 | ; | |
315 | } | |
316 | ||
317 | #endif | |
318 |