繁体   English   中英

Boost Spirit可选解析器和回溯

[英]Boost Spirit optional parser and backtracking

为什么即使没有匹配选项,此解析器也会在属性中保留'b'呢?

using namespace boost::spirit::qi;

std::string str = "abc";

auto a = char_("a");
auto b = char_("b");
qi::rule<std::string::iterator, std::string()> expr;
expr = +a >> -(b >> +a);

std::string res;

bool r = qi::parse(
        str.begin(),
        str.end(),
        expr >> lit("bc"),
        res
);

它解析成功,但是res是"ab"

如果"abac" expr解析"abac" ,则选项匹配并且属性为"aba"

"aac"相同,选项未开始匹配并且属性为"aa"

但是使用"ab" ,即使b被回溯,并且例如与下一个解析器匹配,属性还是"ab"

UPD

使用expr.name("expr"); debug(expr); 我有

<expr>
  <try>abc</try>
  <success>bc</success>
  <attributes>[[a, b]]</attributes>
</expr>

首先,使用auto变量保留表达式模板是UB ,因为它们保存对临时变量"a""b"引用[1]

改写

expr = +qi::char_("a") >> -(qi::char_("b") >> +qi::char_("a"));

或者,如果您坚持:

auto a = boost::proto::deep_copy(qi::char_("a"));
auto b = boost::proto::deep_copy(qi::char_("b"));
expr = +a >> -(b >> +a);

现在注意到在parse调用中隐藏了>> lit("bc")部分,建议您可能希望在解析失败发生时回溯到成功匹配的令牌。

那没有发生:Spirit生成PEG语法,并且总是从左到右贪婪地匹配。


在给定的样本上,即使确实发生了回溯, ab结果也不会消失,如果没有qi::hold则不会回滚对属性的影响: Live On Coliru

容器属性由ref传递,并且以前的(成功的)表达式的效果不会回滚,除非您也告诉Spirit。 这样,您可以“为所用内容付费”(因为一直复制临时文件会很昂贵)。

见例如

<a>
  <try>abc</try>
  <success>bc</success>
  <attributes>[a]</attributes>
</a>
<a>
  <try>bc</try>
  <fail/>
</a>
<b>
  <try>bc</try>
  <success>c</success>
  <attributes>[b]</attributes>
</b>
<a>
  <try>c</try>
  <fail/>
</a>
<bc>
  <try>bc</try>
  <success></success>
  <attributes>[]</attributes>
</bc>
Success: 'ab'

[1]看到这里:

这个 SO问题中引用@sehe

字符串属性是容器属性,可以通过不同的解析器子表达式将许多元素分配给它。 现在出于效率原因,Spirit不会在回溯时回滚所发出属性的值。

因此,我将可选的解析器置于保留状态,此操作已完成。

expr = +qi::char_("a") >> -(qi::hold[qi::char_("b") >> +qi::char_("a")]);

有关更多信息,请参见提到的问题并保存文档

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM