簡體   English   中英

Boost Spirit可選解析器和回溯

[英]Boost Spirit optional parser and backtracking

為什么即使沒有匹配選項,此解析器也會在屬性中保留'b'呢?

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
);

它解析成功,但是res是"ab"

如果"abac" expr解析"abac" ,則選項匹配並且屬性為"aba"

"aac"相同,選項未開始匹配並且屬性為"aa"

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

UPD

使用expr.name("expr"); debug(expr); 我有

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

首先,使用auto變量保留表達式模板是UB ,因為它們保存對臨時變量"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

容器屬性由ref傳遞,並且以前的(成功的)表達式的效果不會回滾,除非您也告訴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]看到這里:

這個 SO問題中引用@sehe

字符串屬性是容器屬性,可以通過不同的解析器子表達式將許多元素分配給它。 現在出於效率原因,Spirit不會在回溯時回滾所發出屬性的值。

因此,我將可選的解析器置於保留狀態,此操作已完成。

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

有關更多信息,請參見提到的問題並保存文檔

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM