2015-09-16 16 views
1

解析器簡單的boost ::在Android

 namespace qi = boost::spirit::qi; 

     template<typename T> 
     class action 
     { 
     public: 
      action(std::vector<std::shared_ptr<part>>& parts) : m_parts{ parts } {} 

      void operator()(const std::vector<char>& cc, qi::unused_type, qi::unused_type) const 
      { 
       std::string s(cc.begin(), cc.end()); 
       if (s.length() > 0) { 
        auto p = new T(s); 
        m_parts.push_back(std::shared_ptr<part>(p)); 
       } 
      } 
     private: 
      std::vector<std::shared_ptr<part>>& m_parts; 
     }; 

     std::vector<std::shared_ptr<part>> parse(const std::string& source) { 
      namespace ascii = boost::spirit::ascii; 

      using ascii::char_; 
      using qi::lit; 

      std::vector<std::shared_ptr<part>> parts; 

      auto prop_g = lit("{{=") 
       >> *char_(' ') 
       >> (*(char_ - char_("} ")))[action<property_part>(parts)] 
       >> *char_(' ') 
       >> "}}" 
       ; 
      auto text_g = (+(char_ - '{'))[action<text_part>(parts)]; 
      auto g = -text_g >> +(prop_g >> text_g); 

      qi::parse(source.begin(), source.end(), g); 
      return parts; 
     } 

精神語法SIGSEGV導致上氣故障::解析奇巧設備上測試時調用。在任何語義動作被調用之前發生故障。相同的代碼適用於Xcode 6/iOS 8.4和VS 2015.我們使用的是Boost 1.59。

我們可以用Bison替換Spirit,意味着需要額外的構建步驟,或者使用Android NDK的Clang,讓我們脫離捱打的道路。

這個故障可以通過構建配置修復嗎?或者我們可以探索其他選項嗎?

回答

2

當然,錯誤是可以修復的。 您不會顯示語法 請參閱更新雖然您展示了很多未知的解析器表達式,但是我們甚至無法開始推理您的代碼。

有一點,確實脫穎而出是(ab)使用auto,雖然。

一個快速的谷歌應該指出你在〜6個關於這個問題的警告。

不能使用auto與精神的表情模板。但在所有的非常非常簡單的情形(unparameterized無國籍終端)這直接導致Undefined Behaviour

使用

  • qi::rule<>包含/組表達嘗試
  • boost::spirit::copyboost::proto::deep_copy

UPDATE

對於編輯的問題:語法因爲未定義的行爲而崩潰(如果這個「看起來很有效」,那麼你就是(非)幸運的!)。

這裏是一個固定版本,作爲獎勵,我刪除了action<>的東西,用現有的鳳凰機制和屬性傳播代替它。

您可能想要並排研究這些更改以準確找出我所更改的內容。

Live On Coliru

#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix.hpp> 

struct part { 
    part(std::string s="") : _value(std::move(s)) {} 
    virtual ~part() { } 
    virtual void do_print(std::ostream& os) const = 0; 
    protected: 
    std::string _value; 
}; 

struct property_part : part { 
    using part::part; 
    void do_print(std::ostream& os) const { os << "{{=" << _value << "}}"; } 
}; 
struct text_part  : part { 
    using part::part; 
    void do_print(std::ostream& os) const { os << "'" << _value << "'"; } 
}; 

std::vector<std::shared_ptr<part>> parse(const std::string& source) { 
    namespace qi = boost::spirit::qi; 
    namespace px = boost::phoenix; 
    using boost::spirit::ascii::char_; 
    using qi::lit; 

    typedef std::shared_ptr<part> pptr; 
    qi::rule<std::string::const_iterator, pptr()> prop_g, text_g; 

    // this is ok: purely stateless expression template 
    prop_g = lit("{{=") 
     >> *char_(' ') 
     >> qi::as_string [ +~char_("} ") ] [ qi::_val = px::construct<pptr>(px::new_<property_part>(qi::_1)) ] 
     >> *char_(' ') 
     >> "}}" 
     ; 

    text_g = qi::as_string [ +~char_('{') ] [ qi::_val = px::construct<pptr>(px::new_<text_part>(qi::_1)) ]; 

    std::vector<pptr> parts; 
    qi::parse(source.begin(), source.end(), -text_g >> +(prop_g >> text_g), parts); 

    return parts; 
} 

int main() { 
    auto result = parse("My book is about {{= this-is-a-(bogus)-property-part }} else entirely {{=byebye}}"); 
    assert(result.size() == 4); 

    for(auto item : result) 
     item->do_print(std::cout); 
} 

打印

'My book is about '{{=this-is-a-(bogus)-property-part}}' else entirely '{{=byebye}} 
+0

謝謝,我會嘗試你的建議。我已經將語義操作添加到代碼片段中以完成解析器。 –

+0

我仍然不得不在那裏添加一些東西:/以固定語法查看更新後的答案。考慮保持規則靜態/共享(它們可以是const)。另外請注意,它看起來像你在做宏觀擴張,但非常(非常!)效率低下。看看[這非常靈活的示例](http://stackoverflow.com/questions/9404558/a/9405546?s=3|0.4015#9405546),這[簡單的使用精神](http://stackoverflow.com/問題/ 17112494/a/17126962#17126962),相同的[不使用精神](http://stackoverflow.com/questions/17112494/a/17128601#17128601)。 – sehe

+0

如果你真的想重複使用模板**和**高效,[這個答案使用Spirit + ICL來解析模板](http://stackoverflow.com/a/28521682/85371),可以非常有效地擴展反覆。 – sehe