を使用してベクターにデータを挿入する際に問題がありますphoenix::insert
。このコードは、「(move xyz - loc r - robot item)」などの入力を解析して、struct Predicate
「move」という名前の 3 つの変数 type loc
、1 つの type 変数、robot
および 1 つの変数 type に変換する必要があります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";
}
}
}
しかし、コードは次のエラーにつながります (libc++ および c++11 を使用する clang3.3; 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
ブーストヘッダーを編集してreturnステートメントを削除することで問題を「修正」しましたが、このライブラリについての理解が限られているため、それを避けたいと思います...
誰かが問題を説明したり、別の解決策を提案したりできますか?