2012-01-31 85 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