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!