views:

36

answers:

1

Say I have a Boost Spirit grammar like this, where a parent rule passes an inherited attribute to its children.

template <typename Iterator>
struct MyGrammar : qi::grammar<Iterator, vector<Foo>()>
{
    qi::rule<Iterator, vector<Foo>()> start;

    qi::rule<Iterator, vector<Foo>(Bar)> parent;
    qi::rule<Iterator, Foo(Bar)> child1;
    qi::rule<Iterator, Foo(Bar)> child2;

    MyGrammar() : MyGrammar::base_type(start)
    {
        start = parent( Bar(etc) ); // An "initial" value for the Bar passed
                                    // between the following rules.  More on
                                    // that later.

        parent = child1(_r1) >> child2(_r1);
        child1 = ...[do something with _r1];
        child2 = ...[do something with _r1];
    }
};

The Foo each the child rules return depends on the given Bar inherited attribute. I might also have this for the parent rule:

parent = *child(_r1);

What I'm wondering is whether or not it is possible for a child rule to modify an inherited attribute, propagate the modification to its parent rule, and have the new value be passed to the next child rule.

In the example above, the start rule would be establishing an initial value for the Bar that gets used in parent and its child rules. The Bar gets modified every time it passes through a child rule. Is this even possible though, and what would such code look like?

+1  A: 

Inherited attributes can be passed by reference:

qi::rule<Iterator, vector<Foo>(Bar)> parent;
qi::rule<Iterator, Foo(Bar&)> child1; 
qi::rule<Iterator, Foo(Bar&)> child2; 

and:

parent = child1(phoenix::ref(_r1)) >> child2(phoenix::ref(_r1));  

allowing to achieve exactly what you want.

hkaiser