// 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 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::if_; using boost::mpl::bool_; /* * 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 class _plus { public: typedef _plus type; template T operator()(T t) const { return _left(t) + _right(t); } private: typename A::type _left; typename B::type _right; }; template class _minus { public: typedef _minus type; template T operator()(T t) const { return _left(t) - _right(t); } private: typename A::type _left; typename B::type _right; }; template struct apply : if_< typename is_c, '+'>::type, _plus::type>, _minus::type> > {}; }; struct build_mult { template class _mult { public: typedef _mult type; template T operator()(T t) const { return _left(t) * _right(t); } private: typename A::type _left; typename B::type _right; }; template class _div { public: typedef _div type; template T operator()(T t) const { return _left(t) / _right(t); } private: typename A::type _left; typename B::type _right; }; template struct apply : if_< typename is_c, '*'>::type, _mult::type>, _div::type> > {}; }; struct build_value { typedef build_value type; template struct apply { typedef apply type; template int operator()(T) const { return V::type::value; } }; }; struct arg { typedef arg type; template T operator()(T t) const { return t; } }; 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 > function_parser; #if BOOST_METAPARSE_STD < 2011 template struct lambda : apply_wrap1 {}; using boost::metaparse::string; lambda >::type f1; lambda >::type f2; lambda >::type f3; lambda >::type f4; lambda >::type f5; #else #ifdef LAMBDA #error LAMBDA already defined #endif #define LAMBDA(exp) apply_wrap1::type LAMBDA(13) f1; LAMBDA(2 + 3) f2; LAMBDA(2 * 2) f3; LAMBDA( 1+ 2*4-6/2) f4; LAMBDA(2 * _) f5; #endif int main() { using std::cout; using std::endl; cout << f1(11) << endl << f2(11) << endl << f3(11) << endl << f4(11) << endl << f5(11) << endl << f5(1.1) << endl ; }