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.

experquisite
  • 879
  • 5
  • 14
  • According to what I can find in the docs ([\[1\]](http://ciere.com/cppnow15/x3_docs/spirit/quick_reference/compound_attribute_rules.html) [\[2\]](http://ciere.com/cppnow15/x3_docs/spirit/quick_reference/char.html) [\[3\]](http://ciere.com/cppnow15/x3_docs/spirit/quick_reference/directive.html) [\[4\]](http://ciere.com/cppnow15/x3_docs/spirit/quick_reference/operator.html)) that should reduce to a single character vector, so it should work. Perhaps a bug? – Dan Mašek May 13 '16 at 06:50
  • 3
    Can you update your questions with a complete working code sample that would allow to reproduce this? – Dan Mašek May 13 '16 at 06:56
  • 3
    @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... – sehe May 13 '16 at 08:27
  • And I can't type straight. MOAR COFFEE :) – sehe May 13 '16 at 09:36

1 Answers1

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

Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Thanks again - the `as<>` template did the trick - defined mine rule to the struct, but the definition was `as` and it figured it out. – experquisite May 13 '16 at 16:08
  • As an aside, did that single-element sequence fix get into 1.61? – experquisite May 13 '16 at 16:47
  • @experquisite 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) – sehe May 13 '16 at 17:22