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

时间:2009-01-21 20:20:28

标签: c++ vc6 boost-spirit greedy

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

我有一行看起来像这样:

//The Description;DESCRIPTION;;

如果该行以DESCRIPTION开头,我想将文字//The 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)

如何击中它?

2 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:3)

您可以尝试使用confix_p

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

它应该等同于Fred's response

您的代码失败的原因是因为print_p 贪婪+print_p解析器将消耗字符,直到遇到输入的结尾或不可打印的字符。分号是可打印的,所以print_p声称它。您的输入已耗尽,变量已分配,匹配失败 - 您的解析器的最后一个分号无法匹配。

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

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