gpt4 book ai didi

c++ - Boost.Spirit.Qi 在将规则分配给包括自身在内的序列时崩溃

转载 作者:太空狗 更新时间:2023-10-29 21:44:25 25 4
gpt4 key购买 nike

我有以下 MWE:

#include <string>

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>

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


int main() {

std::string input("1 2");

qi::rule<std::string::iterator, void(), qi::space_type> parser;
qi::rule<std::string::iterator, void(), qi::space_type> parser2;
qi::rule<std::string::iterator, void(), qi::space_type> parser3;

parser = qi::int_[
std::cerr << phoenix::val("First int: ") << qi::_1 << std::endl
];

parser2 = qi::int_[
std::cerr << phoenix::val("Second int: ") << qi::_1 << std::endl
];

try {
// Comment out these two lines, (finished below ...)
parser3 = parser >> parser2;
phrase_parse(input.begin(), input.end(), parser3, qi::space);

// ... then un-comment these lines, and the program will crash (and no
// exception is caught below).
// parser = parser >> parser2;
// phrase_parse(input.begin(), input.end(), parser, qi::space);
}
catch (...) {
std::cerr << "Exception caught." << std::endl;
}

}

如注释行中所述,如果我将第三个 qi::rule 分配给另外两个规则的序列,并使用第三个规则进行解析,我的程序将按预期工作。但是,如果我将相同的序列分配给序列中的第一条规则,然后使用该第一条规则进行解析,程序将在我运行时崩溃,显然甚至没有抛出异常,因为 catch (...) { . . . block 不执行。

所以我的问题是:关于 'qi::rule 是否有一些规则我应该知道禁止将包含规则的序列分配给相同的规则,或者这次崩溃是由于Boost.Spirit.Qi 中的错误?

意图

澄清一下,根据 cv_and_he 的评论,我在这个小玩具示例背后的目标是弄清楚如何在运行时生成一些动态解析器​​;特别是如何从其计数仅在运行时知道的规则序列生成规则,例如 parser = A1 >> A2 >> ... >> AN;,其中 N 在编译时是未知的,所以我不能用固定数量的 '>>>' 那样硬编码一条规则。这类似于在运行时通过将元素附加到末尾来构建列表,一次一个。

最佳答案

我不确定你想要达到什么目的,但 copy() 似乎就是你想要的

    parser = parser.copy() >> parser2;

查看 Live on Coliru


背景

问题是 Qi 通过引用获取非终结符,所以你得到了 PEG 语法建议的解析器语义。

除此之外,Proto 表达式树(表达式模板)确实通过引用获取它们的一些参数。

这两者的结合有可能真正把你的生活搞得一团糟,尤其是在动态构造解析器的时候。简而言之,我认为,在

  • 使用继承的属性
  • qi::symbols(包括 Nabialek 技巧)

Spirit V2 不支持动态构建规则。 Proto x11/Spirit X3 可能会改善这一点。

在这里查看更多背景:


示例代码

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>

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


int main() {

std::string input("1 2");

qi::rule<std::string::iterator, void(), qi::space_type> parser;
qi::rule<std::string::iterator, void(), qi::space_type> parser2;
qi::rule<std::string::iterator, void(), qi::space_type> parser3;

parser = qi::int_[
std::cerr << phoenix::val("First int: ") << qi::_1 << std::endl
];

parser2 = qi::int_[
std::cerr << phoenix::val("Second int: ") << qi::_1 << std::endl
];

try {
// Comment out these two lines, (finished below ...)
parser3 = parser >> parser2;
phrase_parse(input.begin(), input.end(), parser3, qi::space);

parser = parser.copy() >> parser2;
phrase_parse(input.begin(), input.end(), parser, qi::space);
}
catch (...) {
std::cerr << "Exception caught." << std::endl;
}

}

关于c++ - Boost.Spirit.Qi 在将规则分配给包括自身在内的序列时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20158897/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com