boost::spiritqi解析运行时出错
boost::spirit qi parsing runtime error
为什么在使用该语法解析字符串时出现运行时错误?
template <typename Iterator, typename Skipper>
struct grammar : qi::grammar<Iterator, QVariant(), Skipper>
{
grammar() : grammar::base_type(object)
{
identifier = qi::raw[qi::lexeme[qi::alpha >> *(qi::alnum | '_' | ('-' >> qi::alnum))]];
self = (qi::raw[qi::lexeme["self"]]);
object = (self >> '.' >> identifier)
|(object >> '.' >> identifier); // there is no runtime error without that line
}
}
任何其他语法都很好,但我想解析这样的东西:
self.foo.bar2.baz
出现运行时错误
qi::phrase_parse(it, str.end(), g, ascii::space, v) && it == str.end())
呼叫。
在我看来,作为起点的object
规则必须声明为
qi::rule<It, QVariant(), Skipper> object;
虽然我不知道QVariant是什么,但我知道这一点:
为了使属性传播起作用,您需要使用内置的Qi转换启发法具有属性类型兼容性。
对于第一个分支(self>>'.'>>identifier
)来说,这可能足够简单。假设identifier
合成了一个字符串兼容的属性(例如std::string
或std::vector<char>
),则生成的属性可以合法地分配为字符串。
样品
作为一个简单的例子,看看这个(我"模仿"QVariant
可能是什么):
在Coliru上直播
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
using QVariant = boost::variant<std::string, int>;
template <typename Iterator, typename Skipper>
struct grammar : qi::grammar<Iterator, QVariant(), Skipper>
{
grammar() : grammar::base_type(object)
{
identifier = qi::raw[qi::lexeme[qi::alpha >> *(qi::alnum | '_' | ('-' >> qi::alnum))]];
self = (qi::raw[qi::lexeme["self"]]);
object =
qi::as_string [self >> '.' >> identifier]
//|qi::as_string [object >> '.' >> identifier] // there is no runtime error without that line
;
}
private:
qi::rule<Iterator, QVariant(), Skipper> object;
qi::rule<Iterator, std::string(), Skipper> identifier;
qi::rule<Iterator, std::string(), Skipper> self;
};
int main() {
using It = std::string::const_iterator;
std::string input = "self.foo.bar2.baz";
It f = input.begin(), l = input.end();
QVariant parsed;
bool ok = qi::phrase_parse(f, l, grammar<It, qi::space_type>{}, qi::space, parsed);
if (ok)
std::cout << "Parsed: " << parsed << "n";
else
std::cout << "Parse failedn";
if (f!=l)
std::cout << "Remaining unparsed: '" << std::string(f,l) << "'n";
}
打印:
Parsed: selffoo
Remaining unparsed: '.bar2.baz'
问题
第二分支
qi::as_string [object >> '.' >> identifier]
必须合成为tuple<QVariant, std::string>
才能与其余声明一致。Spirit没有办法自动改变这一点。启发式系统可能会开始抓住救命稻草,并尝试将绑定属性(记住,这是神秘的QVariant)视为一个容器。如果它在这方面成功,事情就会编译。显然,在运行时,事情会崩溃,因为QVariant的实际运行时值调用了不正确的接口。
这就是理论。
解决方案
查看工作演示,注意'.'
被排除在外。这让我怀疑,您实际上不想要任何复杂的对象取消引用的链式"列表",而是可能只想将整个匹配的输入视为原始字符串?在这种情况下,最简单的解决方案是将raw[]
提升一个级别,并可能使用字符串而不是QVariant
。
例如,因为QVariant接口有点草率/不安全,并且直接在variant接口上暴露.beggin/.end/value_type/插入成员?
像"A=(A>>A)|b"这样的左递归在boost::spirit这样的LL解析器中是不可用的。它们应该转换为LL友好的形式:A=bRR=aR|e其中R-新的非终端和e-ε(空终端)。
- 分段错误当我试图运行程序时出错
- 运行命令 "rosbag play example.bag" 时出错。找不到与插件 rosbag/NoEncryptor 对应的库
- 从反向顺序C++访问矢量时运行时出错
- 合并两个排序链表时运行时出错
- 从主线程中询问运行对象表 (ROT) 时出错
- 在VS2015中访问类成员时运行时错误,但在Linux上未访问时出错
- 在 Qt 中将 x 可执行文件作为按钮事件运行时出错
- 运行时动态加载库时出错"unresolved external symbol"
- 尝试使用浮点参数运行重载函数时出错
- 可执行文件在运行时出错
- 在 Eclipse.It 中运行C++代码时出错,'Your program cannot output..'
- OpenCV C++代码在终端中运行良好,但在从Ubuntu 12.04运行时出错
- C++程序生成成功,但在运行时出错
- boost::spiritqi解析运行时出错
- 为我的生成文件运行时出错.cpp
- 确保程序在运行时出错时在 C++/fortran 中的适当位置崩溃
- C++ 传递 2D 数组以运行时出错
- Mysterios Malloc 在运行时出错
- 运行时出错,在线判断上的退出代码为6
- 如何修改C++运行时出错的字符串