问题描述
我正在阅读 Boost X3快速入门教程,并注意到线
I'm reading the Boost X3 Quick Start tutorial and noticed the line
现在,我不禁想知道eps_that_might_fail
在解析后的输入的一部分上进行某种语义/后分析是否有用,这可能会失败,使内部具有某种检查的局部性语法.
Now I can't help but wonder if an eps_that_might_fail
would be useful to do some sort of semantic/post analysis on a part of the parsed input, which could fail, to have some sort of locality of the check inside the grammar.
是否存在可能失败的eps
,使用此结构进行额外的输入验证是否是个好主意?
Is there a might-fail eps
, and is it a good idea to do extra input verification using this construct?
一个我想传达的可怕例子:
A terrible example of what I'm trying to convey:
int_ >> eps_might_fail[is_prime]
如果我没记错的话,这只会解析质数,并允许完整的解析器在期望质数的位置失败.
This will only parse prime numbers, if I'm not mistaken, and allow for the full parser to fail at the point where it expects a prime number.
推荐答案
语义操作是为此目的而设计的.
Semantic actions are intended for this.
最自然的例子是
qi::int_ [ qi::_pass = is_prime(qi::_1) ]
请务必在存在语义动作的情况下使用%=
规则分配,因为如果没有规则分配,语义动作将禁用自动属性传播.
Be sure to use %=
rule assignment in the presence of semantic actions, because without it, semantic actions disable automatic attribute propagation.
显然,您也可以更加冗长,写
You could, obviously, also be more verbose, and write
qi::int_ >> qi::eps(is_prime(qi::_val))
如您所见,引用的文档略微不完整:eps
已经可以接受一个参数,在这种情况下,懒惰的参与者is_prime(qi::_val)
可以确定是否成功执行失败.
As you can see, that quoted documentation is slightly incomplete: eps
can already take a parameter, in this case the lazy actor is_prime(qi::_val)
, that determines whether it succeeds of fails.
在Spirit X3中,除了X3不与Phoenix集成之外,都应用相同的机制.这意味着两件事:
In Spirit X3 the same mechanism applies, except that X3 doesn't integrate with Phoenix. This means two things:
- 从正面来看,我们可以仅使用核心语言功能(lambda)进行语义操作,从而使学习曲线不太陡峭
- 不利的一面是,
x3::eps
的1个参数版本没有一个懒惰的演员
- on the up-side, we can just use core language features (lambdas) for semantic actions, making the learning curve less steep
- on the downside, there's no 1-argument version of
x3::eps
that takes a lazy actor
这是X3的演示程序:
#include <boost/spirit/home/x3.hpp>
namespace parser {
using namespace boost::spirit::x3;
auto is_ltua = [](auto& ctx) {
_pass(ctx) = 0 == (_attr(ctx) % 42);
};
auto start = int_ [ is_ltua ];
}
#include <iostream>
int main() {
for (std::string const txt : { "43", "42", "84", "85" }) {
int data;
if (parse(txt.begin(), txt.end(), parser::start, data))
std::cout << "Parsed " << data << "\n";
else
std::cout << "Parse failed (" << txt << ")\n";
}
}
打印
Parse failed (43)
Parsed 42
Parsed 84
Parse failed (85)
这篇关于可能因“初始化后"失败的eps解析器.可能会失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!