2017-10-20 72 views
1

我試圖使用Boost 1.65.1中的Spirit X3來創建解析器。我減少了我的問題,下面的小例子用更簡單的結構:沒有默認構造函數的Boost-Spirit(X3)解析

#include <boost/config/warning_disable.hpp> 
#include <boost/spirit/home/x3.hpp> 
#include <boost/fusion/include/adapt_struct.hpp> 

#include <iostream> 
#include <vector> 

struct MyPair { 
    MyPair(int x, int y) : mx(x), my(y) {}; 
    //MyPair() {} // No default constructor - neither needed nor wanted. 
    int mx; 
    int my; 
}; 

/* 
BOOST_FUSION_ADAPT_STRUCT(
    MyPair, 
    (int, mx) 
    (int, my) 
) 
*/ 

int main() 
{ 
    using boost::spirit::x3::int_; 
    using boost::spirit::x3::parse; 

    std::vector<MyPair> pairs; 
    char const *first = "11:22,33:44,55:66", *last = first + std::strlen(first); 
    auto pair = [&](auto& ctx) { return MyPair(1, 2); }; 
    bool parsed_some = parse(first, last, ((int_ >> ':' >> int_)[pair]) % ',', pairs); 

    if (parsed_some) { 
     std::cout << "Parsed the following pairs" << std::endl; 
     for (auto& p : pairs) { 
      std::cout << p.mx << ":" << p.my << std::endl; 
     } 
    } 
    return 0; 
} 

我不想默認構造函數添加到我的類型(這裏MyPair)。如果沒有默認的構造函數,我得到了以下錯誤:

'MyPair::MyPair': no appropriate default constructor available ...\boost\utility\value_init.hpp 

但我不想改變我的結構有一個默認的構造函數。假設,我也加一個,最後一個錯誤我得到的是:

binary '=': no operator found which takes a right-hand operand of type 'int' (or there is no acceptable conversion) TestParsing ...\x3\support\traits\move_to.hpp 

但因爲我手動構造屬性的語義動作,我不明白爲什麼我需要一個融合的定義。 (注意,目前它使用硬編碼值,直到我解決這個問題,然後得到適當的值)。

如何使用Spirit X3構造沒有默認構造函數的用戶定義類型的屬性?

回答

1

想到的唯一方法是避免有一個規則/解析器完全綁定到MyPair屬性。

幸運X3是足夠的靈活性,結合反覆的容器屬性:

auto pair = x3::rule<struct pair_, std::vector<MyPair> > {} 
      = (int_ >> ':' >> int_) 
       [([&](auto& ctx) { 
        auto& attr = x3::_attr(ctx); 
        using boost::fusion::at_c; 
        return x3::_val(ctx).emplace_back(at_c<0>(attr), at_c<1>(attr)); 
       })] 
      ; 

Live On Coliru

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

struct MyPair { 
    MyPair(int x, int y) : mx(x), my(y) {}; 
    int mx; 
    int my; 
}; 

int main() 
{ 
    namespace x3 = boost::spirit::x3; 
    using x3::int_; 

    std::vector<MyPair> pairs; 
    char const *first = "11:22,33:44,55:66", *last = first + std::strlen(first); 

    auto pair = x3::rule<struct pair_, std::vector<MyPair> > {} 
       = (int_ >> ':' >> int_) 
        [([&](auto& ctx) { 
         auto& attr = x3::_attr(ctx); 
         using boost::fusion::at_c; 
         return x3::_val(ctx).emplace_back(at_c<0>(attr), at_c<1>(attr)); 
        })] 
       ; 

    bool parsed_some = parse(first, last, pair % ',', pairs); 

    if (parsed_some) { 
     std::cout << "Parsed the following pairs" << std::endl; 
     for (auto& p : pairs) { 
      std::cout << p.mx << ":" << p.my << std::endl; 
     } 
    } 
} 

打印

Parsed the following pairs 
11:22 
33:44 
55:66 
+0

感謝。但我不確定我能否應用這種方法。我想要的輸出「AST」是大多非默認可構造類型的層次結構,例如: A a(「Simple/Primitive argument」)... B b(24.8); //最低層 X x(a,c)... Y y(b); //最低+ 1層 P(x,y)//最低+2層 ......依此類推...... – senevoldsen

+0

然後你就會有精神上的困難。我會解析成中間表示並轉換它。 X3有特點使轉換「自動」 – sehe

+0

我害怕我不得不做另一箇中間表示;很多樣板。你有鏈接到一些關於如何自動化這些轉換的文檔嗎? – senevoldsen

相關問題