1

In the following test case, the alternation of one alpha and a sequence bombs with a long error dump basically saying static assertion failed: The parser expects tuple-like attribute type. Intuitively, I expected the entire rule to produce a string but that's not what happens. I either have to change the left-side of the alternation to +alpha (making both sides vectors) or go the path of semantic actions, at least for the lone char in the alternation (append to _val). Or, change the lone left-side char_ to string. Anyways, I can't figure out what's the proper simple way of parsing a string as trivial as this, any hint is appreciated. TIA.

#include <iostream>

#include <boost/spirit/home/x3.hpp>
namespace x3 = boost::spirit::x3;

namespace grammar {

using x3::char_;
using x3::alpha;
using x3::xdigit;

const auto x =
    x3::rule< struct x_class, std::string > { "x" } =
    char_('/') > alpha >> *(alpha | (char_('#') > xdigit));

} // namespace grammar

int main () {
    std::string input{ "/Foobar#F" }, attr;
    auto iter = input.begin ();

    if (phrase_parse (iter, input.end (), grammar::x, x3::space, attr)) {
        std::cout << attr << std::endl;
    }

    return 0;
}
Engineerist
  • 367
  • 2
  • 13

1 Answers1

1

I hate this behaviour too. Qi was much more natural in this respect.

I honestly don't always know how to "fix" it although

  • in this case it seems you can use raw[] - simplifying the grammar as well
  • sometimes it helps to avoid mixing operator> and operator>>

Here's what I'd do for your grammar:

Live On Coliru

#include <iostream>
#include <boost/spirit/home/x3.hpp>
namespace x3 = boost::spirit::x3;

namespace grammar {
    const auto x =
        x3::rule<struct x_class, std::string> { "x" } =
        x3::raw [ '/' > x3::alpha >> *(x3::alpha | ('#' > x3::xdigit)) ];
}

int main () {
    std::string input{ "/Foobar#F" }, attr;
    auto iter = input.begin ();

    if (phrase_parse (iter, input.end (), grammar::x, x3::space, attr)) {
        std::cout << attr << std::endl;
    }
}

Prints

/Foobar#F
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Much appreciated. I know nothing of the internal details of spirit. IIUC, this behavior is consistent across all parsers and consistency is great design. But it just seems to me that the intuitive behavior, that which is expected, if at all possible, should be present here. – Engineerist Nov 01 '19 at 11:29
  • TBH I think it is down to an (accidental?) fundamental change in thinking about attribute compatibility and propagation with rules in X3. It appears that much stricter congruence is expected from the exposed vs synthesized attribute types, and I _guess_ this was to help with getting much better error messages. I do feel it inadvertantly removed extensibility/transformation opportunities. If I understood the code and its design objectives better I might file an issue over this. – sehe Nov 01 '19 at 12:09