2015-10-25 57 views
1

我在過去的幾個月中經常使用spirit::qi。但是,這次我得到了一個段錯誤,我真的無法理解。瑣碎靈魂分析器的分段錯誤

我已經將它減少到極小的測試用例,語法定義是12行代碼。

這種感覺很像earlier question,但在那裏的解決方案,將.alias()添加到一些終端,以便qi不復制它們,似乎並沒有解決這個問題。

我擔心這裏有一些基本的東西我不知道,因爲我已經設法讓語法更加複雜,而不是完全按照我期望的方式進行測試。

我現在唯一發生的事情是,也許氣只是不喜歡主語法返回類型是一個提升變體?我不知道我以前是否做過任何語法。我想我會在接下來測試這個,但老實說,我一直在旋轉我的車輪擺弄這樣的事情一段時間。

我可以確認,如果設置mod_規則的行被註釋掉了,那麼不會發生段錯誤,並且程序正常運行到完成。

編輯:實際上,即使刪除了所有語法屬性,也會發生段錯誤。

#define BOOST_SPIRIT_USE_PHOENIX_V3 
#include <boost/spirit/include/qi.hpp> 
#include <iostream> 

typedef unsigned int uint; 

namespace qi = boost::spirit::qi; 

/*** 
* Grammar 
*/ 
template <typename Iterator> 
struct op_grammar : qi::grammar<Iterator> { 
    qi::rule<Iterator> constant_; 
    qi::rule<Iterator> mod_; 
    qi::rule<Iterator> expr_; 

    op_grammar() : op_grammar::base_type(expr_) { 
    constant_ = qi::uint_; 
    expr_ = mod_ | constant_; 
    mod_ = expr_ >> qi::lit('%') >> expr_; 
    } 
}; 

/*** 
* Test 
*/ 
int main() { 
// std::string str{"n % 2"}; 
    std::string str{"2"}; 

    typedef std::string::const_iterator str_it; 
    str_it it = str.begin(); 
    str_it end = str.end(); 
    op_grammar<str_it> grammar; 

    if (qi::parse(it, end, grammar) && it == end) { 
    std::cerr << "Good\n"; 
    } else { 
    std::cerr << "Bad\n"; 
    } 
} 

回答

1

其實,我想通了......

的問題是,作爲寫,語法是有缺陷的,沒有辦法,它可以被解析。因爲expr_的第一個非終端是mod_,而mod_的第一個非終結終端是expr_,所以甚至沒有辦法開始弄清楚如何解析它們中的任何一個,這是循環的。

語法可以通過將mod_的第一個expr_更改爲constant_,然後按預期工作來修復。

我會在這裏留下這個答案我猜是因爲這個問題已經得到了投票,但可能我應該刪除問題,不知道。

+1

該術語是「左遞歸」。 PEG不支持左遞歸。你不得不像你所描述的那樣對左遞歸進行反駁 – sehe