2015-12-10 35 views
2

Michael Caisse對Spirit X3發表了演講:https://www.youtube.com/watch?v=xSBWklPLRvw。我試圖將演示文稿轉錄爲工作代碼,但是我有編譯錯誤,其中包括「No viable overloaded'='」和「沒有與'move_to'匹配的函數調用。正確定義我phrase_parse(最後一行)?是否有任何明顯的錯誤?編譯錯誤C++ Spirit X3沒有可行的重載=,沒有與調用move_to的匹配函數

#include <boost/config/warning_disable.hpp> 
#include <boost/spirit/home/x3.hpp> 
#include <boost/spirit/home/x3/support/ast/variant.hpp> 
#include <boost/fusion/include/adapt_struct.hpp> 
#include <boost/fusion/include/std_pair.hpp> 
#include <boost/fusion/include/io.hpp> 
#include <boost/container/stable_vector.hpp>  

#include <iostream> 
#include <iterator> 
#include <fstream> 
#include <string> 
#include <map>  

namespace client { namespace ast 
    { 
     namespace x3 = boost::spirit::x3; 

     using string_t = std::string; 
     using double_t = double; 
     using float_t = double; 
     using int_t = int64_t; 
     using bool_t = bool; 
     struct null_t {}; 

     class value; 

     using object_t = std::map<std::string, value>; 
     using object_member_t = object_t::value_type; 
     using array_t = boost::container::stable_vector<value>; 

     class value : public x3::variant<null_t, bool_t, string_t, int_t, double_t, object_t, array_t> 
     { 
     public: 
      using value_type = value; 
      using base_type::base_type; 
      using base_type::operator=; 
      value(null_t val = null_t{}) : base_type(val) {} 
      value(char const* val)  : base_type(string_t(val)) {} 

      template<typename T> 
      value(T val, typename std::enable_if<std::is_floating_point<T>::value>::type) : base_type(double_t{val}) {} 

      template<typename T> 
      value(T val, typename std::enable_if<std::is_integral<T>::value::type>) : base_type(int_t{val}) {} 

     }; 

     struct json_class; 
     using json_type = x3::rule<json_class, value>; 
     json_type const json = "json"; 
     BOOST_SPIRIT_DECLARE(json_type); 

     // identifier_class id 
     // identifier_type type 
     // identifier_def rule def 
     // identifier  the rule 

     struct value_class; 
     struct object_class; 
     struct member_pair_class; 
     struct array_class; 

     using value_type = x3::rule<value_class, value>; 
     using object_type = x3::rule<object_class, object_t>; 
     using member_pair_type = x3::rule<member_pair_class, object_member_t>; 
     using array_type = x3::rule<array_class, array_t>; 

     value_type const value = "value"; 
     object_type const object = "object"; 
     member_pair_type const member_pair = "member_pair"; 
     array_type const array = "array"; 

     auto const append = [](auto& ctx){ _val(ctx) += _attr(ctx); }; 

     using uchar = unsigned char; 

     x3::uint_parser<uchar, 16, 4, 4> const hex4 = {}; 

     auto push_esc = [](auto& ctx) 
     { 
      auto& utf8 = _val(ctx); 
      switch (_attr(ctx)) 
      { 
       case '"' : utf8 += '"'; break; 
       case '\\': utf8 += '\\'; break; 
       case '/' : utf8 += '/'; break; 
       case 'b' : utf8 += '\b'; break; 
       case 'f' : utf8 += '\f'; break; 
       case 'n' : utf8 += '\n'; break; 
       case 'r' : utf8 += '\r'; break; 
       case 't' : utf8 += '\t'; break; 
      } 
     }; 

     auto push_utf8 = [](auto& ctx) 
     { 
      typedef std::back_insert_iterator<std::string> insert_iter; 
      insert_iter out_iter(_val(ctx)); 
      boost::utf8_output_iterator<insert_iter> utf8_iter(out_iter); 
      *utf8_iter++ = _attr(ctx); 
     }; 

