2017-10-20 14 views
1

私は、ブースト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)私のタイプにデフォルトコンストラクタを追加する必要はありません。デフォルトのコンストラクタを使用しないと、次のエラーが発生します。

しかし、私の構造体にデフォルトのコンストラクタがあるように変更したくありません。私は1つを追加する、と仮定し、私が手に最後のエラーは、次のとおりです。

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( "単純/プリミティブ引数")... B b(24.8); //最下位層 X x(a、c).... Y y(b); //最下位+ 1層 P(x、y)//最下位+ 2層 ...など..... ..... – senevoldsen

+0

あなたは精神で苦労するつもりです。私は中間表現を解析し、それを変換するでしょう。 X3は変換を「自動」にする特性を持っています – sehe

+0

私は別の中間表現を作らなければならないのではないかと心配しました。ボイラープレートがたくさんあります。これらの変換を自動化する方法に関するいくつかのドキュメントへのリンクがありますか? – senevoldsen

関連する問題