我如何用精神正确解析这个?

发布于 2024-07-12 09:51:21 字数 996 浏览 11 评论 0原文

我的情况:我是 Spirit 的新手,我必须使用 VC6,因此使用 Spirit 1.6.4。

我有一行看起来像这样:

//The Description;DESCRIPTION;;

如果该行以 //The Description; 开头,我想将文本 DESCRIPTION 放入字符串中。

我有一些可行的东西,但对我来说看起来不太优雅:

vector<char> vDescription; // std::string doesn't work due to missing ::clear() in VC6's STL implementation
if(parse(chars,
    // Begin grammar
    (
       as_lower_d["//the description;"]
    >> (+~ch_p(';'))[assign(vDescription)]
    ),
    // End grammar
    space_p).hit)
{
    const string desc(vDescription.begin(), vDescription.end());
}

我更想将所有可打印字符分配给下一个 ';' 但以下内容不起作用,因为 parse( ...).hit == false

parse(chars,
        // Begin grammar
        (
           as_lower_d["//the description;"]
        >> (+print_p)[assign(vDescription)]
        >> ';'
        ),
        // End grammar
        space_p).hit)

如何让它命中?

My situation: I'm new to Spirit, I have to use VC6 and am thus using Spirit 1.6.4.

I have a line that looks like this:

//The Description;DESCRIPTION;;

I want to put the text DESCRIPTION in a string if the line starts with //The Description;.

I have something that works but looks not that elegant to me:

vector<char> vDescription; // std::string doesn't work due to missing ::clear() in VC6's STL implementation
if(parse(chars,
    // Begin grammar
    (
       as_lower_d["//the description;"]
    >> (+~ch_p(';'))[assign(vDescription)]
    ),
    // End grammar
    space_p).hit)
{
    const string desc(vDescription.begin(), vDescription.end());
}

I would much more like to assign all printable characters up to the next ';' but the following won't work because parse(...).hit == false

parse(chars,
        // Begin grammar
        (
           as_lower_d["//the description;"]
        >> (+print_p)[assign(vDescription)]
        >> ';'
        ),
        // End grammar
        space_p).hit)

How do I make it hit?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

独﹏钓一江月 2024-07-19 09:51:21

您可以尝试使用 confix_p

confix_p(as_lower_d["//the description;"],
         (+print_p)[assign(vDescription)],
         ch_p(';')
        )

它应该相当于Fred的响应

您的代码失败的原因是 print_p贪婪。 +print_p 解析器将消耗字符,直到遇到输入结尾或不可打印的字符。 分号是可打印的,因此 print_p 声明它。 您的输入耗尽,变量被分配,并且匹配失败 - 解析器的最后一个分号没有任何内容可以匹配。

Fred 的答案构造了一个新的解析器 (print_p - ';'),它匹配 print_p 所做的一切,除了分号。 “匹配除 X 之外的所有内容,然后匹配 X”是一种常见模式,因此提供了 confix_p 作为构建此类解析器的快捷方式。 文档建议使用它来解析 C 或 Pascal 风格的注释,但这不是必需的。

为了使您的代码正常工作,Spirit 需要识别出贪婪的 print_p 匹配太多,然后回溯以允许更少的匹配。 但是,尽管 Spirit 会回溯,但它不会回溯到子解析器贪婪匹配的“中间”。 它将回溯到下一个“选择点”,但你的语法没有任何选择。 请参阅详尽的回溯和贪婪Spirit 文档中的 RD

You might try using confix_p:

confix_p(as_lower_d["//the description;"],
         (+print_p)[assign(vDescription)],
         ch_p(';')
        )

It should be equivalent to Fred's response.

The reason your code fails is because print_p is greedy. The +print_p parser will consume characters until it encounters the end of the input or a non-printable character. Semicolon is printable, so print_p claims it. Your input gets exhausted, the variable is assigned, and the match fails — there's nothing left for the last semicolon of your parser to match.

Fred's answer constructs a new parser, (print_p - ';'), which matches everything print_p does, except for semicolons. "Match everything except X, and then match X" is a common pattern, so confix_p is provided as a shortcut for constructing that kind of parser. The documentation suggests using it for parsing C- or Pascal-style comments, but that's not required.

For your code to work, Spirit would need to recognize that the greedy print_p matched too much and then backtrack to allow matching less. But although Spirit will backtrack, it won't backtrack to the "middle" of what a sub-parser would otherwise greedily match. It will backtrack to the next "choice point," but your grammar doesn't have any. See Exhaustive backtracking and greedy RD in the Spirit documentation.

み格子的夏天 2024-07-19 09:51:21

你没有受到打击,因为 ';' 与 print_p 匹配。 尝试这个:

parse(chars,
    // Begin grammar
    (
       as_lower_d["//the description;"]
    >> (+(print_p-';'))[assign(vDescription)]
    >> ';'
    ),
    // End grammar
    space_p).hit)

You're not getting a hit because ';' is matched by print_p. Try this:

parse(chars,
    // Begin grammar
    (
       as_lower_d["//the description;"]
    >> (+(print_p-';'))[assign(vDescription)]
    >> ';'
    ),
    // End grammar
    space_p).hit)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文