     auto const escape = ('u' > hex4)   [push_utf8] 
          | x3::char_("\"\\/bfnrt") [push_esc]; 

     auto const char_esc = '\\' > escape; 

     auto const double_quoted = x3::lexeme[ '"' > *(char_esc) | (x3::char_("\x20\x21\x23-\x5b\x5d\x7e")) [append] > '"' ]; 

     struct unicode_string_class; 
     using unicode_string_type = x3::rule<unicode_string_class, std::string>; 
     unicode_string_type const unicode_string = "unicode_string"; 
     auto const unicode_string_def = double_quoted; 
     BOOST_SPIRIT_DEFINE(unicode_string);  

     auto const null_value = x3::lit("null") >> x3::attr(null_t{}); 
     x3::int_parser<int64_t> const int_ = {}; 
     x3::ascii::bool_type const bool_value = {}; 

     auto const object_def = x3::lit('{') >> -(member_pair % ',') >> x3::lit('}');  

     auto const member_pair_def = unicode_string >> ':' >> value; 

     auto const array_def = x3::lit('[') >> -(value % ',') >> x3::lit(']'); 

     auto const value_def = null_value | bool_value | object | array | unicode_string 
          | x3::lexeme[!('+' | (-x3::lit('-') >> '0' >> x3::digit)) >> x3::int_ >> !x3::char_(".eE")] 
          | x3::lexeme[!('+' | (-x3::lit('-') >> '0' >> x3::digit)) >> x3::double_ ]; 

     BOOST_SPIRIT_DEFINE(value, object, member_pair, array); 
    } 
}  

int main(int argc, char **argv) 
{ 

    namespace x3 = boost::spirit::x3; 

    std::string storage; // We will read the contents here.  

    using boost::spirit::x3::ascii::space; 
    std::string::const_iterator iter = storage.begin(); 
    std::string::const_iterator iter_end = storage.end(); 

    client::ast::object_t o; 
    auto const grammar = client::ast::value; 

    bool r = phrase_parse(iter, iter_end, grammar, space, o); 
} 
+0

https://www.livecoding.tv/sehe/尋找 – sehe

+0

我相信,代碼的版本也最多在github:https://github.com/cierelabs/json_spirit(我在回答問題時沒有使用它,請參閱[記錄的直播流](https://www.livecoding.tv/video/fixing-spirit-x3-json-parser-part-1)和[part 2](https://www.livecoding.tv/video/fixing-spirit-x3-json-parser-part-2)) – sehe

+0

github上的自述文件提到了Spirit 2,代碼沒有出現x3頭文件。我把它放在XCode中,它編譯並且似乎完美工作。當我回來時,我會給予適當的回顧。謝謝! –

回答

4

好吧,我不得不化解了不少錯誤/怪癖。

我熨燙的部分已經清理工作事情我通常會做不同的這裏的工作結果:

Live On Coliru

#define BOOST_SPIRIT_X3_DEBUG 
#include <iostream> 
#include <boost/config/warning_disable.hpp> 
#include <boost/spirit/home/x3.hpp> 
#include <boost/spirit/home/x3/support/ast/variant.hpp> 
#include <boost/fusion/include/adapt_struct.hpp> 
#include <boost/fusion/include/std_pair.hpp> 
#include <boost/fusion/include/io.hpp> 
#include <boost/container/stable_vector.hpp>  

#include <iterator> 
#include <fstream> 
#include <string> 
#include <map>  

namespace client { 
    namespace x3 = boost::spirit::x3; 

    namespace ast 
    { 
     using string_t = std::string; 
     using double_t = double; 
     using float_t = double; 
     using int_t = int64_t; 
     using bool_t = bool; 
     struct null_t {}; 

     class value; 

