假设我有以下规则:
identifier %=
lexeme[
char_("a-zA-Z")
>> -(*char_("a-zA-Z_0-9")
>> char_("a-zA-Z0-9"))
]
;
qi::rule<Iterator, std::string(), Skipper> identifier;
以及以下输入:
// identifier
This_is_a_valid123_Identifier
当跟踪显示标识符被正确解析并且属性已设置但是队长再次在字符串的第一个字符后面开始一个字符:
<identifier>
<try>This_is_a_valid123_I</try>
<skip>
<try>This_is_a_valid123_I</try>
<emptylines>
<try>This_is_a_valid123_I</try>
<fail/>
</emptylines>
<comment>
<try>This_is_a_valid123_I</try>
<fail/>
</comment>
<fail/>
</skip>
<success>his_is_a_valid123_Id</success>
<attributes>[[T, h, i, s, _, i, s, _, a, _, v, a, l, i, d, 1, 2, 3, _, I, d, e, n, t, i, f, i, e, r]]</attributes>
</identifier>
<skip>
<try>his_is_a_valid123_Id</try>
<emptylines>
<try>his_is_a_valid123_Id</try>
<fail/>
</emptylines>
<comment>
<try>his_is_a_valid123_Id</try>
<fail/>
</comment>
<fail/>
</skip>
我已经尝试在lexeme表达式中使用as_string,但没有帮助。
答案 0 :(得分:4)
我不明白为什么你使表达复杂化。你能试试吗
identifier %=
char_("a-zA-Z")
>> *char_("a-zA-Z_0-9")
;
qi::rule<Iterator, std::string()> identifier;
这是您可以获得的最标准的表达方式。即使您不希望允许以_
结尾的标识符,我也非常确定您不希望将这样的尾随_
解析为“下一个标记”。在这种情况下,我只需在解析后添加验证。
更新发表评论:
以下是分析:
首先关闭:-(*x)
是 红旗 。它永远不是一个有用的模式,因为*x
已匹配空序列,你不能使它“更可选”
(事实上,如果
*x
允许部分回溯,就像在正则表达式中一样,你可能已经看到指数性能甚至是运行时运行;“幸运”,*x
是在灵气中总是贪心)。
这确实有助于你的错误。让我们将OP中的解析器表达式看作第1,2,3行。
T
。 his_is_a_valid123_Identifier
。 -(...)
开始了,第一行之后的所有内容都被撤回了。 然而 :Qi
是。你猜到了。 std::string
是容器属性。
所以你最终得到的是长度为1的成功匹配,以及属性中失败的可选序列的剩余部分。
其他一些关于如何解决这种回溯问题的背景资料: