2017-04-07 47 views
2

簡單的x3代碼無法編譯,因爲沒有任何內容附加到第二個ruleTest或整個解析器。即使我們把x3::omit[ruleTest]圍繞第二個ruleTest它仍然不能編譯。精神x3:本地定義的規則定義必須附帶一個屬性?

void Test(std::string const& str) { 
    auto const ruleTest = x3::rule<struct _, std::string>{} = 
     *(x3::char_ - ' ')[([](auto& ctx){x3::_val(ctx)+='x';})]; 
    x3::parse(boost::begin(str), boost::end(str), 
     ruleTest[([](auto& ctx){std::cout<<x3::_attr(ctx)<<std::endl;})] >> 
     ' ' >> 
     ruleTest 
    ); 
} 

只有當我們重視一個lambda或X3屬性::解析或BOOST_SPIRIT_DEFINE全局定義ruleTest可以解決這個問題。

void Test(std::string const& str) { 
    auto const ruleTest = x3::rule<struct _, std::string>{} = 
     *(x3::char_ - ' ')[([](auto& ctx){x3::_val(ctx)+='x';})]; 
    std::string attr; 
    x3::parse(boost::begin(str), boost::end(str), 
     ruleTest[([](auto& ctx){std::cout<<x3::_attr(ctx)<<std::endl;})] >> 
     ' ' >> 
     ruleTest, attr); 
} 

回答

1

錯誤的關鍵似乎是

test.cpp|9 col 59| error: no match for ‘operator+=’ (operand types are ‘boost::spirit::x3::unused_type’ and ‘char’) 

這是因爲編譯器看到的實際類型結合的屬性的(無)是x3::unused_type,因此語義動作不編譯。

我甚至不確定你會如何工作,因爲你不能在不存在的屬性中將字符更新爲'x'

這裏有一個建議 「修復」:

struct { 
    void operator()(std::string& s, char c) const { s += c; } 
    void operator()(...)     const { } 
} ll; 

auto const ruleTest 
    = x3::rule<struct _, std::string>{} 
    = *(x3::char_ - ' ') [([ll](auto& ctx){ ll(x3::_val(ctx), 'x');})] 
    ; 

看到它Live On Coliru

#include <boost/spirit/home/x3.hpp> 
#include <iostream> 

void Test(std::string const& str) { 
    namespace x3 = boost::spirit::x3; 

    struct { 
     void operator()(std::string& s, char c) const { s += c; } 
     void operator()(...)     const { } 
    } ll; 

    auto const ruleTest 
     = x3::rule<struct _, std::string>{} 
     = *(x3::char_ - ' ') [([ll](auto& ctx){ ll(x3::_val(ctx), 'x');})] 
     ; 

    //std::string attr; 
    auto f = begin(str), l = end(str); 
    bool ok = x3::parse(f, l, 
      ruleTest [([](auto& ctx){std::cout<<x3::_attr(ctx)<<std::endl;})] 
      >> ' ' >> ruleTest); 

    if (ok)  std::cout << "Parse success\n"; 
    else  std::cout << "Parse failed\n"; 
    if (f != l) std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n"; 
} 

int main() { 
    Test("abc def"); 
} 
+0

偉大的答案!謝謝。但爲什麼全局定義的規則沒有這個問題? – Han

+1

我其實不太確定我自己。很顯然,DEFINE/DECLARE宏對於類型防火牆有一些潛力,但我不太確定編譯器如果通過機制看到它是否是本地的。想想看,我不認爲'DECLARE'分配給'rule <>'實例,留下一個使用'parse_rule <>'特化的「存根」。這會「強制」屬性類型。而一旦定義被賦值,它就不會使用'parse_rule <>'方法[...]。有一天需要學習更多。 – sehe

相關問題