2

我在使用phoenix::insert. 代码应将诸如“(move xyz - 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 with libc++ and 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 语句“修复”了这个问题,但鉴于我对这个库的了解有限,我想避免这种情况......

有人可以解释问题或提出不同的解决方案吗?

4

0 回答 0