|
Boost Users : |
Subject: Re: [Boost-users] [Proto] Processing Lists
From: Eric Niebler (eric_at_[hidden])
Date: 2010-02-23 04:02:32
Hi David,
On 2/22/2010 10:29 PM, David Greene wrote:
> I want to process a list that looks something like this:
>
> struct List : or_<
> comma<
> List,
> Item
> >,
> Item
>> {};
>
> But rather than processing each item separately, I want to pass a fusion (or
> some other) sequence to a semantic action:
>
> when<
> List,
> SomeAction(...)
>> {};
>
> Ideally the argument to SomeAction would be a fusion sequence but I don't
> know how to produce one. This doesn't work:
>
> when<
> List,
> SomeAction(flatten(_))
>> {};
>
> because flatten is not a transform.
You were SO close. You want proto::functional::flatten here (the type of
a function object), not proto::flatten (an ordinary function).
> I don't want to use fold_tree because I
> don't want to actually fold the sequence. SomeAction is something like this:
>
> struct SomeAction : callable {
> template<typename Seq>
> void operator()(Seq range) {
> typedef ... iterator;
>
> // Is this legal for fusion sequences?
> for(iterator i = begin(range), iend = end(range);
> i != iend;
> i = next(i)) {
> ...
> }
> }
> }
>
> Is there a way to do this?
Try this:
#include <iostream>
#include <boost/fusion/include/for_each.hpp>
#include <boost/proto/proto.hpp>
using namespace std;
using namespace boost;
using namespace boost::proto;
struct display_value {
typedef void result_type;
template<typename Item>
void operator()(Item i) const {
cout << value(i) << ' ';
}
};
struct SomeAction : callable {
typedef void result_type;
template<typename Seq>
void operator()(Seq const &range) {
// Use fusion algorithms to process the list.
fusion::for_each(range, display_value());
}
};
struct Item : terminal<_> {};
struct List : or_<
comma<
List,
Item
>,
Item
> {};
struct ProcessList : when<
List,
SomeAction(functional::flatten(_))
> {};
int main()
{
ProcessList()((lit(1), 2, 3, 4));
}
> On a related note, I know I can use varag<> to match a function call
> expression with an arbitrary number of operands and invoke a transform
> on each operand. But how would I generate a fusion sequence of all
> the operands? In other words, with:
>
> proto::function< X, proto::vararg<Y> >
>
> how do I talk about the vararg<> part in a semantic action? CalculatorGrammar
> has a use of vararg but it uses fold<> to process it. I don't want to fold a
> sequence, I want to pass it to a transform.
Manjunath already answered this one. Proto expressions already are
fusion sequences, and proto::_expr returns the current expression. You
can use proto::functional::pop_front in a transform to pop off the first
bit (the thing that matches X in your example) and pass the result to
something that accepts fusion sequences.
HTH,
-- Eric Niebler BoostPro Computing http://www.boostpro.com
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net