You don't need to expose all attributes, simplifying the attribute types considerably.
For matching a string literal without exposing it as a key (which, apparently, you don't want anyways, because you're ignoring it in the semantic action), use x3::lit("aaa")
instead of x3::string("aaa")
. In x3 expression, a bare "aaa"
will automatically be interpreted as x3::lit("aaa")
(due to x3::as_parser
).
What's more, you are addressing at_c<2>
implying that you didn't want x3::blank
exposed either. Why not simply x3::omit[x3::blank]
? Better yet, consider the use of a skipper, and have that implicit.
In action
you are using x3::_val
, which depends on the declared rule's attribute (there is no x3::rule in sight?) OR the actual bound reference (you don't pass anything to x3::parse
).
Since your action binds to the parser argument it seems you wanted its attribute, which can be queried with x3::_attr()
instead.
It seems you might be able to do without semantic actions altogether, see below
Fix Ideas:
This combines all the above:
See it Live On Coliru
#include <boost/spirit/home/x3.hpp>
#include <iostream>
namespace x3 = boost::spirit::x3;
int main() {
auto parser_gen = [=](std::string const a, auto&& p) {
return x3::skip(x3::blank)[ x3::lit(a) >> p ];
};
for (std::string const bar : { "aaa 42", "aaa99", }) {
int a;
if (parse(begin(bar), end(bar), parser_gen("aaa", x3::uint_), a)) {
std::cout << "Parsed " << a << "\n";
} else {
std::cout << "Failed\n";
}
}
}
Prints
Parsed 42
Parsed 99
See it Live On Coliru
namespace {
template <typename P>
auto label_gen(P p) {
return x3::omit[ x3::lexeme[ x3::as_parser(p) >> (&x3::punct | !x3::graph) ] ];
}
template <typename L, typename P> auto parser_gen(L l, P p) {
return x3::skip(x3::blank)[ label_gen(l) >> p ];
}
}
Now prints one less match:
Parsed 42
Failed
BONUS: Doing Useful Stuff
So, my guess is you wanted to combine multiple of these label/value pairs in a useful fashion, perhaps explaining the actions. Now, you could take a page from this answer: Boost Spirit x3: parse into structs.
Actually, I will refrain from reproducing the code from that example here, but I think it might apply to your use case very well.