
David A. Greene wrote:
Now the next obvious thing to do is try do_[e1].while_(e2). So here's my attempt:
// A do_ "operator" boost::proto::terminal<tag::Do>::type const do_ = {{}};
// matches do[e1] struct DoGrammar : boost::proto::subscript< tag::Do, StatementGrammar > {};
// A while_ "operator" template<typename Expr> struct Expression< Expr , typename enable_if<proto::matches<Expr, DoGrammar> >::type > : proto::extends<Expr, Expression<Expr>, Domain> { Expression() : while_(proto::make_expr<tag::While>(*this)) {};
// Oops, don't know how to do this here BOOST_PROTO_DEFINE_FUNCTION_TEMPLATE( 1 , while_ , Domain , (tag::While) , BOOST_PP_SEQ_NIL ); };
Yes, it would be nice if that worked. I'll look into it.
Of course, I want to do while_(e1)[e2] as well, so there already is
BOOST_PROTO_DEFINE_FUNCTION_TEMPLATE( 1 , while_ , Domain , (tag::While) , BOOST_PP_SEQ_NIL );
at namespace scope. Is there some way to reuse this in the extension of expressions that match DoGrammar?
I don't think so. while_[...] and do_[...].while_(...) are two different things. Here is some code I just banged out for do_[...].while_(...). #include <iostream> #include <boost/xpressive/proto/proto.hpp> using namespace boost; using namespace proto; struct DoTag {}; struct WhileTag {}; template<typename Expr, typename EnableIf = void> struct Expression; struct Grammar // Stub grammar, matches all expressions : or_<terminal<_>, nary_expr<_, vararg<Grammar> > > {}; struct DoGrammar : subscript<terminal<DoTag>, Grammar> {}; struct Generator { template<typename Expr> struct apply { typedef Expression<Expr> type; }; template<typename Expr> static Expression<Expr> make(Expr const &expr) { return Expression<Expr>(expr); } }; struct Domain : domain<Generator, Grammar> {}; template<typename Expr, typename EnableIf> struct Expression : extends<Expr, Expression<Expr>, Domain> { explicit Expression(Expr const &expr = Expr()) : extends<Expr, Expression<Expr>, Domain>(expr) {} using extends<Expr, Expression<Expr>, Domain>::operator =; }; Expression<terminal<DoTag>::type> const do_ = Expression<terminal<DoTag>::type>(); template<typename Expr> struct Expression<Expr, typename enable_if<matches<Expr, DoGrammar>
::type> : extends<Expr, Expression<Expr>, Domain> { explicit Expression(Expr const &expr = Expr()) : extends<Expr, Expression<Expr>, Domain>(expr) , while_(make_expr<WhileTag, Domain>(This())) {}
using extends<Expr, Expression<Expr>, Domain>::operator =; typename proto::result_of::make_expr<WhileTag, Domain, Expression const>::type while_; private: Expression const &This() const { return *this; } }; struct DoWhileGrammar : function< unary_expr< WhileTag , DoGrammar > , Grammar > {}; template<typename Expr> void test(Expr const &expr) { BOOST_MPL_ASSERT((matches<Expr, DoWhileGrammar>)); } terminal<std::ostream &>::type const cout_ = {std::cout}; int main() { test(do_[ cout_ << "hello, world" ].while_(true)); return 0; } BTW, are you working with Dan Marsden on the Phoenix port, or just experimenting with your own Proto-flavored lambda library? Just curious. -- Eric Niebler Boost Consulting www.boost-consulting.com