> -(*char_("a-zA-Z_-6ren">
gpt4 book ai didi

c++ - Boost Spirit Qi 解析器不消耗整个字符串表达式?

转载 作者:搜寻专家 更新时间:2023-10-31 01:05:22 26 4
gpt4 key购买 nike

假设我有以下规则:

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

由于跟踪显示标识符已正确解析并设置了属性,但 skipper 再次在字符串的第一个字符后开始一个字符:

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

我已经尝试在词素表达式中使用 as_string 但没有帮助。

最佳答案

我不明白为什么要使表达式复杂化。你能试试吗

identifier %= 
char_("a-zA-Z")
>> *char_("a-zA-Z_0-9")
;

qi::rule<Iterator, std::string()> identifier;

这是你能得到的最标准的表达方式。即使您不想允许以 _ 结尾的标识符,我也很确定您不希望这样的尾随 _ 被解析为“下一个标记” .在这种情况下,我会在解析后添加验证。

更新评论:

分析如下:

  • 首先:-(*x) 是一个危险信号。它永远不是一个有用的模式,因为 *x 已经匹配了一个空序列,你不能让它“更可选”

    (in fact, if *x was made to allow partial backtracking as in regular expression, you'd likely have seen exponential performance or even infite runtime; "luckily", *x is always greedy in Spirit Qi).

这确实有助于你的错误。让我们在 OP 中查看第 1、2、3 行的解析器表达式。

  • 首先,第 1 行匹配 T
  • 第二行最初贪婪地匹配his_is_a_valid123_Identifier
  • 但这不能满足第三行,所以 -(...) 开始执行,第一行之后的所有内容都回溯。
  • 然而:气

    • 确实回溯光标(当前输入迭代器)但是
    • 不会默认回滚对容器属性的更改。

    是的。你猜到了。 std::string 是容器属性。

所以你最终得到的是长度为 1 的成功匹配和属性中失败的可选序列的剩余部分。

关于如何解决此类回溯问题的其他一些背景资料:

关于c++ - Boost Spirit Qi 解析器不消耗整个字符串表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22638679/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com