2012-01-31 87 views
1

我有一个输入字符串,我试图解析。它可能看起来像两者之一:解析一个字符串(用空格)但忽略空格末尾的(精神)

sys(error1, 2.3%) 
sys(error2 , 2.4%) 
sys(this error , 3%) 

请注意有时在逗号之前的空格。在我的语法(boost spirit library)中,我想分别捕获“error1”,“error2”和“this error”。

原来这里是语法我不得不抓住这一点 - 这在名称末尾吸收的空间:

name_string %= lexeme[+(char_ - ',' - '"')]; 
name_string.name("Systematic Error Name"); 

start = (lit("sys")|lit("usys")) > '(' 
    > name_string[boost::phoenix::bind(&ErrorValue::SetName, _val, _1)] > ',' 
    > errParser[boost::phoenix::bind(&ErrorValue::CopyErrorAndRelative, _val, _1)] 
    > ')'; 

我试图解决这个问题最早是:

name_string %= lexeme[*(char_ - ',' - '"') > (char_ - ',' - '"' - ' ')]; 

然而这完全失败。看起来它无法解析任何中间有空格的东西。

我对Spirit很新 - 所以也许我错过了一些简单的东西。看起来lexeme在前沿边上跳过 - 我需要在前后边做的事情。

在此先感谢您的帮助!

感谢下面的psur,我能够把答案放在一起。它不是完美的(见下文),但我想我会更新帖子给大家看它的背景和很好的格式化的:

qi::rule<Iterator, std::string(), ascii::space_type> name_word; 
qi::rule<Iterator, std::string(), ascii::space_type> name_string; 
ErrorValueParser<Iterator> errParser; 

name_word %= +(qi::char_("_a-zA-Z0-9+")); 
//name_string %= lexeme[name_word >> *(qi::hold[+(qi::char_(' ')) >> name_word])]; 

name_string %= lexeme[+(qi::char_("-_a-zA-Z0-9+")) >> *(qi::hold[+(qi::char_(' ')) >> +(qi::char_("-_a-zA-Z0-9+"))])]; 

start = (
     lit("sys")[bind(&ErrorValue::MakeCorrelated, _val)] 
     |lit("usys")[bind(&ErrorValue::MakeUncorrelated, _val)] 
     ) 
    >> '(' 
    >> name_string[bind(&ErrorValue::SetName, _val, _1)] >> *qi::lit(' ') 
    >> ',' 
    >> errParser[bind(&ErrorValue::CopyErrorAndRelative, _val, _1)] 
    >> ')'; 

这工作!它们的关键是name_string,并且在其中是qi :: hold,在此之前我并不熟悉这个操作符。这几乎就像是一个子规则:qi :: hold [...]内的所有内容都必须成功地解析它。因此,如果上面有另一个单词,它只会在一个单词之后留下一个空格。结果是,如果一个单词序列以空格结束,那么最后的空格将不会被解析!它们可以被* qi :: lit('')吸收(参见开始规则)。

有两件事情,我想弄清楚如何在这里提高:

  • 这将是很好把实际字符串解析成name_word。问题在于name_word的声明 - 当它放在name_string的定义中的适当位置时它失败。

  • 如果name_string可以包含尾部空格的解析,尽管它的返回值没有,它会更好。我想我知道该怎么做...

当/如果我找出这些,我会更新这篇文章。谢谢您的帮助!

回答

1

以下规则应该为你工作:

name_word %= +(qi::char_("_a-zA-Z0-9")); 

start %= qi::lit("sys(") 
    >> qi::lexeme[ name_word >> *(qi::hold[ +(qi::char_(' ')) >> name_word ]) ] 
    >> *qi::lit(' ') 
    >> qi::lit(',') 
    // ... 

name_word解析只有一个名字字;我认为它只包含字母,数字和下划线。

start规则qi::hold很重要。它仅在下一个是name_word时解析空间。在其他情况下,解析器将回滚并移至*qi::lit(' '),然后转为逗号。

+0

我花了一段时间才明白这一点。我并不熟悉“持有” - 这看起来很完美。我会尝试这一点,并标记答案,如果它的工作。 – Gordon 2012-02-11 23:11:52

+0

我appologize,我得到一个海湾合作委员会模板错误转储,我没有心脏尝试最初排序。我认为这个错误表明我期待qi :: lexeme的值是一个字符串,但它实际上是其他的东西。如果我这样做:'qi :: rule name_word; qi :: rule name_string;'然后对于名词我将其定义为'name_word%= +(qi :: char _(“_ a-zA-Z0-9” ))';和名称字符串作为'name_string%= qi :: lexeme [name_word >> *(qi :: hold [+(qi :: char_(''))>> name_word])];'我得到一个糟糕的海湾合作委员会转储。 – Gordon 2012-02-26 10:12:44

+0

好的,我上面的评论是不正确的... somethign其他正在导致编译器错误...正在工作... – Gordon 2012-02-26 10:19:40