2009-01-21 46 views
3

我的情况:我是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()); 
} 

我会更喜欢所有可打印字符分配到下一个​​3210但下面不会起作用,因为parse(...).hit == false

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

我该如何击中它?

回答

3

您可以尝试使用confix_p

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

它应该相当于Fred's response

您的代码失败的原因是因为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

3

你没有受到欢迎,因为';'由print_p匹配。试试这个:

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

谢谢,明天我会试试这个。 看来我的一方存在根本的误解。我认为解析器会尝试匹配的东西,如果可能的话,不要这么懒惰...... 你知道这个行为的术语是什么吗? – foraidt 2009-01-21 22:52:58

+0

我认为这个词是“贪婪”。见http://www.boost.org/doc/libs/1_35_0/libs/spirit/doc/faq.html#greedy_rd – 2009-01-21 22:57:40