Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用Boost::Spirit解析前置条件和递归_C++_Boost_Boost Spirit_Boost Spirit Qi - Fatal编程技术网

C++ 使用Boost::Spirit解析前置条件和递归

C++ 使用Boost::Spirit解析前置条件和递归,c++,boost,boost-spirit,boost-spirit-qi,C++,Boost,Boost Spirit,Boost Spirit Qi,我试图用Boost::Spirit解析PDDL文件,但在将前置条件解析为结构时遇到了一些问题。我正在努力理解Boost手册中关于如何将条件放入我的结构和递归的内容 我在下面给出一段代码,可以很好地说明这个问题。必须分析如下所示的字符串: :precondition (and (at-pos ?r ?pos) (not (has-pos ?m ?pos)) ) 到目前为止,我的代码看起来是这样的,但我几乎可以肯定,在没有Boost::Phoenix方面的经验的情况下,我不理解at_c是如

我试图用Boost::Spirit解析PDDL文件,但在将前置条件解析为结构时遇到了一些问题。我正在努力理解Boost手册中关于如何将条件放入我的结构和递归的内容

我在下面给出一段代码,可以很好地说明这个问题。必须分析如下所示的字符串:

:precondition
(and
  (at-pos ?r ?pos)
  (not (has-pos ?m ?pos))
)
到目前为止,我的代码看起来是这样的,但我几乎可以肯定,在没有Boost::Phoenix方面的经验的情况下,我不理解at_c是如何工作的

predi_param = '?' >> name_type;
predi = '(' 
    >> name_type
    >> +predi_param
    >> ')';
literal = ( 
    ( '(' >> lit("not") >>
      predi       [at_c<0>(_val) = false]
      >> ')'
    )
    | predi       [at_c<0>(_val) = true]
  )
  >> ')';
pred_list = ( '(' >> lit("and") >> (*pred_list) >> ')')
  | literal;
preconditions = lit(":precondition") >> pred_list;

qi::rule<Iterator, std::string(), ascii::space_type> predi_param;
qi::rule<Iterator, Predicate(), ascii::space_type> predi;
qi::rule<Iterator, Literal(), ascii::space_type> literal;
qi::rule<Iterator, std::vector<Literal>(), ascii::space_type> preconditions, pred_list;
predi_param='?'>>name_type;
predi='('
>>名称/类型
>>+预测参数
>> ')';
文字=(
('('>>lit(“not”)>>
预测值[at_c(_val)=假]
>> ')'
)
|预测值[at_c(_val)=真]
)
>> ')';
pred_list=('('>>lit(“and”)>>(*pred_list)>>'))
|文字;
前置条件=点亮(“:前置条件”)>>pred_列表;
qi::规则预测参数;
qi:规则预测;
qi::规则文本;
qi::规则先决条件,pred_列表;
我的AST如下所示:

struct Predicate
{
  std::string name;
  std::vector<std::string> predicate_params;
};  
struct Literal
{
  bool condition;
  Predicate predicate;
};

BOOST_FUSION_ADAPT_STRUCT(
    pddl_parser::Literal,
    (bool, condition)
    (pddl_parser::Predicate, predicate)
)

BOOST_FUSION_ADAPT_STRUCT(
    pddl_parser::Predicate,
    (std::string, name)
    (std::vector<std::string>, predicate_params)
)
struct谓词
{
std::字符串名;
std::向量谓词参数;
};  
结构文字
{
布尔条件;
谓词;
};
增强融合适应结构(
pddl_解析器::文本,
(布尔,条件)
(pddl_解析器::谓词,谓词)
)
增强融合适应结构(
pddl_解析器::谓词,
(std::字符串,名称)
(标准::向量,谓词参数)
)
编译此文件会导致编译错误:

parser.cpp:67:17:   required from ‘pddl_parser::domain_parser<Iterator>::domain_parser() [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >]’
parser.cpp:136:10:   required from here
/usr/include/boost/spirit/home/qi/detail/assign_to.hpp:153:20: error: no matching function for call to ‘pddl_parser::Literal::Literal(const std::vector<pddl_parser::Literal>&)’
             attr = static_cast<Attribute>(val);
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from parser.cpp:11:0:
./pddlast.h:23:10: note: candidate: pddl_parser::Literal::Literal()
   struct Literal
          ^~~~~~~
./pddlast.h:23:10: note:   candidate expects 0 arguments, 1 provided
./pddlast.h:23:10: note: candidate: pddl_parser::Literal::Literal(const pddl_parser::Literal&)
./pddlast.h:23:10: note:   no known conversion for argument 1 from ‘const std::vector<pddl_parser::Literal>’ to ‘const pddl_parser::Literal&’
./pddlast.h:23:10: note: candidate: pddl_parser::Literal::Literal(pddl_parser::Literal&&)
./pddlast.h:23:10: note:   no known conversion for argument 1 from ‘const std::vector<pddl_parser::Literal>’ to ‘pddl_parser::Literal&&’
parser.cpp:67:17:来自“pddl\u parser::domain\u parser::domain\u parser()[带迭代器=\uuuu gnu\u cxx::\uu normal\u迭代器]”的必需项
parser.cpp:136:10:此处为必填项
/usr/include/boost/spirit/home/qi/detail/assign\u to.hpp:153:20:错误:调用“pddl\u解析器::Literal::Literal(const std::vector&)”时没有匹配的函数
attr=静态(val);
^~~~~~~~~~~~~~~~~~~~~~~~~~~
在parser.cpp:11:0中包含的文件中:
./pddlast.h:23:10:note:candidate:pddl_解析器::Literal::Literal()
结构文字
^~~~~~~
./pddlast.h:23:10:注意:候选者需要0个参数,提供1个参数
./pddlast.h:23:10:注意:候选:pddl_解析器::Literal::Literal(constpddl_解析器::Literal&)
./pddlast.h:23:10:注意:参数1从'const std::vector'到'const pddl_parser::Literal&'没有已知的转换
./pddlast.h:23:10:注意:候选:pddl_解析器::Literal::Literal(pddl_解析器::Literal&&)
./pddlast.h:23:10:注意:参数1从'const std::vector'到'pddl_parser::Literal&'没有已知的转换
如果出于测试目的将
pred_列表
重新格式化为
pred_列表=('('>*literal)>>')虽然我去掉了
(and)
,但代码编译后仍然没有成功。我的印象是我完全搞错了什么,但什么也找不到。这是我第一次尝试使用Boost::Spirit。

你这么说吧

pred_list = ( '(' >> *literal) >> ')');
编译,但以下内容不编译:

