2014-10-03 48 views
2

爲什麼此解析器在屬性中保留'b'?即使選項不匹配?Boost Spirit可選解析器和回溯

using namespace boost::spirit::qi; 

std::string str = "abc"; 

auto a = char_("a"); 
auto b = char_("b"); 
qi::rule<std::string::iterator, std::string()> expr; 
expr = +a >> -(b >> +a); 

std::string res; 

bool r = qi::parse(
     str.begin(), 
     str.end(), 
     expr >> lit("bc"), 
     res 
); 

它解析成功,但資源是"ab"

如果僅用expr解析"abac",則選項匹配且屬性爲"aba"

"aac"相同,選項不會開始匹配,屬性爲"aa"

但與"ab",屬性是"ab",即使b回溯,並且,例如,與下一個分析器匹配。

UPD

隨着expr.name("expr");debug(expr);

<expr> 
    <try>abc</try> 
    <success>bc</success> 
    <attributes>[[a, b]]</attributes> 
</expr> 

回答

3

首先,它是UB使用auto變量來表達模板,因爲他們持有的臨時對象的引用"a""b"[1]

而是寫

expr = +qi::char_("a") >> -(qi::char_("b") >> +qi::char_("a")); 

或者,如果你堅持:

auto a = boost::proto::deep_copy(qi::char_("a")); 
auto b = boost::proto::deep_copy(qi::char_("b")); 
expr = +a >> -(b >> +a); 

現在注意到在parse呼叫>> lit("bc")部分隱藏,暗示可能是可預期的回溯到上成功地匹配令牌當分析失敗發生在路上時。

這不會發生:Spirit會生成PEG語法,並始終從左到右貪婪地匹配。


在對樣品給出ab結果,即使回溯確實發生,對屬性的影響不無qi::hold回滾:Live On Coliru

容器屬性沿着由參傳遞並且以前(成功)表達式的效果是而不是回滾,除非您也告訴Spirit。這樣,你可以「支付你使用的東西」(因爲一直複製臨時對象會花費很多)。

參見例如

<a> 
    <try>abc</try> 
    <success>bc</success> 
    <attributes>[a]</attributes> 
</a> 
<a> 
    <try>bc</try> 
    <fail/> 
</a> 
<b> 
    <try>bc</try> 
    <success>c</success> 
    <attributes>[b]</attributes> 
</b> 
<a> 
    <try>c</try> 
    <fail/> 
</a> 
<bc> 
    <try>bc</try> 
    <success></success> 
    <attributes>[]</attributes> 
</bc> 
Success: 'ab' 

[1]在這裏看到:

+0

嗯,我已經取代'auto's與規則。 – 2014-10-03 20:27:34

+0

但是,我不明白,你使用二進制減號?那是不同的語言,不是嗎? – 2014-10-03 20:28:35

+0

@MikhailCheshkov我只是注意到這個錯字。 **更新了答案。請原諒我的錯誤:/ – sehe 2014-10-03 20:34:12

2

引用從this @sehe SO質疑

的字符串的屬性是一個容器屬性和許多元件可以被 分配到它通過不同的解析器子表達式。現在對於效率的原因,Spirit不回滾發射的 屬性的回溯值。

所以,我已經把可選的解析器擱置了,它就完成了。

expr = +qi::char_("a") >> -(qi::hold[qi::char_("b") >> +qi::char_("a")]); 

欲瞭解更多信息,請參見上述問題,hold docs

+0

該信息在我的答案中是正確的。嗯。也許是因爲我沒有在那裏顯示「hold」的用法。好吧,+1(感謝您支持我的缺席) – sehe 2014-10-03 21:03:33

相關問題