// 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) #define BOOST_MPL_LIMIT_STRING_SIZE 64 #define BOOST_METAPARSE_LIMIT_STRING_SIZE BOOST_MPL_LIMIT_STRING_SIZE #include #include #include #include #include #include #include #include #include #include #include #include #include using boost::mpl::apply_wrap1; using boost::mpl::front; using boost::mpl::back; using boost::mpl::if_; using boost::mpl::bool_; using boost::metaparse::build_parser; using boost::metaparse::token; using boost::metaparse::entire_input; using boost::metaparse::int_; using boost::metaparse::grammar; using boost::metaparse::transform; #if BOOST_METAPARSE_STD < 2011 int main() { std::cout << "Please use a compiler that supports constexpr" << std::endl; } #else #ifdef _STR # error _STR already defined #endif #define _STR BOOST_METAPARSE_STRING template struct is_c : bool_ {}; struct build_plus_impl { 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_plus { typedef build_plus type; template struct apply : boost::mpl::fold< typename back::type, typename front::type, build_plus_impl > {}; }; struct build_mult_impl { 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_mult { typedef build_mult type; template struct apply : boost::mpl::fold< typename back::type, typename front::type, build_mult_impl > {}; }; struct build_value { typedef build_value type; template struct apply { typedef apply type; template int operator()(T) const { return V::type::value; } }; }; struct build_arg { typedef build_arg type; template struct apply { typedef apply type; template T operator()(T t) const { return t; } }; }; struct keep_front { typedef keep_front type; template struct apply : front {}; }; typedef grammar<_STR("plus_exp")> ::import<_STR("int_token"), token>>::type ::rule<_STR("ws ::= (' ' | '\n' | '\r' | '\t')*")>::type ::rule<_STR("plus_token ::= '+' ws"), keep_front>::type ::rule<_STR("minus_token ::= '-' ws"), keep_front>::type ::rule<_STR("mult_token ::= '*' ws"), keep_front>::type ::rule<_STR("div_token ::= '/' ws"), keep_front>::type ::rule<_STR("arg_token ::= '_' ws"), keep_front>::type ::rule<_STR("plus_exp ::= prod_exp ((plus_token | minus_token) prod_exp)*"), build_plus>::type ::rule<_STR("prod_exp ::= value_exp ((mult_token | div_token) value_exp)*"), build_mult>::type ::rule<_STR("value_exp ::= int_token | arg_exp")>::type ::rule<_STR("arg_exp ::= arg_token"), build_arg>::type g; typedef build_parser> function_parser; #ifdef LAMBDA #error LAMBDA already defined #endif #define LAMBDA(exp) apply_wrap1::type LAMBDA(13) f1; LAMBDA(2 + 3) f2; LAMBDA(2 * 3) f3; LAMBDA(1+ 2*4-6/2) f4; LAMBDA(2 * _) f5; 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 ; } #endif