2017-02-20 90 views
0

試圖學習Boost :: Spirit並想要解決c樣式標識符的一個簡單示例。下面的語法不會聲稱'incompatible_start_rule'。目標是讓這個語法返回一個字符串,而不是一個字符串向量,因爲默認屬性傳播規則會。Boost Spirit語法自定義屬性

template <typename IT> 
struct cppIdentifier : qi::grammar<IT, std::string, space_type()> 
{ 

    cppIdentifier() : cppIdentifier::base_type(start) 
    { 
     start = char_("a-zA-Z_")[boost::phoenix::push_back(_val, _1)] 
       >> *(char_("a-zA-Z0-9_")[boost::phoenix::push_back(_val, _1)]); 
    } 

    qi::rule<IT, std::string, space_type> start; 
}; 

要做到這一點我需要做些什麼?

另外請注意,我很清楚這個特定問題可能有很多替代方案,但是我對學習如何操作自定義語法的屬性類型感興趣,所以請保留這些在評論中而不是答案中。

由於提前,

回答

2

首先,你需要使用函數簽名式的模板參數指定規則的輸出屬性類型(和繼承的屬性類型,如果有的話)。而不是qi::grammar<IT, std::string, space_type()>,請嘗試qi::grammar<IT, std::string(), space_type>

其次,你並不真的需要在這裏語​​義動作 - 但如果你打算使用語法分析器,你需要lexeme[]指令:

template <typename IT> 
struct cppIdentifier : qi::grammar<IT, std::string(), qi::space_type> 
{ 
    cppIdentifier() : cppIdentifier::base_type(start) 
    { 
     start = qi::lexeme[char_("a-zA-Z_") >> *(char_("a-zA-Z0-9_"))]; 
    } 

    qi::rule<IT, std::string(), qi::space_type> start; 
}; 

最後,確保你傳遞一個兼容skipper對象到phrase_parse:

std::string s = "HELLO 123"; 

cppIdentifier < std::string::const_iterator> id; 

std::string ident; 

qi::phrase_parse(s.cbegin(), s.cend(), id, qi::space_type(), ident); 

// without lexeme[], ident becomes "HELLO123", not "HELLO" 
+1

歡迎,[標籤:boost-spirit]的[SO]標籤中的新貢獻者。非常感謝您的幫助! – sehe

+1

非常感謝!我從網站學到了很多東西,包括你的答案,所以如果我能以小的方式提供幫助,我會嘗試。我也發現我從寫自己的答案中學到很多東西。 –

+0

是的!這很有用,謝謝。顯然,我需要深入研究規則和語法模板參數。 –