|
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