c++ - 琐碎精神解析器的段错误

标签 c++ parsing c++11 boost-spirit boost-spirit-qi

在过去的几个月里,我经常使用 spirit::qi。然而,这次我遇到了一个我真的无法理解的段错误。

我已经将它缩减为一个极小的测试用例,语法定义为 12 行代码。

这感觉很像 earlier question但是那里的解决方案,将 .alias() 添加到某些终端,以便 qi 不会复制它们,似乎无法解决这个问题。

我担心我在这里遗漏了一些基本的东西,因为我已经设法创造出比这更复杂的语法来测试我期望的方式。

我现在唯一想到的是,也许 qi 只是不喜欢主语法返回类型是一个 boost 变体?我不知道我以前是否做过这样的语法。我想接下来我会对此进行测试,但老实说,我一直在转动我的轮子摆弄类似的东西有一段时间了。

我可以确认,如果设置 mod_ 规则的行被注释掉,则不会发生段错误,程序会正常运行直至完成。

编辑:实际上,即使删除了所有语法属性,它也会出现段错误。

#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <iostream>

typedef unsigned int uint;

namespace qi = boost::spirit::qi;

/***
 * Grammar
 */
template <typename Iterator>
struct op_grammar : qi::grammar<Iterator> {
  qi::rule<Iterator> constant_;
  qi::rule<Iterator> mod_;
  qi::rule<Iterator> expr_;

  op_grammar() : op_grammar::base_type(expr_) {
    constant_ = qi::uint_;
    expr_ = mod_ | constant_;
    mod_ = expr_ >> qi::lit('%') >> expr_; 
  }
};

/***
 * Test
 */
int main() {
//  std::string str{"n % 2"};
  std::string str{"2"};

  typedef std::string::const_iterator str_it;
  str_it it = str.begin();
  str_it end = str.end();
  op_grammar<str_it> grammar;

  if (qi::parse(it, end, grammar) && it == end) {
    std::cerr << "Good\n";
  } else {
    std::cerr << "Bad\n";
  }
}

最佳答案

其实,我想通了...

问题是,如所写,语法有缺陷,无法解析。因为,expr_的第一个非终结符是mod_mod_的第一个非终结符是expr_,所以甚至没有办法开始弄清楚如何解析它们中的任何一个,它是循环的。

可以通过将 mod_ 的第一个 expr_ 更改为 constant_ 来修复语法,然后它会按预期工作。

我想我会在这里留下这个答案,因为这个问题已经得到了赞成票,但我不确定是否应该删除这个问题。

关于c++ - 琐碎精神解析器的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33325243/

相关文章:

c++ - 在某些 C++ 编译器上使用 restrict 限定符的编译器错误

c++ - 运行 OpenCV HOG 样本

parsing - 左结合运算符的 BNF 语法

c++ - C++11 的垃圾收集 ABI 有实际用途吗?

c++ - std::map clear() 在调试器中的性能?

python - 给定路径计算 python 文件函数数量的好方法

java - 解析带有前缀的K、V数据的最佳方案

c++ - GCC 警告将函数指针转换为对象指针

c++ - std::condition_variable::wait_until 相对于 std::this_thread::sleep_for 有什么优势吗?

c++ - 返回一个 const char *