2015-09-16 15 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