pred_list = ( '(' >> lit("and") >> (*pred_list) >> ')') | literal;
如果你仔细观察,这是有道理的。由于
pred_list
具有声明的属性类型
std::vector
,显然重复的文本(
*literal
)可能与自动属性传播的文本兼容

现在,看第二个规则定义。它解析一组无属性的文本(
”(“
”和“
”)”
),然后<代码>*pred_列表
。如果
pred_list
声明了
std::vector
属性,那么
*pred_list
肯定会合成
std::vector
。更糟糕的是,“事后思考”使合成属性等同于变量

对。那有点乱。您的AST根本不反映规则,反之亦然

前面的路 您可能应该重述您的问题,删除失败的实现位并描述目标。如果我们能够知道真正的语法要求,/那么/我们就可以导出一个匹配的AST,它是正确的

间奏 在中场休息时,让我简化
literal
的规则。(有关背景信息,请参见):

PS看来一只流浪猫也输入了额外的信息

    >> ')';
最后呢

建设性的猜测 从仅仅查看示例输入来看,我打赌您只想解析表单的

(function_name arguments)
应用程序可以嵌套的位置。所以,参数要么是原子,要么是函数应用

好吧,让我们用AST,快点:

namespace AST {
    using Atom = std::string;

    struct Application;

    using Expression = boost::variant<Atom, Application>;

    struct Application {
        Atom function;
        std::vector<Expression> arguments;
    };
}
并且启用了
BOOST\u SPIRIT\u DEBUG


:前提条件\n
\n
获取更多高级信息)

它没有立即根据PDDL规范验证AST。我根本不确定您打算实现多少,所以我认为更通用的初学者可能会有所帮助

完整列表

#define BOOST_SPIRIT_DEBUG
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>

namespace AST {
    using Atom = std::string;

    struct Application;

    using Expression = boost::variant<Atom, Application>;

    struct Application {
        Atom function;
        std::vector<Expression> arguments;

        friend std::ostream& operator<<(std::ostream& os, Application const& a) {
            os << "(" << a.function;
            for (auto& arg : a.arguments)
                os << " " << arg;
            return os << ")";
        }
    };
}

BOOST_FUSION_ADAPT_STRUCT(AST::Application, function, arguments)

namespace pddl_parser {

    namespace qi    = boost::spirit::qi;

    template <typename Iterator>
    struct Precondition : qi::grammar<Iterator, AST::Expression()> {
        Precondition() : Precondition::base_type(precondition) {
            using namespace qi;

            atom         = +(graph - '(' - ')');
            application  = '(' >> atom >> *expression >> ')';
            expression   = atom | application;

            precondition = skip(ascii::space) [":precondition" >> expression];

            BOOST_SPIRIT_DEBUG_NODES((precondition)(expression)(application)(atom))
        }

      private:
        using Skipper = qi::ascii::space_type;
        qi::rule<Iterator, AST::Application(), Skipper> application;
        qi::rule<Iterator, AST::Expression(), Skipper>  expression;

