Boost Spirit:如何计算某些字符的出现次数,然后将结果放入 AST?
Boost Spirit: how to count occurences of certain characters and then put the result in AST?
我想解析以下文本:
group RGB
group RRGB
group GBBB
group RRGGG
生成的 AST 将是一个表示每个字符计数的结构:
struct group
{
int r;
int g;
int b;
};
对于上面的输入,它将是 1,1,1
、2,1,1
、0,1,3
、2,3,0
。
我无法提供任何可以方便地对字符进行计数并强制执行其顺序的语法(GBR
应该会导致解析失败)。
有 x3::repeat
解析器,但只强制执行一定数量的字符,它的属性是一个容器。
x3::matches[a]
有bool
属性但不知道一个字符可能出现多少次
没有可以计算出现次数和 return 匹配次数的解析器。我想要像 x3::lit("group") >> count['R'] >> count['G'] >> count['B']
这样的语法,但不知道 count
应该如何定义。
现在我能想到的唯一可行的解决方案是 x3::lit("group") >> (*x3::char_['R'] >> *x3::char_['G'] >> *x3::char_['B'])[func]
,然后调用 func
只对字符串进行操作。 IMO 这不是一个干净的解决方案,它需要语义操作并创建不必要的字符串。
稍微修改"x3/directive/matches.hpp"你可以得到这样的东西:
#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{};
}}}
我想解析以下文本:
group RGB
group RRGB
group GBBB
group RRGGG
生成的 AST 将是一个表示每个字符计数的结构:
struct group
{
int r;
int g;
int b;
};
对于上面的输入,它将是 1,1,1
、2,1,1
、0,1,3
、2,3,0
。
我无法提供任何可以方便地对字符进行计数并强制执行其顺序的语法(GBR
应该会导致解析失败)。
有 x3::repeat
解析器,但只强制执行一定数量的字符,它的属性是一个容器。
x3::matches[a]
有bool
属性但不知道一个字符可能出现多少次
没有可以计算出现次数和 return 匹配次数的解析器。我想要像 x3::lit("group") >> count['R'] >> count['G'] >> count['B']
这样的语法,但不知道 count
应该如何定义。
现在我能想到的唯一可行的解决方案是 x3::lit("group") >> (*x3::char_['R'] >> *x3::char_['G'] >> *x3::char_['B'])[func]
,然后调用 func
只对字符串进行操作。 IMO 这不是一个干净的解决方案,它需要语义操作并创建不必要的字符串。
稍微修改"x3/directive/matches.hpp"你可以得到这样的东西:
#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{};
}}}