main.cpp 5.2 KB

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