        // lexemes
        qi::rule<Iterator, AST::Expression()> precondition;
        qi::rule<Iterator, AST::Atom()> atom;
    };
}

int main() {
    using It = std::string::const_iterator;

    for (std::string const& input : {
            R"--(:precondition
                    (and
                      (at-pos ?r ?pos)
                      (not (has-pos ?m ?pos))
                    ))--"
            })
    {
        std::cout << "-----\n";
        It f = input.begin(), l = input.end();

        AST::Expression precondition;
        bool ok = parse(f, l, pddl_parser::Precondition<It>{}, precondition);

        if (ok) {
            std::cout << "Parsed " << precondition << "\n";
        } else {
            std::cout << "Parse Failed\n";
        }

        if (f != l) {
            std::cout << "Remaining unparsed input: '" << std::string(f, l) << "'\n";
        }
    }
}
#定义BOOST\u SPIRIT\u DEBUG
#包括
#包括
名称空间AST{
使用Atom=std::string;
结构应用;
使用Expression=boost::variant;
结构应用程序{
原子函数;
向量参数;
friend std::ostream&operator>expression];
BOOST_SPIRIT_DEBUG_节点((前提条件)(表达式)(应用程序)(原子))
}
私人:
使用Skipper=qi::ascii::space\u类型;
qi:规则应用;
qi:规则表达;
//词素
规则前提;
规则原子;
};
}
int main(){
使用它=std::string::const_迭代器;
对于(标准::字符串常量和输入):{
R”--(:前提条件)
(及
(在r位置)
(没有(有pos?m?pos))
))--"
})
{

我不能谢谢你,我花了一些时间来理解并集成到我的代码的其余部分,但是现在它像一个符咒一样工作。一个更一般的附加问题:这是最佳实践吗
template <typename Iterator>
struct Precondition : qi::grammar<Iterator, AST::Expression()> {
    Precondition() : Precondition::base_type(precondition) {
        using namespace qi;

        atom         = +(graph - '(' - ')');
        application  = '(' >> atom >> *expression >> ')';
        expression   = atom | application;

        precondition = skip(ascii::space) [":precondition" >> expression];

        BOOST_SPIRIT_DEBUG_NODES((precondition)(expression)(application)(atom))
    }

  private:
    using Skipper = qi::ascii::space_type;
    qi::rule<Iterator, AST::Application(), Skipper> application;
    qi::rule<Iterator, AST::Expression(), Skipper>  expression;

    // lexemes
    qi::rule<Iterator, AST::Expression()> precondition;
    qi::rule<Iterator, AST::Atom()> atom;
};
Parsed (and (at-pos ?r ?pos) (not (has-pos ?m ?pos)))
#define BOOST_SPIRIT_DEBUG
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>

namespace AST {
    using Atom = std::string;

    struct Application;

    using Expression = boost::variant<Atom, Application>;

    struct Application {
        Atom function;
        std::vector<Expression> arguments;

        friend std::ostream& operator<<(std::ostream& os, Application const& a) {
            os << "(" << a.function;
            for (auto& arg : a.arguments)
                os << " " << arg;
            return os << ")";
        }
    };
}

BOOST_FUSION_ADAPT_STRUCT(AST::Application, function, arguments)

namespace pddl_parser {

    namespace qi    = boost::spirit::qi;

    template <typename Iterator>
    struct Precondition : qi::grammar<Iterator, AST::Expression()> {
        Precondition() : Precondition::base_type(precondition) {
            using namespace qi;

            atom         = +(graph - '(' - ')');
            application  = '(' >> atom >> *expression >> ')';
            expression   = atom | application;

            precondition = skip(ascii::space) [":precondition" >> expression];

            BOOST_SPIRIT_DEBUG_NODES((precondition)(expression)(application)(atom))
        }

      private:
        using Skipper = qi::ascii::space_type;
        qi::rule<Iterator, AST::Application(), Skipper> application;
        qi::rule<Iterator, AST::Expression(), Skipper>  expression;

        // lexemes
        qi::rule<Iterator, AST::Expression()> precondition;
        qi::rule<Iterator, AST::Atom()> atom;
    };
}

int main() {
    using It = std::string::const_iterator;

    for (std::string const& input : {
            R"--(:precondition
                    (and
                      (at-pos ?r ?pos)
                      (not (has-pos ?m ?pos))
                    ))--"
            })
    {
        std::cout << "-----\n";
        It f = input.begin(), l = input.end();

        AST::Expression precondition;
        bool ok = parse(f, l, pddl_parser::Precondition<It>{}, precondition);

        if (ok) {
            std::cout << "Parsed " << precondition << "\n";
        } else {
            std::cout << "Parse Failed\n";
        }

        if (f != l) {
            std::cout << "Remaining unparsed input: '" << std::string(f, l) << "'\n";
        }
    }
}