通过自定义属性解析增强 Spirit 规则

发布于 2024-09-07 13:58:02 字数 702 浏览 1 评论 0原文

我正在编写一个 Boost Spirit 语法来将文本解析为这些结构的向量:

struct Pair
{
    double a;
    double b;
};

BOOST_FUSION_ADAPT_STRUCT(
    Pair,
    (double, a)
    (double, a)
)

这个语法有一个这样的规则:

qi::rule<Iterator, Pair()> pairSequence;

然而,pairSequence 的实际语法是这样的:

double_ % separator

我希望这个语法生成一个 < code>Pair 其中 a 等于 double,b 等于某个常量。我想做这样的事情:

pairSequence = double_[_val = Pair(_1, DEFAULT_B)] % separator;

当然,上面的内容不能编译。我尝试向 Pair 添加构造函数,但仍然遇到编译错误(没有匹配的函数可调用 'Pair::Pair(const boost::phoenix::actor >&,双)')。

I am writing a Boost Spirit grammar to parse text into a vector of these structs:

struct Pair
{
    double a;
    double b;
};

BOOST_FUSION_ADAPT_STRUCT(
    Pair,
    (double, a)
    (double, a)
)

This grammar has a rule like this:

qi::rule<Iterator, Pair()> pairSequence;

However, the actual grammar of pairSequence is this:

double_ % separator

I want this grammar to produce a Pair with a equal to the double and b equal to some constant. I want to do something like this:

pairSequence = double_[_val = Pair(_1, DEFAULT_B)] % separator;

The above does not compile, of course. I tried adding a constructor to Pair, but I still get compile errors (no matching function for call to 'Pair::Pair(const boost::phoenix::actor >&, double)').

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

为人所爱 2024-09-14 13:58:02

首先,pairSequence 的签名必须是:

qi::rule<Iterator, std::vector<Pair>()> pairSequence; 

因为列表运算符公开 std::vector作为其属性。

从语义操作内部调用的所有函数都必须是“惰性”的,因此您需要利用 phoenix:

namespace phx = boost::phoenix;

pairSequence = 
    double_[
        phx::push_back(_val, 
            phx::construct<Pair>(_1, phx::val(DEFAULT_B))
        )
    ] % separator
; 

另一种可能性是向 Pair 添加一个(非显式)构造函数:

struct Pair         
{         
    Pair(double a) : a(a), b(DEFAULT_B) {}

    double a;         
    double b;         
};         

这可以简化语法:

pairSequence = double_ % separator; 

并且完全依赖于Spirit内置的属性传播规则。

顺便说一句,要使这一切发挥作用,您不需要将 Pair 改编为 Fusion 序列。

First of all, the signature of pairSequence needs to be:

qi::rule<Iterator, std::vector<Pair>()> pairSequence; 

as the list operator exposes a std::vector<Pair> as its attribute.

All functions called from inside a semantic action have to be 'lazy', so you need to utilize phoenix:

namespace phx = boost::phoenix;

pairSequence = 
    double_[
        phx::push_back(_val, 
            phx::construct<Pair>(_1, phx::val(DEFAULT_B))
        )
    ] % separator
; 

Another possibility would be to add a (non-explicit) constructor to Pair:

struct Pair         
{         
    Pair(double a) : a(a), b(DEFAULT_B) {}

    double a;         
    double b;         
};         

which allows to simplify the grammar:

pairSequence = double_ % separator; 

and completely relies on Spirit's built-in attribute propagation rules.

BTW, for any of this to work, you don't need to adapt Pair as a Fusion sequence.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文