boost :: spirit добавить вектор

У меня проблема с вставкой данных в вектор с помощью phoenix::insert. Код должен анализировать ввод, такой как «(move x y z - loc r - robot item)», в struct Predicate с именем «move» и 3 переменными типа loc, 1 переменной типа robot и 1 переменной с типом по умолчанию object. Все эти символы - просто строки, не имеющие отношения к проблеме (я считаю). Проблема заключается в использовании phoenix::insert в определении правила для predicate.

Вот код, который у меня есть:

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/spirit/home/phoenix/container.hpp>
#include <boost/fusion/include/adapt_struct.hpp>


namespace client {

  namespace fusion = boost::fusion;
  namespace phoenix = boost::phoenix;
  namespace qi = boost::spirit::qi;
  namespace ascii = boost::spirit::ascii;

  struct Variable {
    std::string name;
    std::string type;
  };


  struct Predicate {
    std::string name;
    std::vector<Variable> vars;
  };


  struct TermList {
    std::vector<Variable> vars;

    TermList() = default;
    TermList(std::vector<std::string> names, std::string type)
    {
      for (auto& n : names)
      {
        Variable t;
        t.name = n;
        t.type = type;
        vars.push_back(t);
      }
    }

    TermList& operator=(const TermList& rhs) = default;
    TermList(const TermList& from) = default;
    TermList(TermList&& from) = default;
  };

}

BOOST_FUSION_ADAPT_STRUCT(
  client::Variable,
  (std::string, name)
  (std::string, type)
)

BOOST_FUSION_ADAPT_STRUCT(
  client::Predicate,
  (std::string, name)
  (std::vector<client::Variable>, vars)
)

BOOST_FUSION_ADAPT_STRUCT(
  client::TermList,
  (std::vector<client::Variable>, vars)
)

namespace client {

  template <typename Iterator, typename Skipper = ascii::space_type>
  struct strips_domain_grammar
  : qi::grammar<Iterator, Predicate(),
                qi::locals<std::vector<Variable>>, Skipper>
  {
    strips_domain_grammar()
    : strips_domain_grammar::base_type(predicate, "predicate")
    {

      using qi::eps;
      using qi::lit;
      using qi::lexeme;
      using qi::raw;

      using qi::on_error;
      using qi::fail;

      using phoenix::at_c;
      using phoenix::push_back;
      using phoenix::insert;
      using phoenix::begin;
      using phoenix::end;
      using phoenix::construct;
      using phoenix::val;

      using ascii::char_;
      using ascii::string;
      using ascii::alpha;
      using ascii::alnum;
      using namespace qi::labels;

      // identifier such as move or ?from
      identifier %= raw[lexeme[((alpha | char_('_') | char_('?'))
                                >> *(alnum | char_('_') | char_('-')))]];

      // x | x y | x - type | x y z - type
      term_list =
      +(identifier          [push_back(_a, _1)])
      >>
      (
       ('-' >
       identifier [qi::_val = phoenix::construct<TermList>(qi::_a, qi::_1)])
       |
       eps        [qi::_val = phoenix::construct<TermList>(qi::_a, "object")]
       )
      ;

      // (move x y z - loc r - robot item) // item is detault type - object
      predicate =
      char_('(')
      > identifier       [at_c<0>(_val) = _1]
      > +(term_list      [insert(at_c<1>(_val), end(at_c<1>(_val)),   // <- ERROR
                                 begin(at_c<0>(_1)), end(at_c<0>(_1)))])
      > ')'
      ;


      predicate.name("predicate");
      term_list.name("term list");
      identifier.name("id");

      // on_error is called only when an expectation fails (> instead of >>)
      on_error<fail>
      (
       predicate
       , std::cout
       << val("Error! Expecting ")
       << _4                               // what failed?
       << val(" here: \"")
       << construct<std::string>(_3, _2)   // iterators to error-pos, end
       << val("\"")
       << std::endl
       );
    }

    qi::rule<Iterator, std::string(), Skipper> identifier;

    qi::rule<Iterator, TermList(),
             qi::locals<std::vector<std::string>>, Skipper> term_list;

    qi::rule<Iterator, Predicate(),
             qi::locals<std::vector<Variable>>, Skipper> predicate;

  };
} // namespace client

int main(int argc, const char** argv)
{
  typedef std::string::const_iterator iterator_type;
  typedef client::strips_domain_grammar<iterator_type> domain_grammar;

  domain_grammar g;

  std::string str;
  while (std::getline(std::cin, str))
  {
    if (str.empty() || str[0] == 'q' || str[0] == 'Q')
      break;

    using boost::spirit::ascii::space;

    client::Predicate predicate;
    std::string::const_iterator iter = str.begin();
    std::string::const_iterator end = str.end();
    bool r = phrase_parse(iter, end, g, space, predicate);

    if (r && iter == end)
    {
      std::cout << "-------------------------\n";
      std::cout << "Parsing succeeded\n";
      std::cout << "got: " << predicate.name;
      std::cout << "\n-------------------------\n";
    }
    else
    {
      std::cout << "-------------------------\n";
      std::cout << "Parsing failed\n";
      std::cout << "-------------------------\n";
    }
  }
}

но код приводит к следующей ошибке (clang3.3 с libc ++ и c ++ 11; mac os x 10.8):

boost/spirit/home/phoenix/stl/container/container.hpp:416:16: error: void function 'operator()' should not return a value [-Wreturn-type]
           return c.insert(arg1, arg2, arg3);

Как упоминалось выше, я считаю, что ошибка является результатом использования phoenix::insert в действии в правиле predicate.

Я «исправил» проблему, отредактировав заголовок boost и удалив оператор return, но, учитывая мое ограниченное понимание этой библиотеки, я бы хотел избежать этого ...

Может кто-нибудь объяснить проблему или предложить другое решение?


person Roman Kutlak    schedule 19.02.2013    source источник
comment
Как он недавно сказал: вы ограничиваете свой потенциал получать быстрые и простые ответы, оставляя ровно столько кода, чтобы сделать это загадкой.   -  person    schedule 20.02.2013
comment
@llonesmiz ну ... вы уловили мои чувства здесь :)   -  person sehe    schedule 20.02.2013
comment
@Roman Если вы покажете небольшой автономный пример, демонстрирующий вашу проблему, с фактическим вводом и ожидаемыми результатами, я почти уверен, что мы оба сможем предложить значительно более простой подход за считанные минуты.   -  person sehe    schedule 20.02.2013
comment
Ну я изменил вопрос, но пример не совсем маленький. Хотя он самодостаточен :-)   -  person Roman Kutlak    schedule 22.02.2013
comment
Я предполагаю, что ваша проблема аналогична показанной здесь, что существует несоответствие между тем, что Phoenix ожидает в результате, и тем, что функция возвращается, начиная с C ++ 11. К сожалению, у меня нет доступа к clang, который может использовать libc ++, поэтому следующий код не протестирован, но я думаю, что он должен работать. Программа, которая, надеюсь, работает.   -  person    schedule 22.02.2013
comment
Спасибо, llonesmiz, что, кажется, помогли.   -  person Roman Kutlak    schedule 22.02.2013