在Android上简单的提升::精神语法SIGSEGV

时间:2015-09-16 14:37:19

标签: c++ gcc boost android-ndk boost-spirit-qi

解析器

        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;
        }
在Kitkat设备上进行测试时,

会导致qi :: parse调用出错。在调用任何语义操作之前发生错误。相同的代码适用于Xcode 6 / iOS 8.4和VS 2015.我们正在使用Boost 1.59。

我们可以用Bison代替Spirit意味着额外的构建步骤,或者将Clang与Android NDK一起使用,让我们摆脱困境。

可以使用构建配置修复此故障还是我们可以探索其他选项?

1 个答案:

答案 0 :(得分:2)

当然可以修复错误。 你没有显示语法参见更新尽管如此,你展示了许多具有未知数的解析器表达式,所以我们甚至无法开始推理你的代码。

确实突出的一点是auto的(ab)使用。

一个快速谷歌应该指出你关于SO的约6个问题警告这个。

  

您不能将auto与Spirit的表达式模板一起使用。除了非常微不足道的案例(非参数无状态终端)外,这直接导致Undefined Behaviour

尝试使用

  • qi::rule<>包含/分组表达式
  • boost::spirit::copyboost::proto::deep_copy

<强>更新

对于编辑过的问题:确实语法由于未定义的行为而崩溃(如果这“似乎有效”,那么你只是(非)幸运!)。

这是一个固定版本,作为奖励我删除了action<>用现有的Phoenix机制和属性传播替换它的东西。

您可能需要并排研究这些变化,以确切了解我所做的更改。

<强> 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}}