Joel Falcou wrote:
How can I write a transform that matches expression like
a0+a1+a2+ ... +an (with N +)
You write a grammar.
and turn into a custom node like
sum(a0,a1,...,an)
You use proto::functional::flatten to turn the binary + expression tree
into a flat Fusion sequence, and then you use
proto::functional::unpack_expr to turn the Fusion sequence into an
expression node with any tag you want. See below:
#include <iostream>
#include
#include
#include
namespace mpl = boost::mpl;
namespace proto = boost::proto;
namespace fusion = boost::fusion;
using proto::_;
struct Plus
: proto::or_<
proto::terminal<_>
, proto::plus
>
{};
struct as_vector : proto::callable
{
template<typename Sig>
struct result;
template
struct result
: fusion::result_of::as_vector<
typename boost::remove_reference<Seq>::type
>
{};
template<typename Seq>
typename fusion::result_of::as_vector<Seq const>::type const
operator()(Seq const &seq) const
{
return fusion::as_vector(seq);
}
};
struct FlattenPlus
: proto::when<
proto::plus
, proto::functional::unpack_exprproto::tag::plus(
as_vector(proto::functional::flatten(_))
)
>
{};
int main()
{
proto::literal<int> i(0), j(1), k(2), l(3), m(4);
proto::display_expr(FlattenPlus()(i+j+k+l+m));
return 0;
}
This displays:
plus(
terminal(0)
, terminal(1)
, terminal(2)
, terminal(3)
, terminal(4)
)
The only reason I need as_vector above is because currently unpack_expr
requires a RandomAccessSequence, and a flattened expression is a
ForwardSequence. Fixing unpack_expr to handle ForwardSequences is on my
TODO list.
HTH,
--
Eric Niebler
BoostPro Computing
http://www.boostpro.com