I would like to parse the following text:
group RGB
group RRGB
group GBBB
group RRGGG
The resulting AST would be a struct that represents counts of each character:
struct group
{
int r;
int g;
int b;
};
For the inputs above it would be 1,1,1
, 2,1,1
, 0,1,3
, 2,3,0
.
I can't come with any grammar that would conveniently count characters and enforce their order (GBR
should fail the parse).
There is x3::repeat
parser but in only enfoces certain count of characters, it's attribute is a container.
x3::matches[a]
has bool
attribute but I don't know how many times a character may appear
There is no parser that would count appearance and return number of matches. I want a grammar like x3::lit("group") >> count['R'] >> count['G'] >> count['B']
, but have no idea how count
should be defined.
Right now the only working solution I can think of would be x3::lit("group") >> (*x3::char_['R'] >> *x3::char_['G'] >> *x3::char_['B'])[func]
which then calls func
that would just operate on the string. IMO this is not a clean solution and it requires semantic actions and creates unnecessary strings.
Slightly modifying "x3/directive/matches.hpp" you can get something like this:
#include <boost/spirit/home/x3/core/parser.hpp>
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
#include <boost/spirit/home/x3/support/unused.hpp>
namespace not_boost { namespace not_spirit { namespace not_x3
{
template <typename Subject>
struct count_directive : boost::spirit::x3::unary_parser<Subject, count_directive<Subject>>
{
using base_type = boost::spirit::x3::unary_parser<Subject, count_directive<Subject>>;
static bool const has_attribute = true;
using attribute_type = int;
count_directive(Subject const& subject) : base_type(subject) {}
template <typename Iterator, typename Context
, typename RContext, typename Attribute>
bool parse(Iterator& first, Iterator const& last
, Context const& context, RContext& rcontext, Attribute& attr) const
{
int count=0;
while(this->subject.parse(first, last, context, rcontext, boost::spirit::x3::unused))
{
count++;
}
boost::spirit::x3::traits::move_to(count, attr);
return true;
}
};
struct count_gen
{
template <typename Subject>
count_directive<typename boost::spirit::x3::extension::as_parser<Subject>::value_type>
operator[](Subject const& subject) const
{
return { boost::spirit::x3::as_parser(subject) };
}
};
auto const count = count_gen{};
}}}