     using object_t  = std::map<std::string, value>; 
     using object_member_t = object_t::value_type; 
     using member_pair_t = std::pair<object_t::key_type, object_t::mapped_type>; 
     using array_t   = boost::container::stable_vector<value>; 

     class value : public x3::variant<null_t, bool_t, string_t, int_t, double_t, object_t, array_t> 
     { 
     public: 
      using value_type = value; 
      using base_type::base_type; 
      using base_type::operator=; 
      value(null_t val = null_t{}) : base_type(val) {} 
      value(char const* val)  : base_type(string_t(val)) {} 

      template<typename T> 
      value(T val, typename std::enable_if<std::is_floating_point<T>::value>::type) : base_type(double_t{val}) {} 

      template<typename T> 
      value(T val, typename std::enable_if<std::is_integral<T>::value::type>) : base_type(int_t{val}) {} 

     }; 

    } 

    namespace parser 
    { 
     auto const append = [](auto& ctx){ x3::_val(ctx) += x3::_attr(ctx); }; 

     using uchar = unsigned char; 

     x3::uint_parser<uchar, 16, 4, 4> const hex4 = {}; 

     auto push_esc = [](auto& ctx) { 
      auto& utf8 = x3::_val(ctx); 
      switch (x3::_attr(ctx)) 
      { 
       case '"' : utf8 += '"'; break; 
       case '\\': utf8 += '\\'; break; 
       case '/' : utf8 += '/'; break; 
       case 'b' : utf8 += '\b'; break; 
       case 'f' : utf8 += '\f'; break; 
       case 'n' : utf8 += '\n'; break; 
       case 'r' : utf8 += '\r'; break; 
       case 't' : utf8 += '\t'; break; 
      } 
     }; 

     auto push_utf8 = [](auto& ctx) { 
      typedef std::back_insert_iterator<std::string> insert_iter; 
      insert_iter out_iter(x3::_val(ctx)); 
      boost::utf8_output_iterator<insert_iter> utf8_iter(out_iter); 
      *utf8_iter++ = x3::_attr(ctx); 
     }; 

     auto const escape = ('u' > hex4)   [push_utf8] 
          | x3::char_("\"\\/bfnrt") [push_esc]; 

     auto const char_esc = '\\' > escape; 

     auto const double_quoted = x3::lexeme[ 
          '"' > *(char_esc | (x3::char_("\x20\x21\x23-\x5b\x5d-\x7e") [append])) > '"' 
         ]; 

     auto const unicode_string 
         = x3::rule<struct unicode_string_class, std::string> { "unicode_string" } 
         = double_quoted; 

     auto const null_value = x3::lit("null") >> x3::attr(ast::null_t{}); 

     x3::ascii::bool_type const bool_value = {}; 

     using value_type = x3::rule<struct value_class, ast::value>; 
     static value_type const value = "value"; 

     auto const member_pair = x3::rule<struct member_pair_class, ast::member_pair_t> { "member_pair" } 
          = unicode_string >> ':' >> value; 

     auto const object = x3::rule<struct object_class, ast::object_t> { "object" } 
          = x3::lit('{') >> -(member_pair % ',') >> x3::lit('}');  

     auto const array = x3::rule<struct array_class, ast::array_t> { "array" } 
         = x3::lit('[') >> -(value % ',') >> x3::lit(']'); 

     x3::real_parser<double, x3::strict_real_policies<double> > const double_ = {}; 
     x3::int_parser<int64_t> const int_          = {}; 

     auto const value_def = null_value | bool_value | object | array | unicode_string | double_ | int_ ; 

     BOOST_SPIRIT_DEFINE(value) 

     auto const json = x3::skip(x3::ascii::space) [ value ]; 
    } 
}  

int main() 
{ 
    std::string storage = R"({ "check": [ 1,2,3, null, true ], "more": { "nested" : "values" } })"; 

    client::ast::value o; 
    return parse(storage.begin(), storage.end(), client::parser::json, o)? 0 : 255; 
} 

