为什么此解析器会在属性中保留'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"
。
如果仅使用expr解析"abac"
,则匹配选项且属性为"aba"
。
与"aac"
相同,选项不会开始匹配,属性为"aa"
。
但是使用"ab"
,属性为"ab"
,即使b得到回溯,并且,例如,与下一个解析器匹配。
UPD
expr.name("expr");
和debug(expr);
我得到了
<expr>
<try>abc</try>
<success>bc</success>
<attributes>[[a, b]]</attributes>
</expr>
答案 0 :(得分:3)
首先,它UB使用auto
变量来保留表达式模板,因为它们包含对临时值"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);
现在注意到隐藏在>> lit("bc")
电话中的parse
部分,建议您可以预期,当解析失败发生时,回溯到成功匹配的令牌。
这并不会发生:Spirit会生成PEG语法,并且总是从左到右贪婪地匹配。
对于给定的示例,ab
结果,即使回溯发生,在没有qi::hold
的情况下也不会回滚对该属性的影响: {{ 3}} 强>
容器属性由ref传递,之前(成功)表达式的效果是 不 回滚,除非您也告诉Spirit。通过这种方式,您可以为您使用的内容付费#34; (因为复制临时工作总是很昂贵)。
参见例如
<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] 见这里:
答案 1 :(得分:2)