I know I can implement a custom parser by making an object with the appropriate "parse" member function template, but I don't know what I need to do to make it use the skipper in the Context, which it seems to need to do. That is, below I expected both cases to succeed but the second fails:
namespace x3 = boost::spirit::x3;
namespace parser {
struct foobar : x3::parser<foobar> {
using attribute_type = std::string;
template<typename Iterator, typename Context, typename RContext, typename Attribute>
bool parse(Iterator& first, Iterator const& last, Context const& context,
RContext const& rcontext, Attribute& attr) const
{
static const std::string foobar_str = "foobar";
auto i = first;
auto j = foobar_str.begin();
while (i != last && j != foobar_str.end()) {
if (*i++ != *j++)
return false;
}
first = i;
attr = foobar_str;
return true;
};
};
const auto foo = foobar();
}
int main()
{
std::string input = "foobarfoobarfoobar";
std::vector<std::string> strings;
auto foobars = parser::foo >> parser::foo >> parser::foo;
bool success = x3::phrase_parse(input.begin(), input.end(), foobars, x3::space, strings);
if (success)
std::cout << "yes\n"; // yes for this one
else
std::cout << "no\n";
input = "foobar foobar foobar";
success = x3::phrase_parse(input.begin(), input.end(), foobars, x3::space, strings);
if (success)
std::cout << "yes\n";
else
std::cout << "no\n"; // no because of the spaces
}
You can simply apply the skipper by getting it from the context. It is up to you decide when to use it (e.g. whether post-skip is part of the behaviour), but I suppose pre-skip is implied when there is an active skipper anyways.
If you inherit from x3::parser_base, you can simply invoke
skip_over(f, l, ctx);
to do the job.
See for an example X3 parse rule doesn't compile