對外輸出:

<value> 
<try>{ "check": [ 1,2,3, </try> 
<object> 
    <try>{ "check": [ 1,2,3, </try> 
    <member_pair> 
    <try> "check": [ 1,2,3, n</try> 
    <unicode_string> 
     <try> "check": [ 1,2,3, n</try> 
     <success>: [ 1,2,3, null, tru</success> 
     <attributes>[c, h, e, c, k]</attributes> 
    </unicode_string> 
    <value> 
     <try> [ 1,2,3, null, true</try> 
     <object> 
     <try>[ 1,2,3, null, true </try> 
     <fail/> 
     </object> 
     <array> 
     <try>[ 1,2,3, null, true </try> 
     <value> 
      <try> 1,2,3, null, true ]</try> 
      <object> 
      <try>1,2,3, null, true ],</try> 
      <fail/> 
      </object> 
      <array> 
      <try>1,2,3, null, true ],</try> 
      <fail/> 
      </array> 
      <unicode_string> 
      <try>1,2,3, null, true ],</try> 
      <fail/> 
      </unicode_string> 
      <success>,2,3, null, true ], </success> 
      <attributes>1</attributes> 
     </value> 
     <value> 
      <try>2,3, null, true ], "</try> 
      <object> 
      <try>2,3, null, true ], "</try> 
      <fail/> 
      </object> 
      <array> 
      <try>2,3, null, true ], "</try> 
      <fail/> 
      </array> 
      <unicode_string> 
      <try>2,3, null, true ], "</try> 
      <fail/> 
      </unicode_string> 
      <success>,3, null, true ], "m</success> 
      <attributes>2</attributes> 
     </value> 
     <value> 
      <try>3, null, true ], "mo</try> 
      <object> 
      <try>3, null, true ], "mo</try> 
      <fail/> 
      </object> 
      <array> 
      <try>3, null, true ], "mo</try> 
      <fail/> 
      </array> 
      <unicode_string> 
      <try>3, null, true ], "mo</try> 
      <fail/> 
      </unicode_string> 
      <success>, null, true ], "mor</success> 
      <attributes>3</attributes> 
     </value> 
     <value> 
      <try> null, true ], "more</try> 
      <success>, true ], "more": { </success> 
      <attributes></attributes> 
     </value> 
     <value> 
      <try> true ], "more": { "</try> 
      <success> ], "more": { "neste</success> 
      <attributes>1</attributes> 
     </value> 
     <success>, "more": { "nested"</success> 
     <attributes>[1, 2, 3, , 1]</attributes> 
     </array> 
     <success>, "more": { "nested"</success> 
     <attributes>[1, 2, 3, , 1]</attributes> 
    </value> 
    <success>, "more": { "nested"</success> 
    <attributes>[[c, h, e, c, k], [1, 2, 3, , 1]]</attributes> 
    </member_pair> 
    <member_pair> 
    <try> "more": { "nested" </try> 
    <unicode_string> 
     <try> "more": { "nested" </try> 
     <success>: { "nested" : "valu</success> 
     <attributes>[m, o, r, e]</attributes> 
    </unicode_string> 
    <value> 
     <try> { "nested" : "value</try> 
     <object> 
     <try>{ "nested" : "values</try> 
     <member_pair> 
      <try> "nested" : "values"</try> 
      <unicode_string> 
      <try> "nested" : "values"</try> 
      <success> : "values" } }</success> 
      <attributes>[n, e, s, t, e, d]</attributes> 
      </unicode_string> 
      <value> 
      <try> "values" } }</try> 
      <object> 
       <try>"values" } }</try> 
       <fail/> 
      </object> 
      <array> 
       <try>"values" } }</try> 
       <fail/> 
      </array> 
      <unicode_string> 
       <try>"values" } }</try> 
       <success> } }</success> 
       <attributes>[v, a, l, u, e, s]</attributes> 
      </unicode_string> 
      <success> } }</success> 
      <attributes>[v, a, l, u, e, s]</attributes> 
      </value> 
      <success> } }</success> 
      <attributes>[[n, e, s, t, e, d], [v, a, l, u, e, s]]</attributes> 
     </member_pair> 
     <success> }</success> 
     <attributes>[[[n, e, s, t, e, d], [v, a, l, u, e, s]]]</attributes> 
     </object> 
     <success> }</success> 
     <attributes>[[[n, e, s, t, e, d], [v, a, l, u, e, s]]]</attributes> 
    </value> 
    <success> }</success> 
    <attributes>[[m, o, r, e], [[[n, e, s, t, e, d], [v, a, l, u, e, s]]]]</attributes> 
    </member_pair> 
    <success></success> 
    <attributes>[[[c, h, e, c, k], [1, 2, 3, , 1]], [[m, o, r, e], [[[n, e, s, t, e, d], [v, a, l, u, e, s]]]]]</attributes> 
