main.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // Copyright Abel Sinkovics (abel@sinkovics.hu) 2014.
  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/first_of.hpp>
  10. #include <boost/metaparse/middle_of.hpp>
  11. #include <boost/metaparse/space.hpp>
  12. #include <boost/metaparse/int_.hpp>
  13. #include <boost/metaparse/foldl_reject_incomplete_start_with_parser.hpp>
  14. #include <boost/metaparse/one_of.hpp>
  15. #include <boost/metaparse/get_result.hpp>
  16. #include <boost/metaparse/token.hpp>
  17. #include <boost/metaparse/entire_input.hpp>
  18. #include <boost/metaparse/string.hpp>
  19. #include <boost/metaparse/build_parser.hpp>
  20. #include <boost/mpl/apply_wrap.hpp>
  21. #include <boost/mpl/fold.hpp>
  22. #include <boost/mpl/front.hpp>
  23. #include <boost/mpl/back.hpp>
  24. #include <boost/mpl/plus.hpp>
  25. #include <boost/mpl/minus.hpp>
  26. #include <boost/mpl/times.hpp>
  27. #include <boost/mpl/divides.hpp>
  28. #include <boost/mpl/bool.hpp>
  29. #include <boost/mpl/equal_to.hpp>
  30. #include <boost/mpl/eval_if.hpp>
  31. #include <boost/mpl/bool.hpp>
  32. using boost::metaparse::sequence;
  33. using boost::metaparse::lit_c;
  34. using boost::metaparse::last_of;
  35. using boost::metaparse::first_of;
  36. using boost::metaparse::middle_of;
  37. using boost::metaparse::space;
  38. using boost::metaparse::repeated;
  39. using boost::metaparse::build_parser;
  40. using boost::metaparse::int_;
  41. using boost::metaparse::foldl_reject_incomplete_start_with_parser;
  42. using boost::metaparse::get_result;
  43. using boost::metaparse::one_of;
  44. using boost::metaparse::token;
  45. using boost::metaparse::entire_input;
  46. using boost::mpl::apply_wrap1;
  47. using boost::mpl::fold;
  48. using boost::mpl::front;
  49. using boost::mpl::back;
  50. using boost::mpl::plus;
  51. using boost::mpl::minus;
  52. using boost::mpl::times;
  53. using boost::mpl::divides;
  54. using boost::mpl::eval_if;
  55. using boost::mpl::bool_;
  56. using boost::mpl::equal_to;
  57. using boost::mpl::bool_;
  58. /*
  59. * The grammar
  60. *
  61. * expression ::= plus_exp
  62. * plus_exp ::= prod_exp ((plus_token | minus_token) prod_exp)*
  63. * prod_exp ::= int_token ((mult_token | div_token) simple_exp)*
  64. * simple_exp ::= int_token | paren_exp
  65. * paren_exp ::= open_paren_token expression close_paren_token
  66. */
  67. typedef token<lit_c<'+'> > plus_token;
  68. typedef token<lit_c<'-'> > minus_token;
  69. typedef token<lit_c<'*'> > mult_token;
  70. typedef token<lit_c<'/'> > div_token;
  71. typedef token<lit_c<'('> > open_paren_token;
  72. typedef token<lit_c<')'> > close_paren_token;
  73. typedef token<int_> int_token;
  74. template <class T, char C>
  75. struct is_c : bool_<T::type::value == C> {};
  76. struct eval_plus
  77. {
  78. template <class State, class C>
  79. struct apply :
  80. eval_if<
  81. is_c<front<C>, '+'>,
  82. plus<typename State::type, typename back<C>::type>,
  83. minus<typename State::type, typename back<C>::type>
  84. >
  85. {};
  86. };
  87. struct eval_mult
  88. {
  89. template <class State, class C>
  90. struct apply :
  91. eval_if<
  92. is_c<front<C>, '*'>,
  93. times<typename State::type, typename back<C>::type>,
  94. divides<typename State::type, typename back<C>::type>
  95. >
  96. {};
  97. };
  98. struct plus_exp;
  99. typedef middle_of<open_paren_token, plus_exp, close_paren_token> paren_exp;
  100. typedef one_of<int_token, paren_exp> simple_exp;
  101. typedef
  102. foldl_reject_incomplete_start_with_parser<
  103. sequence<one_of<mult_token, div_token>, simple_exp>,
  104. simple_exp,
  105. eval_mult
  106. >
  107. prod_exp;
  108. struct plus_exp :
  109. foldl_reject_incomplete_start_with_parser<
  110. sequence<one_of<plus_token, minus_token>, prod_exp>,
  111. prod_exp,
  112. eval_plus
  113. >
  114. {};
  115. typedef last_of<repeated<space>, plus_exp> expression;
  116. typedef build_parser<entire_input<expression> > calculator_parser;
  117. #ifdef _STR
  118. # error _STR already defined
  119. #endif
  120. #define _STR BOOST_METAPARSE_STRING
  121. #if BOOST_METAPARSE_STD < 2011
  122. int main()
  123. {
  124. std::cout << "Please use a compiler that support constexpr" << std::endl;
  125. }
  126. #else
  127. int main()
  128. {
  129. using std::cout;
  130. using std::endl;
  131. cout
  132. << apply_wrap1<calculator_parser, _STR("13")>::type::value << endl
  133. << apply_wrap1<calculator_parser, _STR(" 1+ 2*4-6/2")>::type::value << endl
  134. << apply_wrap1<calculator_parser, _STR("1+2*3+4")>::type::value << endl
  135. << apply_wrap1<calculator_parser, _STR("(1+2)*(3+4)")>::type::value << endl
  136. << apply_wrap1<calculator_parser, _STR("(2*3)+(4*5)")>::type::value << endl
  137. << apply_wrap1<calculator_parser, _STR("2 * 3 + 4")>::type::value << endl
  138. << apply_wrap1<calculator_parser, _STR("2 + (3 * 4)")>::type::value << endl
  139. ;
  140. }
  141. #endif