2015-10-13 38 views
2

我想分析以下字符串:id=1;entry1=[A,B,D];entry2=[bla,blubb];factor=[1,5]!鳳凰綁定到結構提升精神法則 - 編譯失敗

我的解析器:

struct Entry 
{ 
    uint32_t id; 
    std::vector<std::string> entry1; 
    std::vector<std::string> entry2; 

    bool useFactor; 
    std::pair<int, int> factor; 
}; 

BOOST_FUSION_ADAPT_STRUCT(Entry, id, entry1, entry2, useFactor, factor) 

template<typename It> 
struct testParser : qi::grammar<It, Entry()> 
{ 
    testParser : testParser::base_type(start) 
    { 
    using namespace qi; 
    id_ %= lit("id=") >> int_ ; 
    entry1_ %= lit("entry1=") >> char_('[') >> +(char_ -char_(']') % ',') >> char_(']'); 
    entry2_ %= lit("entry1=") >> char_('[') >> +(char_ -char_(']') % ',') >> char_(']'); 
    factor %= lit("factor=") >> char_('[') >> int_ >> char_(',') >> int_ >> char_(']'); 

    start = id >> ';' >> entry1 >> ';' >> entry2 >> ((';' >> factor[ phx::bind(&Entry::useFactor,_1) = true;]) >> '!') | '!'; 

    qi::rule<It, Entry()> start; 
    qi::rule<It, int()> id; 
    qi::rule<It, std::vector<std::string>()> entry1_, entry2_; 
    qi::rule<It, std::pair<int,int>()> factor; 
} 
}; 

即時得到極端大的編譯錯誤消息。我認爲它是因爲entry1和entry2規則(字符串插入的向量)

+0

你能開始發佈有效的代碼嗎?對樣品進行癱瘓確實沒有意義。您可以複製/粘貼。請參閱http://sscce.org。現在:https://www.livecoding.tv/sehe/ – sehe

回答

2

正如您可能在直播中看到的一樣,我已逐漸修正了語法。

那裏有很多「你喝醉了」的時刻,所以我不能確定我能在這裏捕捉到散文的基本步驟。無論如何,有a look at the recorded stream¹

一些實質性的筆記(忽略隨機拼寫錯誤和清楚地混淆代碼):

  • 使用attr(v)簡單地暴露的屬性(如,在這種情況下attr(true)
  • 使用lit('c')lit("abc")或只是'c'和​​到匹配文字字符(字符串)捕獲其內容
  • 使用%=只在語義動作
  • 語義運行存在後的主題解析器成功(只有當且僅當成功)。

    因此,即使您應該/應該已經在語義操作中設置了useFactor成員,但只有在存在factor部分時纔會運行(否則將保留不確定的值)。

  • 格式化很重要。

  • 調試很重要。

可選:

  • 使用as_vector破解一個快速的方法來打印結果使用BOOST_SPIRIT_DEBUG*調試規則
  • 我已經展示了該技術使用inherited arguments這樣你就可以重複使用entry規則爲entry1entry2

未顯示:

  • 使用船長爲空白不敏感
  • 使用no_case爲...不區分大小寫
  • 與船長:的lexeme提防避免匹配的關鍵字跨跳過輸入字符

工作碼,作爲一個SSCCE

Live On Coliru

#define BOOST_SPIRIT_DEBUG 
#include <iostream> 
#include <vector> 

namespace std { 
    template <typename T> 
    static ostream& operator<<(ostream& os, vector<T> const& v) { 
     os << "vector{ "; 
     for(auto& e : v) 
      os << "'" << e << "', "; 
     return os << "}"; 
    } 
    template <typename T, typename U> 
    static ostream& operator<<(ostream& os, pair<T,U> const& p) { 
     return os << "pair{ '" << p.first << "', '" << p.second << "' }"; 
    } 
} 

#include <boost/fusion/adapted/struct.hpp> 
#include <boost/fusion/adapted/std_pair.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix.hpp> 

namespace qi = boost::spirit::qi; 
namespace phx = boost::phoenix; 

struct Entry 
{ 
    uint32_t id; 
    std::vector<std::string> entry1; 
    std::vector<std::string> entry2; 

    bool useFactor; 
    std::pair<int, int> factor; 
}; 

BOOST_FUSION_ADAPT_STRUCT(Entry, id, entry1, entry2, useFactor, factor) 

template<typename It> 
struct testParser : qi::grammar<It, Entry()> 
{ 
    testParser() : testParser::base_type(start) 
    { 
     using namespace qi; 

     id  = "id=" >> int_; 
     entry = lit(_r1) >> ('[' >> +~char_("],") % ',' >> ']'); 
     factor = "factor=" >> ('[' >> int_ >> ',' >> int_ >> ']'); 

     start = 
       id    >> ';' 
      >> entry(+"entry1=") >> ';' 
      >> entry(+"entry2=") >> ';' 
      >> attr(true) 
      >> (factor | attr(std::pair<int,int>{1,1})) 
      >> '!'; 

     BOOST_SPIRIT_DEBUG_NODES((start)(entry)(id)(factor)) 
#if 0 
#endif 
    } 
    private: 
    qi::rule<It, Entry()>        start; 
    qi::rule<It, int()>         id; 
    qi::rule<It, std::vector<std::string>(std::string)> entry; 
    qi::rule<It, std::pair<int,int>()>     factor; 
}; 

int main() { 
    std::string const input = "id=1;entry1=[A,B,D];entry2=[bla,blubb];factor=[1,5]!"; 
    using It = std::string::const_iterator; 

    testParser<It> g; 
    It f = input.begin(), l = input.end(); 

    Entry entry; 
    bool ok = qi::parse(f, l, g, entry); 

    std::cout << std::boolalpha; 
    if (ok) { 
     std::cout << "Parsed: " << boost::fusion::as_vector(entry) << "\n"; 
    } else { 
     std::cout << "Parse failed\n"; 
    } 

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

打印:

<start> 
<try>id=1;entry1=[A,B,D];</try> 
<id> 
    <try>id=1;entry1=[A,B,D];</try> 
    <success>;entry1=[A,B,D];entr</success> 
    <attributes>[1]</attributes> 
</id> 
<entry> 
    <try>entry1=[A,B,D];entry</try> 
    <success>;entry2=[bla,blubb];</success> 
    <attributes>[[[A], [B], [D]], [e, n, t, r, y, 1, =]]</attributes> 
</entry> 
<entry> 
    <try>entry2=[bla,blubb];f</try> 
    <success>;factor=[1,5]!</success> 
    <attributes>[[[b, l, a], [b, l, u, b, b]], [e, n, t, r, y, 2, =]]</attributes> 
</entry> 
<factor> 
    <try>factor=[1,5]!</try> 
    <success>!</success> 
    <attributes>[[1, 5]]</attributes> 
</factor> 
<success></success> 
<attributes>[[1, [[A], [B], [D]], [[b, l, a], [b, l, u, b, b]], 1, [1, 5]]]</attributes> 
</start> 
Parsed: (1 vector{ 'A', 'B', 'D', } vector{ 'bla', 'blubb', } true pair{ '1', '5' }) 

¹(我錯過了第一部分,我在那裏固定頭,平衡括號並添加括號來構造等等o.O)。

+0

[記錄的流](https://www.livecoding.tv/video/fixing-up-a-spirit-grammar/)就在這裏。 ([實驗](http://chat.stackoverflow.com/transcript/10?m=24182469#24182469)) – sehe

+0

增加了一個(非詳盡的)固定事物列表。 – sehe