5

I am trying to write a parser with Spirit X3, but I haven't gotten very far because I'm running into a compilation error that I can't figure out. I think I know what the compiler is complaining about, but what I don't understand is why it cares. The following code compiles (clang 3.9, Boost 1.62.0) and works. (I realize it's structured poorly and that there are built-in parsers for constants; I'm just trying to demonstrate the issue.)

#define BOOST_SPIRIT_X3_DEBUG

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

using namespace std;
namespace x3 = boost::spirit::x3;

namespace lang {

    using namespace x3;

    struct Constant {
    };

    rule<class constant_id, Constant> const constant = "constant";

    auto const integer_literal = -char_('-') >> +digit;
    auto const float_literal = -char_('-') >> +digit >> -(char_('.') >> *digit);

    auto const constant_def = (integer_literal)[([](auto &ctx) { _val(ctx) = Constant(); })];

    BOOST_SPIRIT_DEFINE(constant);
}

int main(int argc, char *argv[]) {

    string s("3.14159");
    if (x3::phrase_parse(s.begin(), s.end(), lang::constant, x3::space)) {
        cout << "Ok!";
    } else {
        cout << "Error!";
    }

    return 0;
}

However, if I change constant_def to use float_literal instead of integer_literal:

auto const constant_def = (float_literal)[([](auto &ctx) { _val(ctx) = Constant(); })];

I start to get a compilation error.

sequence.hpp:143:9: error: static_assert failed "Attribute does not have the expected size."
    static_assert(
    ^

Looking at the source, I see a message:

// If you got an error here, then you are trying to pass
// a fusion sequence with the wrong number of elements
// as that expected by the (sequence) parser.

I think that the error has to do with the presence of the optional in the definition of float_literal. I believe that the attribute type of integer_literal is something like vector<char> but that the optional causes the attribute of float_literal to be something like tuple<vector<char>, optional<vector<char>>>? And somewhere I'm trying to force that to be a string or something and it's failing because it's trying to convert a 2-tuple to a 1-tuple. I suspect that the solution is to wrap the float_literal definition in raw[] so that I get the underlying string instead, which is want I want anyway. But since this is my first X3 parser, I want to understand why the compiler is raising this error so I can diagnose it if it comes up in another context.

What I really don't understand is why the compiler cares about the type of float_literal. I've attached a semantic action that generates an instance of Constant, which is the attribute type of the constant rule, without any reference to the attribute of float_literal, so why does the compiler care about the attribute of float_literal at all? Where is it trying to do the unequal-length-sequence assignment, and for what purpose?

Thanks!

Quentin
  • 62,093
  • 7
  • 131
  • 191
Willis Blackburn
  • 8,068
  • 19
  • 36
  • 3
    The problem seems to be caused by something I think is a bug in X3: there is a mismatch between the size of the synthesized attribute and the size computed while partitioning the sequence when there is an `optional`(which derives from `proxy` which has `is_pass_through_unary=true`) that contains a sequence with more than one element. [An even simpler example that shows the same problem](http://melpon.org/wandbox/permlink/D7rDdY55v7fHQboP) (and [the values that fail in the static assert](http://melpon.org/wandbox/permlink/S2SJnSmI6ISrGfL9)). – llonesmiz Dec 12 '16 at 16:38
  • 4
    Well I'm not sure that bug is the correct term since it seems to be intentional. It allows to do something like [this](http://melpon.org/wandbox/permlink/WhbnW8Bt3qSr6LfF) that was impossible in Spirit.Qi. The problem is that there are two desired and incompatible behaviours and obviously both can't work at the same time. Maybe there should be a directive to either `flatten` or "`unflatten`" the attributes allowing us to choose the behaviour we need. – llonesmiz Dec 12 '16 at 16:42

0 Answers0