main.cpp 6.4 KB

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