Boost.SSpirit.Qi在将规则分配给包括自身在内的序列时崩溃
Boost.Spirit.Qi crashes when assigning rule to a sequence including itself
我有以下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::规则分配给另外两个规则的序列,并使用第三个规则进行解析,我的程序将按预期工作。然而,如果我将相同的序列分配给序列中的第一条规则,然后使用第一条规则进行解析,那么当我运行程序时,程序将崩溃,显然甚至没有抛出异常,因为catch (...) { . . . }
块没有执行。
因此,我的问题是:关于"qi::rule
"的我应该知道的规则是否禁止将包含规则的序列分配给同一规则,或者这次崩溃是由于Boost.SSpirit.Qi中的错误造成的?
意向
为了澄清,根据cv_and_he的评论,我在这个小玩具示例背后的目标是弄清楚如何在运行时生成一些动态解析器;特别是如何从一系列规则中生成规则,这些规则的计数只在运行时知道,例如parser = A1 >> A2 >> ... >> AN;
,其中N
在编译时是未知的,所以我不能用这种方式硬编码一个固定数量为">>
"的规则。这类似于在运行时通过一次一个地在末尾添加元素来构建列表。
我不确定你想要实现什么,但copy()似乎是你追求的目标
parser = parser.copy() >> parser2;
查看Coliru直播
背景
问题是Qi通过引用获取非终端,因此您可以获得PEG语法所建议的语法分析器语义。
除此之外,Proto表达式树(表达式模板)确实引用了它们的一些参数。
这两者结合在一起可能会真正扰乱你的生活,尤其是当构建解析器动态时。简而言之,我认为,在之外
- 使用继承的属性
- 和qi::符号(包括Nabialek技巧)
在Spirit V2中,动态构建规则并没有得到很好的支持。Proto x11/Spirit X3可能会让这一点变得更好。
点击此处查看更多背景:
- C++Boost qi递归规则构造
- 从替代语法分析器表达式的可变列表生成Spirit语法分析器表达式
- Boost Spirit规则可以参数化吗
示例代码
#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;
}
}
相关文章:
- 当回溯以零开始时,如何调试崩溃
- 内联映射初始化的动态atexit析构函数崩溃
- 执行函数时导致崩溃的变量
- 程序崩溃并显示"std::out_of_range"错误
- CoInitialize()在单独的线程上崩溃而不返回
- 使用调试/崩溃报告将应用程序部署到客户端
- 为什么所有C++编译器都会崩溃或挂起此代码
- 为什么lambda在clang上崩溃而不是在gcc上崩溃
- 为什么我的多线程作业队列崩溃
- ExtractIconEx:可以工作,但偶尔会崩溃
- 为什么引用传递会导致此崩溃(C++)
- 试图创建流或fopen时程序崩溃
- 类对象数组的问题会导致崩溃
- 排序时无法执行交换操作.我做的时候它会崩溃.为什么
- 为什么要增加导致崩溃的指针
- 在虚幻引擎中删除NXOpen对象时崩溃
- 为什么它只打印双链接列表的第一个值,而我的程序却崩溃了
- 应用程序崩溃并显示"symbol _ZdlPvm, version Qt_5 not defined in file libQt5Core.so.5 with link time reference"
- Visual Studio在尝试读取resource.txt文件时崩溃
- Boost.SSpirit.Qi在将规则分配给包括自身在内的序列时崩溃