boost :: spirit附加一个向量

时间:2013-02-19 21:34:40

标签: c++ boost boost-spirit boost-spirit-qi

我在使用phoenix::insert将数据插入向量时遇到问题。 代码应解析输入,例如“(将xyz - loc r - 机器人项目移动)”到名为“move”的struct Predicate和类型为loc的3个变量,类型{{1}的1个变量}和1个默认类型为robot的变量。所有这些符号都只是与问题无关的字符串(我相信)。问题是在object的规则定义中使用phoenix::insert

这是我的代码:

predicate

但代码导致以下错误(clang3.3与libc ++和c ++ 11; mac os x 10.8):

#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";
    }
  }
}

如上所述,我认为错误是在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的结果。

我通过编辑boost标题并删除return语句“修复”了这个问题,但鉴于我对这个库的理解有限,我想避免这个......

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

0 个答案:

没有答案