Home
Reading
Searching
Subscribe
Sponsors
Statistics
Posting
Contact
Spam
Lists
Links
About
Hosting
Filtering
Features Download
Marketing
Archives
FAQ
Blog
 
Gmane

From: Hartmut Kaiser <hartmut.kaiser <at> gmail.com>
Subject: Re: attr() last resort
Newsgroups: gmane.comp.parsers.spirit.general
Date: Saturday 23rd January 2010 18:01:11 UTC (over 8 years ago)
> On Sat, Jan 23, 2010 at 13:38,   wrote:
> > Now I have studied philosophy,medicine and the law,and unfortunately,
> > theology,wearily sweating, yet I stand now,poor fool, no wiser than I
> was
> > before.
> > (goethe, faust part one)
> > made all sort of posts, read the forums up and down. i still can't
> set an
> > attribute while parsing. my last resort: here is the code. comments
> on the
> > factor parser below highly appreciated.
> > thanks!
> 
> I feel your pain. After spending way too much time in trying to get
> attributes to work,
> I reverted to qi::raw for about everything (the Spirit 1.x way). I
> also tried to store a relative simple parse expression in a struct,
> with BOOST_FUSION_ADAPT_STRUCT. I can't spot the mistake in your code
> at first sight either.
> 
> The mere fact that we need to manually construct the correct attribute
> accumulation is driving users into erroneous code. The compile errors
> don't make sense whatsoever, so you're basically up to gun-shotting
> until something compiles, but then doesn't work.
> 
> Couldn't spirit have a debug feature that prints the accumulated
> attributes such that, when it compiles, we can see what we're passing
> into our non-terminal, and tells us: create a struct that looks like
> '....' to catch all parsed stuff in non-terminal X ?

There is

namespace boost { namespace spirit { namespace traits
{
    template 
    struct attribute_of;
}}}

Where you can leave off the Context and Iterator parameter most of the time
(raw[] needs the Iterator, though). The 'Component' is the parser
expression
you would like to query for its attribute. Note though, 'Component' is not
the proto expression (i.e. not something like BOOST_TYPEOF(int_ >>
double_)), but the parser expression you get as a result of applying

namespace boost { namespace spirit { namespace result_of
{
    template 
    struct compile;
}}}

So overall you could write:

    typedef spirit::result_of::compile<
        spirit::qi::domain, 
        BOOST_TYPEOF(int_ >> double_)
    >::type parser_expression_type;

    mpl::print<
        spirit::traits::attribute_of<
            parser_expression_type, 
            spirit::unused_type, 
            <...your_iterator_type...>
        >::type 
    > x;

which would generate a warning referring to the type it is instantiated
with. 

Or let us encapsulate that into a reusable facility printing the typename
to
cout:

    template 
    struct attribute_of_qi_component
    {
        typedef typename spirit::result_of::compile<
            qi::domain, Expr
        >::type parser_expression_type;

        typedef typename spirit::traits::attribute_of<
            parser_expression_type, 
            spirit::unused_type, Iterator
        >::type type;
    };

    struct display_attribute_type
    {
        template 
        void operator()(T const &) const
        {
            typedef typename attribute_of_qi_component::type type;
            std::cout << typeid(type).name() << std::endl;
        }
    };
    display_attribute_type const display = {};

Which you can invoke with:

    display(qi::int_ >> qi::double_);

Note: all this is from the top of my head, so might not compile as is...

The overall attribute propagation is not really magic... It's just that you
need to understand what attribute types an expression has. The process
these
compound attributes are generated is formal and pretty much documented. In
the end it's just a different way of looking at the expression.

> I wouldn't classify myself as a dumb user. I make extensively use of
> mpl, fusion and the invoke magic, the two latter being minimally
> documented and requiring above the ordinary levels of motivation. I
> tried to apply the same to attribute propagation and phoenix binding,
> to no avail. I'm hoping that some tip of the day will enlight me. If I
> may suggest an improvement to the tips of the day: always include an
> example with two non terminals (so rule A using rule B, where we add
> semantic actions in A and B), and also an example with a simple bind
> instead of a phoenix lambda construct. I almost never bind a semantic
> action to a 'double_' or similar, but always to a rule I defined
> myself.

Ok thanks, noted. Although attaching a semantic action to a self-defined
rule is not different form attaching one to a double. 
_1, _2, etc. always refer to the attributes of the thing it's attached to.
And the types of the attributes are defined by your rule definition. I'm
really trying to do exactly what you're asking for, writing about how
attribute propagation works, but obviously I failed so far :-( 

Did you see the 3 articles targeting the 'attribute magic'?

HTH
Regards Hartmut



------------------------------------------------------------------------------
Throughout its 18-year history, RSA Conference consistently attracts the
world's best and brightest in the field, creating opportunities for
Conference
attendees to learn about information security's most important issues
through
interactions with peers, luminaries and emerging and established companies.
http://p.sf.net/sfu/rsaconf-dev2dev
 
CD: 12ms