main.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  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/repeated.hpp>
  6. #include <boost/metaparse/sequence.hpp>
  7. #include <boost/metaparse/lit_c.hpp>
  8. #include <boost/metaparse/last_of.hpp>
  9. #include <boost/metaparse/space.hpp>
  10. #include <boost/metaparse/int_.hpp>
  11. #include <boost/metaparse/foldl_reject_incomplete_start_with_parser.hpp>
  12. #include <boost/metaparse/one_of.hpp>
  13. #include <boost/metaparse/get_result.hpp>
  14. #include <boost/metaparse/token.hpp>
  15. #include <boost/metaparse/entire_input.hpp>
  16. #include <boost/metaparse/string.hpp>
  17. #include <boost/metaparse/transform.hpp>
  18. #include <boost/metaparse/always.hpp>
  19. #include <boost/metaparse/build_parser.hpp>
  20. #include <boost/mpl/apply_wrap.hpp>
  21. #include <boost/mpl/front.hpp>
  22. #include <boost/mpl/back.hpp>
  23. #include <boost/mpl/plus.hpp>
  24. #include <boost/mpl/minus.hpp>
  25. #include <boost/mpl/times.hpp>
  26. #include <boost/mpl/divides.hpp>
  27. #include <boost/mpl/bool.hpp>
  28. #include <boost/mpl/equal_to.hpp>
  29. #include <boost/mpl/if.hpp>
  30. using boost::metaparse::sequence;
  31. using boost::metaparse::lit_c;
  32. using boost::metaparse::last_of;
  33. using boost::metaparse::space;
  34. using boost::metaparse::repeated;
  35. using boost::metaparse::build_parser;
  36. using boost::metaparse::int_;
  37. using boost::metaparse::foldl_reject_incomplete_start_with_parser;
  38. using boost::metaparse::get_result;
  39. using boost::metaparse::one_of;
  40. using boost::metaparse::token;
  41. using boost::metaparse::entire_input;
  42. using boost::metaparse::transform;
  43. using boost::metaparse::always;
  44. using boost::mpl::apply_wrap1;
  45. using boost::mpl::front;
  46. using boost::mpl::back;
  47. using boost::mpl::plus;
  48. using boost::mpl::minus;
  49. using boost::mpl::times;
  50. using boost::mpl::divides;
  51. using boost::mpl::if_;
  52. using boost::mpl::bool_;
  53. using boost::mpl::equal_to;
  54. /*
  55. * The grammar
  56. *
  57. * expression ::= plus_exp
  58. * plus_exp ::= prod_exp ((plus_token | minus_token) prod_exp)*
  59. * prod_exp ::= value_exp ((mult_token | div_token) value_exp)*
  60. * value_exp ::= int_token | '_'
  61. */
  62. typedef token<lit_c<'+'> > plus_token;
  63. typedef token<lit_c<'-'> > minus_token;
  64. typedef token<lit_c<'*'> > mult_token;
  65. typedef token<lit_c<'/'> > div_token;
  66. typedef token<int_> int_token;
  67. typedef token<lit_c<'_'> > arg_token;
  68. template <class T, char C>
  69. struct is_c : bool_<T::type::value == C> {};
  70. struct build_plus
  71. {
  72. template <class A, class B>
  73. struct _plus
  74. {
  75. typedef _plus type;
  76. template <class T>
  77. struct apply :
  78. plus<typename apply_wrap1<A, T>::type, typename apply_wrap1<B, T>::type>
  79. {};
  80. };
  81. template <class A, class B>
  82. struct _minus
  83. {
  84. typedef _minus type;
  85. template <class T>
  86. struct apply :
  87. minus<typename apply_wrap1<A, T>::type, typename apply_wrap1<B, T>::type>
  88. {};
  89. };
  90. template <class State, class C>
  91. struct apply :
  92. if_<
  93. typename is_c<front<C>, '+'>::type,
  94. _plus<State, typename back<C>::type>,
  95. _minus<State, typename back<C>::type>
  96. >
  97. {};
  98. };
  99. struct build_mult
  100. {
  101. template <class A, class B>
  102. struct _mult
  103. {
  104. typedef _mult type;
  105. template <class T>
  106. struct apply :
  107. times<typename apply_wrap1<A, T>::type, typename apply_wrap1<B, T>::type>
  108. {};
  109. };
  110. template <class A, class B>
  111. struct _div
  112. {
  113. typedef _div type;
  114. template <class T>
  115. struct apply :
  116. divides<
  117. typename apply_wrap1<A, T>::type,
  118. typename apply_wrap1<B, T>::type
  119. >
  120. {};
  121. };
  122. template <class State, class C>
  123. struct apply :
  124. if_<
  125. typename is_c<front<C>, '*'>::type,
  126. _mult<State, typename back<C>::type>,
  127. _div<State, typename back<C>::type>
  128. >
  129. {};
  130. };
  131. class build_value
  132. {
  133. private:
  134. template <class V>
  135. struct impl
  136. {
  137. typedef impl type;
  138. template <class T>
  139. struct apply : V {};
  140. };
  141. public:
  142. typedef build_value type;
  143. template <class V>
  144. struct apply : impl<typename V::type> {};
  145. };
  146. struct arg
  147. {
  148. typedef arg type;
  149. template <class T>
  150. struct apply
  151. {
  152. typedef T type;
  153. };
  154. };
  155. typedef
  156. one_of<transform<int_token, build_value>, always<arg_token, arg> >
  157. value_exp;
  158. typedef
  159. foldl_reject_incomplete_start_with_parser<
  160. sequence<one_of<mult_token, div_token>, value_exp>,
  161. value_exp,
  162. build_mult
  163. >
  164. prod_exp;
  165. typedef
  166. foldl_reject_incomplete_start_with_parser<
  167. sequence<one_of<plus_token, minus_token>, prod_exp>,
  168. prod_exp,
  169. build_plus
  170. >
  171. plus_exp;
  172. typedef last_of<repeated<space>, plus_exp> expression;
  173. typedef build_parser<entire_input<expression> > metafunction_parser;
  174. #if BOOST_METAPARSE_STD < 2011
  175. template <class Exp>
  176. struct meta_lambda : apply_wrap1<metafunction_parser, Exp> {};
  177. int main()
  178. {
  179. using std::cout;
  180. using std::endl;
  181. using boost::metaparse::string;
  182. typedef meta_lambda<string<'1','3'> >::type metafunction_class_1;
  183. typedef meta_lambda<string<'2',' ','+',' ','3'> >::type metafunction_class_2;
  184. typedef meta_lambda<string<'2',' ','*',' ','2'> >::type metafunction_class_3;
  185. typedef
  186. meta_lambda<string<' ','1','+',' ','2','*','4','-','6','/','2'> >::type
  187. metafunction_class_4;
  188. typedef meta_lambda<string<'2',' ','*',' ','_'> >::type metafunction_class_5;
  189. typedef boost::mpl::int_<11> int11;
  190. cout
  191. << apply_wrap1<metafunction_class_1, int11>::type::value << endl
  192. << apply_wrap1<metafunction_class_2, int11>::type::value << endl
  193. << apply_wrap1<metafunction_class_3, int11>::type::value << endl
  194. << apply_wrap1<metafunction_class_4, int11>::type::value << endl
  195. << apply_wrap1<metafunction_class_5, int11>::type::value << endl
  196. ;
  197. }
  198. #else
  199. #ifdef META_LAMBDA
  200. #error META_LAMBDA already defined
  201. #endif
  202. #define META_LAMBDA(exp) \
  203. apply_wrap1<metafunction_parser, BOOST_METAPARSE_STRING(#exp)>::type
  204. int main()
  205. {
  206. using std::cout;
  207. using std::endl;
  208. typedef META_LAMBDA(13) metafunction_class_1;
  209. typedef META_LAMBDA(2 + 3) metafunction_class_2;
  210. typedef META_LAMBDA(2 * 2) metafunction_class_3;
  211. typedef META_LAMBDA( 1+ 2*4-6/2) metafunction_class_4;
  212. typedef META_LAMBDA(2 * _) metafunction_class_5;
  213. typedef boost::mpl::int_<11> int11;
  214. cout
  215. << apply_wrap1<metafunction_class_1, int11>::type::value << endl
  216. << apply_wrap1<metafunction_class_2, int11>::type::value << endl
  217. << apply_wrap1<metafunction_class_3, int11>::type::value << endl
  218. << apply_wrap1<metafunction_class_4, int11>::type::value << endl
  219. << apply_wrap1<metafunction_class_5, int11>::type::value << endl
  220. ;
  221. }
  222. #endif