</object> 
<success></success> 
<attributes>[[[c, h, e, c, k], [1, 2, 3, , 1]], [[m, o, r, e], [[[n, e, s, t, e, d], [v, a, l, u, e, s]]]]]</attributes> 
</value> 

一些注意事項:

  1. 發生故障的任務是因爲解析器規則value結果value類型,而不是object_t的對象...

  2. object_member_t是一對與std::stringconst第一_類型。哎呀。這不能分配給任何一方。因此,請你自己的一雙型和使用它:

    using member_pair_t = std::pair<object_t::key_type, object_t::mapped_type>; 
    
  3. 我的G ++ 5似乎有麻煩,如果留下不合格做的_attr_val ADL查找。我不確定這是一個編譯器問題還是什麼。我剛剛用x3::_attrx3::_val現在

  4. 在規則defs中有一堆缺少的parens,使規則很難讀/檢查。加入他們

  5. unicode_string竟然被破壞(見下文)

  6. 的從未使用int_parser<int64_t>(?呵呵)。使用它:)

  7. 數字解析不起作用。同時它看起來過於複雜。我建議使用double_ | int_其中double_使用嚴格的政策:風格

    x3::real_parser<double, x3::strict_real_policies<double> > const double_ = {}; 
    

事項:

  1. 不要讓你的來電者負責選擇一個隊長。畢竟,如果您使用x3::char_("+8")作爲隊長,那麼事情將會破裂或無法成爲JSON?我建議一個頂級規則只介紹船長:

    auto const json = x3::skip(x3::ascii::space) [ value ]; 
    
  2. 測試駕駛者可以更少一點:

    std::string storage = R"({ "check": [ 1,2,3, null, true ], "more": { "nested" : "values" } })"; 
    
    client::ast::value o; 
    bool r = parse(storage.begin(), storage.end(), client::parser::json, o); 
    
  3. 我刪除了嘈雜_class/_type/_def舞蹈規則未使用「exernally」(這個簡單的代碼示例中,任何非遞歸使用:value

  4. 使用BOOST_SPIRIT_X3_DEBUG,看看發生了什麼:)(這讓我發現在錯誤,查看丟失的破折號)

+1

感謝您分享這令人難以忍受的和有益的細節! – uchuugaka

+0

使用boost 1.65.1和gcc 7.2時,會給出'/boost/spirit/home/x3/nonterminal/detail/rule.hpp:316:24:錯誤:使用已刪除的函數'client :: ast :: value :: value(const client :: ast :: value&)' value_type made_attr = make_attribute :: call(attr); test14.cc:35:15:note:'client :: ast :: value :: value(const client :: ast :: value&)'被隱式聲明爲刪除,因爲'client :: ast :: value'聲明瞭一個移動構造函數或移動賦值運算符 class value:public x3 :: variant Mankka

相關問題