// Copyright Abel Sinkovics (abel@sinkovics.hu) 2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using boost::metaparse::sequence; using boost::metaparse::lit_c; using boost::metaparse::last_of; using boost::metaparse::space; using boost::metaparse::repeated; using boost::metaparse::build_parser; using boost::metaparse::int_; using boost::metaparse::foldl_reject_incomplete_start_with_parser; using boost::metaparse::get_result; using boost::metaparse::one_of; using boost::metaparse::token; using boost::metaparse::entire_input; using boost::metaparse::transform; using boost::metaparse::always; using boost::mpl::apply_wrap1; using boost::mpl::front; using boost::mpl::back; using boost::mpl::plus; using boost::mpl::minus; using boost::mpl::times; using boost::mpl::divides; using boost::mpl::if_; using boost::mpl::bool_; using boost::mpl::equal_to; /* * The grammar * * expression ::= plus_exp * plus_exp ::= prod_exp ((plus_token | minus_token) prod_exp)* * prod_exp ::= value_exp ((mult_token | div_token) value_exp)* * value_exp ::= int_token | '_' */ typedef token > plus_token; typedef token > minus_token; typedef token > mult_token; typedef token > div_token; typedef token int_token; typedef token > arg_token; template struct is_c : bool_ {}; struct build_plus { template struct _plus { typedef _plus type; template struct apply : plus::type, typename apply_wrap1::type> {}; }; template struct _minus { typedef _minus type; template struct apply : minus::type, typename apply_wrap1::type> {}; }; template struct apply : if_< typename is_c, '+'>::type, _plus::type>, _minus::type> > {}; }; struct build_mult { template struct _mult { typedef _mult type; template struct apply : times::type, typename apply_wrap1::type> {}; }; template struct _div { typedef _div type; template struct apply : divides< typename apply_wrap1::type, typename apply_wrap1::type > {}; }; template struct apply : if_< typename is_c, '*'>::type, _mult::type>, _div::type> > {}; }; class build_value { private: template struct impl { typedef impl type; template struct apply : V {}; }; public: typedef build_value type; template struct apply : impl {}; }; struct arg { typedef arg type; template struct apply { typedef T type; }; }; typedef one_of, always > value_exp; typedef foldl_reject_incomplete_start_with_parser< sequence, value_exp>, value_exp, build_mult > prod_exp; typedef foldl_reject_incomplete_start_with_parser< sequence, prod_exp>, prod_exp, build_plus > plus_exp; typedef last_of, plus_exp> expression; typedef build_parser > metafunction_parser; #if BOOST_METAPARSE_STD < 2011 template struct meta_lambda : apply_wrap1 {}; int main() { using std::cout; using std::endl; using boost::metaparse::string; typedef meta_lambda >::type metafunction_class_1; typedef meta_lambda >::type metafunction_class_2; typedef meta_lambda >::type metafunction_class_3; typedef meta_lambda >::type metafunction_class_4; typedef meta_lambda >::type metafunction_class_5; typedef boost::mpl::int_<11> int11; cout << apply_wrap1::type::value << endl << apply_wrap1::type::value << endl << apply_wrap1::type::value << endl << apply_wrap1::type::value << endl << apply_wrap1::type::value << endl ; } #else #ifdef META_LAMBDA #error META_LAMBDA already defined #endif #define META_LAMBDA(exp) \ apply_wrap1::type int main() { using std::cout; using std::endl; typedef META_LAMBDA(13) metafunction_class_1; typedef META_LAMBDA(2 + 3) metafunction_class_2; typedef META_LAMBDA(2 * 2) metafunction_class_3; typedef META_LAMBDA( 1+ 2*4-6/2) metafunction_class_4; typedef META_LAMBDA(2 * _) metafunction_class_5; typedef boost::mpl::int_<11> int11; cout << apply_wrap1::type::value << endl << apply_wrap1::type::value << endl << apply_wrap1::type::value << endl << apply_wrap1::type::value << endl << apply_wrap1::type::value << endl ; } #endif