提振精神可选解析器和回溯 [英] Boost Spirit optional parser and backtracking
问题描述
为什么这个解析器离开'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] 在这里看到:
- Assigning解析器自动变量
- Generating从另一种解析器前pressions 一个可变参数列表精神解析器前pressions
- boost精神V2气错误使用优化级别 相关
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.
- boost::spirit::qi duplicate parsing on the output
- Understanding Boost.spirit's string parser
- Boost spirit revert parsing
<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:
- Assigning parsers to auto variables
- Generating Spirit parser expressions from a variadic list of alternative parser expressions
- boost spirit V2 qi bug associated with optimization level
这篇关于提振精神可选解析器和回溯的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!