如何使用boost::spirit::qi解析行尾符?

9

一个简单的eol不就可以解决问题吗?

#include <algorithm>
#include <boost/spirit/include/qi.hpp>
#include <iostream>
#include <string>
using boost::spirit::ascii::space;
using boost::spirit::lit;
using boost::spirit::qi::eol;
using boost::spirit::qi::phrase_parse;

struct fix : std::unary_function<char, void> {
  fix(std::string &result) : result(result) {}
  void operator() (char c) {
    if      (c == '\n') result += "\\n";
    else if (c == '\r') result += "\\r";
    else                result += c;
  }
  std::string &result;
};

template <typename Parser>
void parse(const std::string &s, const Parser &p) {
  std::string::const_iterator it = s.begin(), end = s.end();
  bool r = phrase_parse(it, end, p, space);
  std::string label;
  fix f(label);
  std::for_each(s.begin(), s.end(), f);
  std::cout << '"' << label << "\":\n" << "  - ";
  if (r && it == end) std::cout << "success!\n";
  else std::cout << "parse failed; r=" << r << '\n';
}

int main() {
  parse("foo",     lit("foo"));
  parse("foo\n",   lit("foo") >> eol);
  parse("foo\r\n", lit("foo") >> eol);
}

输出:

"foo":
  - 成功!
"foo\n":
  - 解析失败;r=0
"foo\r\n":
  - 解析失败;r=0

为什么后两个会失败?


相关问题:

使用Boost::Spirit,如何要求记录的一部分必须在自己的行上?

1个回答

14

您在调用 phrase_parse 时使用的是 space 作为跳过器。该解析器匹配任何由 std::isspace 返回 true 的字符(假设您正在进行基于 ascii 的解析)。因此,输入中的 \r\n 在被您的跳过器吞掉之前,无法被您的 eol 解析器看到。


1
使用 phrase_parse(it, end, p, space - eol) 允许 eol 成功。谢谢! - Greg Bacon
2
@GregBacon 当我输入 space - eol 时,我得到了非常奇怪和冗长的错误消息。 - Dilawar
1
@Dilawar 参考这个答案 https://dev59.com/fGPVa4cB1Zd3GeqP6YE9#10469726],了解有关更改跳过器行为的提示和技巧。 - sehe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接