在Boost Spirit中报告错误

chr*_*ock 4 c++ boost-spirit boost-spirit-qi

我的解析器语法底部有以下错误处理程序:

qi::on_error<qi::fail>(
    launch,
    std::cerr << phoenix::val("Paring error in ") << spirit::_4 << std::endl
              << phoenix::construct<std::string>(spirit::_3, spirit::_2)
              << std::endl
    );
Run Code Online (Sandbox Code Playgroud)

问题是解析器的输入事先没有被新行分解,因此产生的错误语句将是源代码中从错误点到结束的所有行.有没有直接替代

phoenix::construct<std::string>(spirit::_3, spirit::_2)
Run Code Online (Sandbox Code Playgroud)

只打印发生错误的一行?如果我试图搜索,凤凰语义将给我带来麻烦'\n'.

chr*_*ock 7

我们需要创建一个可以获取Spirit参数的Phoenix函数.

// lazy function for error reporting
struct ReportError {
  // the result type must be explicit for Phoenix
  template<typename, typename, typename, typename>
  struct result { typedef void type; };

  // contract the string to the surrounding new-line characters
  template<typename Iter>
  void operator()(Iter first_iter, Iter last_iter,
                  Iter error_iter, const qi::info& what) const {
    std::string first(first_iter, error_iter);
    std::string last(error_iter, last_iter);
    auto first_pos = first.rfind('\n');
    auto last_pos = last.find('\n');
    auto error_line = ((first_pos == std::string::npos) ? first
                        : std::string(first, first_pos + 1))
                      + std::string(last, 0, last_pos);
    auto error_pos = (error_iter - first_iter) + 1;
    if (first_pos != std::string::npos) {
      error_pos -= (first_pos + 1);
    }
    std::cerr << "Parsing error in " << what << std::endl
              << error_line << std::endl
              << std::setw(error_pos) << '^'
              << std::endl;
  }
};

const phoenix::function<ReportError> report_error = ReportError();
Run Code Online (Sandbox Code Playgroud)

然后我们只在错误处理程序中调用此函数.

qi::on_error<qi::fail>(
    launch,
    report_error(spirit::_1, spirit::_2, spirit::_3, spirit::_4)
    );
Run Code Online (Sandbox Code Playgroud)