Как использовать boost::spirit для анализа последовательности слов в вектор?

Я пытаюсь научиться 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 для этого простого случая.


person Frank    schedule 02.05.2012    source источник


Ответы (3)


Вы принципиально неправильно понимаете цель (или, по крайней мере, неправильное использование) анализатора пропуска 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.)

person ildjarn    schedule 02.05.2012

Я считаю, что это минимальная версия. 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";
  }
}
person G. Civardi    schedule 09.06.2012

На всякий случай, если кто-то еще столкнется с моей проблемой ведущих пробелов.

Я использовал решение ildjarn, пока не наткнулся на строку, начинающуюся с пробелов.

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

Мне потребовалось некоторое время, чтобы понять, что начальный пробел приводит к сбою функции qi::parse(...). Решение состоит в том, чтобы обрезать начальные пробелы ввода перед вызовом qi::parse().

person sofname    schedule 12.12.2016
comment
Это потому, что то, что люди рекомендовали вам, неправильно. Вы не должны менять фразу_parse на синтаксический анализ. Правильный способ — использовать лексему[]. - person facetus; 24.07.2020