• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
30 #if BOOST_METAPARSE_STD < 2011
31 
main()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>
buildparsed73   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 
parsedparsed83   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 
operator <<(ostream & o,const parsed & p)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 
const_listconst_list108   constexpr const_list(const T& h, const const_list<T, Len - 1>& t) :
109     head(h),
110     tail(t)
111   {}
112 
push_frontconst_list113   constexpr const_list<T, Len + 1> push_front(const T& t) const
114   {
115     return const_list<T, Len + 1>(t, *this);
116   }
117 
atconst_list118   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 {
push_frontconst_list127   constexpr const_list<T, 1> push_front(const T& t) const
128   {
129     return const_list<T, 1>(t, *this);
130   }
131 
atconst_list132   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 {
runto_list141   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 {
runto_list150   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 
presultpresult161   constexpr presult(int v, int r) : value(v), remaining_from(r) {}
162 
incrpresult163   constexpr presult incr() const { return presult(value + 1, remaining_from); }
164 };
165 
166 template <char C, int N>
parse_cs(const const_list<char,N> & s,int from)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>
parse_impl(const const_list<char,N> & s)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>
parse(const char (& s)[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 {
runtmp_to_const_list_impl226   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 {
runtmp_to_const_list_impl243   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>
implparse_with_constexpr260   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 
main()293 int main()
294 {
295   using std::cout;
296   using std::endl;
297 
298   cout
299     << "TMP only parsers:" << endl
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
311     << P_MIXED(aba) << endl
312     << P_MIXED(aaaaaaabbbbaaaa) << endl
313     << endl
314     ;
315 }
316 
317 #endif
318 
319