7

我正在努力学习boost::spirit。例如,我正在尝试将一系列单词解析为vector<string>. 我试过这个:

#include <boost/spirit/include/qi.hpp>
#include <boost/foreach.hpp>

namespace qi = boost::spirit::qi;

int main() {

  std::vector<std::string> words;
  std::string input = "this is a test";

  bool result = qi::phrase_parse(
      input.begin(), input.end(),
      +(+qi::char_),
      qi::space,
      words);

  BOOST_FOREACH(std::string str, words) {
    std::cout << "'" << str << "'" << std::endl;
  }
}

这给了我这个输出:

'thisisatest'

但我想要以下输出,其中每个单词都单独匹配:

'this'
'is'
'a'
'test'

如果可能的话,我想避免qi::grammar为这个简单的案例定义我自己的子类。

4

3 回答 3

14

您从根本上误解了(或至少滥用)跳过解析器的目的 -qi::space用作跳过解析器,是为了使您的解析器空白不可知,因此a b和之间没有区别ab

在您的情况下,空格重要,因为您希望它来分隔单词。因此,您不应该跳过空格,并且要使用qi::parse而不是qi::phrase_parse

#include <vector>
#include <string>
#include <iostream>
#include <boost/foreach.hpp>
#include <boost/spirit/include/qi.hpp>

int main()
{
    namespace qi = boost::spirit::qi;

    std::string const input = "this is a test";

    std::vector<std::string> words;
    bool const result = qi::parse(
        input.begin(), input.end(),
        +qi::alnum % +qi::space,
        words
    );

    BOOST_FOREACH(std::string const& str, words)
    {
        std::cout << '\'' << str << "'\n";
    }
}

(现在更新了 G. Civardi 的修复程序。)

于 2012-05-02T21:28:04.747 回答
2

我相信这是最小的版本。qi::omit 应用于 qi 列表解析器分隔符不是必需的 - 它不会生成任何输出属性。详情见: http: //www.boost.org/doc/libs/1_48_0/libs/spirit/doc/html/spirit/qi/reference/operator/list.html

#include <string>
#include <iostream>
#include <boost/foreach.hpp>
#include <boost/spirit/include/qi.hpp>

int main()
{
  namespace qi = boost::spirit::qi;

  std::string const input = "this is a test";

  std::vector<std::string> words;
  bool const result = qi::parse(
      input.begin(), input.end(),
      +qi::alnum % +qi::space,
      words
  );

  BOOST_FOREACH(std::string const& str, words)
  {
      std::cout << '\'' << str << "'\n";
  }
}
于 2012-06-09T21:31:23.723 回答
1

以防万一其他人遇到我的领先空间问题。

我一直在使用 ildjarn 的解决方案,直到遇到一个以空格开头的字符串。

std::string const input = " this is a test";

我花了一段时间才弄清楚前导空格导致函数 qi::parse(...) 失败。解决方案是在调用 qi::parse() 之前修剪输入前导空格。

于 2016-12-12T04:38:59.330 回答