提振精神可选解析器和回溯 [英] Boost Spirit optional parser and backtracking

查看:151
本文介绍了提振精神可选解析器和回溯的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么这个解析器离开'B'中的属性,即使不匹配选项?

 使用空间boost ::精神::补气;性病::字符串str =ABC;自动一个=炭_(一);
经销商B =炭_(B);
齐::规则<的std ::字符串::迭代器,标准::字符串()> EXPR;
EXPR = + A>> - (B个;&GT +一);标准::字符串资源;BOOL R =气::解析(
        str.begin(),
        str.end(),
        EXPR>>点亮(BC),
        水库
);

它成功地解析,但资源是AB

如果解析ABAC与EXPR独自一人,选择匹配和属性是ABA

AAC,选项不会开始匹配,属性是AA。<相同/ p>

但随着AB,属性是AB,即使B获得了退步,而且,正如例如,下一解析器匹配。

UPD

使用 expr.name(EXPR); 调试(表达式);

 &LT;&expr的GT;
  &LT;尽量&GT; ABC&LT; /&尝试GT;
  &LT;成功与GT; BC&LT; /成功&GT;
  &所述;属性&GT; [A,B]]下; /属性&GT;
&LT; / EXPR&GT;


解决方案

首先,这是 UB 使用汽车变量来保持前pression模板,因为他们持有的临时引用b [1]

而不是写

  EXPR = +补气::字符_(A)&GT;&GT; - (气::字符_(B)&GT;&GT; +补气::字符_(A));

或者,如果你坚持:

 汽车A =的boost ::原:: DEEP_COPY(气::字符_(A));
自动B =提振::原:: DEEP_COPY(气::字符_(B));
EXPR = + A&GT;&GT; - (B个;&GT +一);


现在注意到了&GT;&GT;点亮(BC)部分躲在解析电话,暗示可能是可预期的回溯,当解析出现故障情况下就成功地匹配令牌路。

这不会发生:精神产生PEG语法,并且总是贪婪地从左至右匹配。


在给定的, AB 结果样品,即使回溯的发生时,该属性的影响不无<$回滚C $ C>齐::持有 住在Coliru

容器的属性沿着由参过去了,previous的效果(成功)前pressions为回滚,除非你告诉精神太。通过这种方式,可以通过支付你用什么(如复制临时变量所有的时间将是昂贵的)。

请参阅例如

 &LT; A&GT;
  &LT;尽量&GT; ABC&LT; /&尝试GT;
  &LT;成功与GT; BC&LT; /成功&GT;
  &所述;属性&GT [一种]与下; /属性&GT;
&所述; / A&GT;
&LT; A&GT;
  &LT;尽量&GT; BC&LT; /&尝试GT;
  &LT;失败/&GT;
&所述; / A&GT;
&LT; B&GT;
  &LT;尽量&GT; BC&LT; /&尝试GT;
  &LT;成功与GT; C&LT; /成功&GT;
  &LT;&属性GT; [B] LT; /属性&GT;
&LT; / B&GT;
&LT; A&GT;
  &LT;尽量&GT; C&LT; /&尝试GT;
  &LT;失败/&GT;
&所述; / A&GT;
&LT; BC&GT;
  &LT;尽量&GT; BC&LT; /&尝试GT;
  &LT;成功与GT;&LT; /成功&GT;
  &LT;&属性GT;&LT; /属性&GT;
&LT; / BC&GT;
成功:'AB'


[1] 在这里看到:

Why this parser leave 'b' in attributes, even if option wasn't matched?

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
);

It parses successfully, but res is "ab".

If parse "abac" with expr alone, option is matched and attribute is "aba".

Same with "aac", option doesn't start to match and attribute is "aa".

But with "ab", attribute is "ab", even though b gets backtracked, and, as in example, matched with next parser.

UPD

With expr.name("expr"); and debug(expr); I got

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

解决方案

Firstly, it's UB to use the auto variables to keep the expression templates, because they hold references to the temporaries "a" and "b" [1].

Instead write

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

or, if you insist:

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


Now noticing the >> lit("bc") part hiding in the parse call, suggests you may expect backtracking to on succesfully matched tokens when a parse failure happens down the road.

That doesn't happen: Spirit generates PEG grammars, and always greedily matches from left to right.


On to the sample given, ab results, even though backtracking does occur, the effects on the attribute are not rolled back without qi::hold: Live On Coliru

Container attributes are passed along by ref and the effects of previous (successful) expressions is not rolled back, unless you tell Spirit too. This way, you can "pay for what you use" (as copying temporaries all the time would be costly).

See e.g.

<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] see here:

这篇关于提振精神可选解析器和回溯的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