Boost logo

Boost :

From: Eric Niebler (eric_at_[hidden])
Date: 2008-03-18 00:00:20


Markus Werle wrote:
> Task 4: Write an expand function that for
> a*(b+c) returns a type representation a*b+a*c

The Expand transform defined below does this.

#include <iostream>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/proto/debug.hpp>
#include <boost/xpressive/proto/context.hpp>
#include <boost/xpressive/proto/transform.hpp>
using namespace boost;

template<int I> struct arg
{
     friend std::ostream &operator <<(std::ostream &sout, arg)
     {
         return sout << "arg<" << I << ">";
     }
};

proto::terminal<arg<1> >::type a;
proto::terminal<arg<2> >::type b;
proto::terminal<arg<3> >::type c;
proto::terminal<arg<4> >::type d;

using namespace proto;

struct Expand;
struct Recurse;

struct Distribute
   : or_<
         when<
             plus<_,_>
           , _make_plus(Recurse(_left), Recurse(_right))
>
       , when<
             minus<_,_>
           , _make_minus(Recurse(_left), Recurse(_right))
>
>
{};

struct Recurse
   : or_<
         Distribute
       , when<Expand, _make_multiplies(_state, Expand)>
>
{};

struct Expand
   : or_<
         terminal<_>
       , when<multiplies<_, Distribute>, Distribute(_right, _left)>
       , nary_expr<_, vararg<Expand> >
>
{};

int main()
{
     int ignore = 0;
     display_expr(
         Expand()(a*(b+c-d), ignore, ignore)
     );
}

The above code fragment displays:

minus(
     plus(
         multiplies(
             terminal(arg<1>)
           , terminal(arg<2>)
         )
       , multiplies(
             terminal(arg<1>)
           , terminal(arg<3>)
         )
     )
   , multiplies(
         terminal(arg<1>)
       , terminal(arg<4>)
     )
)

I think that's right. That's a fun little problem. :-)

-- 
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