Attribute compatibility and Alternatives

Joel de Guzman <[email protected]> Sat, 19 Feb 2011 11:17:57 +0800
Newsgroups gmane.comp.parsers.spirit.devel,gmane.comp.parsers.spirit.general
Message-ID <[email protected]>
Hi,

This code: http://tinyurl.com/65vjrgg demonstrates the calculator
automatically generating without decorations and with no semantic
actions; just pure attribute propagation.

I will not bother going into the details of how this example works
now, since I do intend to do a couple of tutorials touching on
this. So, please don't worry if this post does not make sense to
you yet. At the very least, let me just say that this *IS* important.
This post is targeting mostly the advanced users and the developers.

Various new features made this possible. Hartmut's recent work that
unifies handling of sequences and loops (e.g. kleene) clearly helped
in achieving this. At that point, I thought about modernizing the
calc-ast example to see how we've come so far in terms of attribute
handling: and all its magic!

At first try, it almost worked! Except for one remaining problem:
Alternatives still do not respect attribute compatibility. So,
I took the challenge and now we have attribute compatibility on
alternatives (also see my recent post on Attribute compatibility
and semantic actions). With this define:

     BOOST_SPIRIT_ALTERNATIVES_ALLOW_ATTR_COMPAT

Your alternatives can now allow attribute compatibility. Previously,
alternatives always(!) synthesize the expected attributes of its
nodes. With the new code, the new calc-ast example (link above)
works like a charm without any tricks and workarounds.

*Warning: more hard-core notes ahead*

It's not perfect though, and I doubt it will ever be. Here's why:
Given an alternative expression:

     a | b | c

with the expected attributes A, B and C, the expected attribute is:

     variant<A, B, C>

However, as much as we love attribute compatibility, we want to use
attributes Ac, Bc and Cc which are compatible with A, B and C
respectively. Hence, we want to pass in a compatible attribute of:

     variant<Ac, Bc, Cc>

Easy, just do a one-to-one correspondence with the variant types
and the expected types, you say? No! Often, the types in the variant
do not correspond that easily. Consider this:

     int_ | char_('x') | char('y')

and this variant:

     variant<int, char>

That variant should very well be compatible! So the tricky part here
is in determining which of the variant type corresponds to the
alternative node.

The initial idea was to have a trait that answers the question: is
component, C, compatible with attribute A? But that is a very tricky
answer. Such a trait will have to capture every detail of how Spirit
deals with attribute compatibility in terms of traits. Difficult!
And thinking about it more, it's not even usable. Here's why:
consider the code above. Here, the char_ parser *can* and will accept
an int! IOTW, char_ is compatible with int!

So, my solution is to simplify with a stricter trait:

     ///////////////////////////////////////////////////////////////////////////
     // Find out if T can be a substitute for Expected attribute
     ///////////////////////////////////////////////////////////////////////////
     template <typename T, typename Expected, typename Enable = void>
     struct is_substitute;

This trait returns true_ if T is a substitute with Expected (attribute).
Right now, it has to be

1) an exact match T == Expected
2) An optional with type T that is a substitute with another optional
    with Expected (attribute).
3) Both T and Expected are fusion sequences with the same number of
    elements and with element types of T that are substitutes for the
    target Expected element types.

So far, this has worked with the example, but might need to be refined
and expanded to handle more cases (e.g. std containers?).

Anyway, this has already been longer than I intended to write, so I'll
end now. Comments, suggestion please!

Regards,
-- 
Joel de Guzman
http://www.boostpro.com
http://boost-spirit.com




------------------------------------------------------------------------------
The ultimate all-in-one performance toolkit: Intel(R) Parallel Studio XE:
Pinpoint memory and threading errors before they happen.
Find and fix more than 250 security defects in the development cycle.
Locate bottlenecks in serial and parallel code that limit performance.
http://p.sf.net/sfu/intel-dev2devfeb