#include #include #include namespace proto = boost::proto; namespace fusion = boost::fusion; namespace mpl = boost::mpl; using proto::_; // For display_expr debugging purposes namespace boost { namespace mpl { template std::ostream & operator<<(std::ostream & sout, mpl::int_) { return std::cout << "mpl::int_<" << N << ">"; } }} namespace tag { struct split {}; } template struct make_split : proto::result_of::make_expr {}; template typename make_split::type const split(Expr const& expr) { typename make_split::type const e = {expr}; return e; } struct push_back { BOOST_PROTO_CALLABLE() template struct result; template struct result : boost::add_const< typename fusion::result_of::push_back< typename boost::add_const::type>::type , typename boost::remove_const::type>::type >::type > {}; template typename fusion::result_of::push_back::type const operator()(Seq const& seq, T const& t) const { return fusion::push_back(seq, t); } }; #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) #define push_back(x,y) proto::call #endif // Given an expression that (maybe) contains split expressions, // replace the expressions with mpl::int_<0> terminals. struct Substitute : proto::or_< proto::when< proto::unary_expr , proto::terminal >::type(mpl::int_<0>()) > , proto::terminal<_> , proto::nary_expr<_, proto::vararg > > {}; // Walk an expression recursively. Collect into the state // vector the split expressions. Return the collected // replacements. struct Replacements : proto::or_< proto::when, proto::_state> , proto::when< proto::unary_expr , Replacements( proto::_child , push_back(proto::_state, Substitute(proto::_child)) ) > , proto::otherwise > > {}; // Start the recursive replacement collection on an expression // that may have split expressions. struct Splitter : proto::otherwise< Replacements(_, push_back(proto::_state, Substitute)) > {}; #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) #undef push_back #endif int main() { typedef proto::terminal::type char_; char_ const a = {'a'}; char_ const b = {'b'}; char_ const c = {'c'}; char_ const d = {'d'}; char_ const e = {'e'}; char_ const f = {'f'}; fusion::vector0<> const res = fusion::vector0<>(); fusion::for_each(Splitter()(split(a) + split(b), res), proto::functional::display_expr()); std::cout << "\n\n"; fusion::for_each(Splitter()(a + b, res), proto::functional::display_expr()); std::cout << "\n\n"; fusion::for_each(Splitter()(split(a) + b, res), proto::functional::display_expr()); std::cout << "\n\n"; fusion::for_each(Splitter()(a + split(b), res), proto::functional::display_expr()); std::cout << "\n\n"; fusion::for_each(Splitter()(a + split(b + c), res), proto::functional::display_expr()); std::cout << "\n\n"; fusion::for_each(Splitter()(a+b+split( c*d + split(e-f)), res), proto::functional::display_expr()); std::cout << "\n\n"; Splitter()(split(a) + split(b), res); Splitter()(a + b, res); Splitter()(split(a) + b, res); Splitter()(a + split(b), res); Splitter()(a + split(b + c), res); }