I end up getting these move errors a lot and am not quite sure why other than having something to do with the way I'm parsing strings. Remove everything having to do with 'dummy' and the errors come back.
Someone mentioned using attr_gen (couldn't find this in the docs) and by doing so, I can get past these "traits::move_to" compile errors, but the parser still fails. I've marked the lines that I've added to get it to compile, but don't think are necessary with "<---".
#define BOOST_SPIRIT_X3_DEBUG
#include <complex>
#include <iostream>
#include <string>
#include <vector>
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
namespace client {
namespace ast {
struct number {
int num1;
int num2;
};
struct comment {
std::string text;
bool dummy; // <---
};
struct input {
std::vector<comment> comments;
std::vector<number> numbers;
};
}
}
BOOST_FUSION_ADAPT_STRUCT(client::ast::comment, text, dummy) // <---
BOOST_FUSION_ADAPT_STRUCT(client::ast::number, num1, num2)
BOOST_FUSION_ADAPT_STRUCT(client::ast::input, comments, numbers)
namespace client {
namespace parser {
namespace x3 = boost::spirit::x3;
namespace ascii = boost::spirit::x3::ascii;
using namespace x3;
x3::attr_gen dummy; // <---
auto const comment = char_ % ' ' >> dummy(false); // <---
//auto const comment = lexeme[+graph] >> dummy(false);
auto const number = int_ >> int_;
auto lines = [](auto p) { return *(p >> eol); };
auto const input = skip(blank) [
lines(comment) >>
lines(number)
];
}
}
int main()
{
namespace x3 = boost::spirit::x3;
using boost::spirit::x3::ascii::blank;
using x3::char_;
std::string const iss(R"(this is a test
1 2)");
auto iter = iss.begin(), eof = iss.end();
client::ast::input types;
bool ok = parse(iter, eof, client::parser::input, types);
if (iter != eof) {
std::cout << "Remaining unparsed: '" << std::string(iter, eof) << "'\n";
}
std::cout << "Parsed: " << (100.0 * std::distance(iss.begin(), iter) / iss.size()) << "%\n";
std::cout << "ok = " << ok << std::endl;
for (auto& item : types.comments) { std::cout << boost::fusion::as_deque(item) << "\n"; }
for (auto& item : types.numbers) { std::cout << boost::fusion::as_deque(item) << "\n"; }
}
x3::attr()
is perfectly well documented (the generator type behind it is an implementation detail, much like you'd usex3::int_
, notx3::int_gen
).The fact that you need it has been answered before. The key is having single-element fusion sequences.
This parses 1 or more arbitrary characters separated by single space literals. In your case it may match only
't'
because what follows is'h'
, not a' '
.I'd naturally spell that
So it would match anything until
eol
. If you insist on matching "wordy" things, by all meansTo synthesize the matched input into a string attribute, wrap it in
raw[]
:Or if, indeed you want no other whitespace than
' '
, make it soIt's slightly weird to spell it like
Because
"hello world"
or `"hello\tworld"'