问题
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"; }
}
回答1:
x3::attr()
is perfectly well documented (the generator type behind it is an implementation detail, much like you'd use x3::int_
, not x3::int_gen
).
The fact that you need it has been answered before. The key is having single-element fusion sequences.
- Spirit Qi attribute propagation issue with single-member struct
- Boost spirit compile error for trivial grammar
回答2:
comment = char_ % ' ';
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
comment = *(char_ - eol);
So it would match anything until eol
. If you insist on matching "wordy" things, by all means
comment = skip(blank) [ *lexeme[+graph_] ];
To synthesize the matched input into a string attribute, wrap it in raw[]
:
comment = raw [ skip(blank) [ *graph_ ] ];
Or if, indeed you want no other whitespace than ' '
, make it so
comment = raw[ skip(' ') [ *graph_ ] ];
It's slightly weird to spell it like
comment = raw[ (+graph_) % ' ' ];
Because
- it doesn't match an empty line
- it doesn't match
"hello world"
or `"hello\tworld"'
来源:https://stackoverflow.com/questions/45157367/x3-what-is-attr-gen