Boost logo

Boost :

From: Eric Niebler (eric_at_[hidden])
Date: 2007-07-07 23:23:13


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

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk