boost::spirit::x3 attribute compatibility rules, intuition or code?
Asked Answered
M

1

3

Is there a document somewhere which describes how various spirit::x3 rule definition operations affect attribute compatibility?

I was surprised when:

x3::lexeme[ x3::alpha > *(x3::alnum | x3::char_('_')) ]

could not be moved into a fusion-adapted struct:

struct Name {
    std::string value;
};

For the time being, I got rid of the first mandatory alphabetical character, but I would still like to express a rule which defines that the name string must begin with a letter. Is this one of those situations where I need to try adding eps around until it works, or is there a stated reason why the above couldn't work?

I apologize if this has been written down somewhere, I couldn't find it.

Microsporophyll answered 13/5, 2016 at 4:1 Comment(4)
According to what I can find in the docs ([1] [2] [3] [4]) that should reduce to a single character vector, so it should work. Perhaps a bug?Pearsall
Can you update your questions with a complete working code sample that would allow to reproduce this?Pearsall
@DanMašek I completely agree with that. I made it because I'm a rountinier, but I hate having go through those motions because it's just wasting time, and frequently I "maigcally" don't reproduce the original problem...Titlark
And I can't type straight. MOAR COFFEE :)Titlark
T
7

If you're not on the develop branch you don't have the fix for that single-element sequence adaptiation bug, so yeah it's probably that.

Due to the genericity of attribute transformation/propagation, there's a lot of wiggle room, but of course it's just documented and ultimately in the code. In other words: there's no magic.

In the Qi days I'd have "fixed" this by just spelling out the desired transform with qi::as<> or qi::attr_cast<>. X3 doesn't have it (yet), but you can use a rule to mimick it very easily:

Live On Coliru

#include <iostream>
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/home/x3.hpp>

namespace x3 = boost::spirit::x3;

struct Name {
    std::string value;
};

BOOST_FUSION_ADAPT_STRUCT(Name, value)

int main() {

    std::string const input = "Halleo123_1";
    Name out;

    bool ok = x3::parse(input.begin(), input.end(),
            x3::rule<struct _, std::string>{} =
            x3::alpha >> *(x3::alnum | x3::char_('_')),
            out);

    if (ok)
        std::cout << "Parsed: " << out.value << "\n";
    else
        std::cout << "Parse failed\n";
}

Prints:

Parsed: Halleo123_1

Automate it

Because X3 works so nicely with c++14 core language features, it's not hard to reduce typing:

Understanding the List Operator (%) in Boost.Spirit

Titlark answered 13/5, 2016 at 8:26 Comment(3)
Thanks again - the as<> template did the trick - defined mine rule to the struct, but the definition was as<std::string> and it figured it out.Microsporophyll
As an aside, did that single-element sequence fix get into 1.61?Microsporophyll
@Microsporophyll Not as far as I can tell (I checked a8e391bd99dddb and it's in master, but I doubt that has been tagged - there doesn't seem to be a tag corresponding to 1.61)Titlark

© 2022 - 2024 — McMap. All rights reserved.