语义操作在 boost::spirit 解析中运行多次
Semantic actions runs multiple times in boost::spirit parsing
我试图在使用 boost::spirit 解析时使用语义规则创建 AST。
必须只为输入的一部分构建 AST,输入的另一部分应该在没有语法树的情况下进行解析。
例如,对于这样的输入字符串:"self.usedFoo(Bar).filter(self.baz > baz)" 或 "self.Foo.filter(true)" 应该只为粗体部分构建 AST。
还有一个问题:解析器多次运行解析语法和调用语义操作(instatntiating AST 节点)也多次,所以我遇到了严重的内存泄漏。
简化的源代码:
语法:
line = stmt | stmt >> "filter.(" >> filter >> ')';
filter %= (filterterm)
filterterm %= (filterfactor)
filterfactor = value [phoenix::bind(&ValueFilterSemanticNode::Instantiate, qi::_val, qi::_1)];
实例化节点:
static void ValueFilterSemanticNode::Instantiate(QVariant &res, QVariant &value)
{
qDebug() << " Creating new Value Node...";
ValueFilterSemanticNode *n = new ValueFilterSemanticNode();
qDebug() << " " << n;
n->value = QVariant(value.toInt());
res = QVariant::fromValue(n);
}
输入:
self.filter(1)
调试出来:
Creating new Value Node...
0x22fdfd0
Creating new Value Node...
0x22fe030
Creating new Value Node...
0x22fde50
[...many many lines...]
Creating new Value Node...
0x22fe238
Creating new Value Node...
0x22fe218
Running Filter test
Value node running... 0x22fe218
Check result = QVariant(int, 1)
因此,如您所见,节点实例化次数过多导致内存泄漏。
即使稍后回溯,语义操作也会触发。
解析器表达式可能会抛出异常。
仅出于这些原因,在语义操作中进行动态分配并不是一个好主意。如果需要,使用智能指针(尽管这仍然是低效的)。
见
- Boost Spirit: "Semantic actions are evil"?
- How can I use polymorphic attributes with boost::spirit::qi parsers?
我试图在使用 boost::spirit 解析时使用语义规则创建 AST。 必须只为输入的一部分构建 AST,输入的另一部分应该在没有语法树的情况下进行解析。
例如,对于这样的输入字符串:"self.usedFoo(Bar).filter(self.baz > baz)" 或 "self.Foo.filter(true)" 应该只为粗体部分构建 AST。
还有一个问题:解析器多次运行解析语法和调用语义操作(instatntiating AST 节点)也多次,所以我遇到了严重的内存泄漏。
简化的源代码:
语法:
line = stmt | stmt >> "filter.(" >> filter >> ')';
filter %= (filterterm)
filterterm %= (filterfactor)
filterfactor = value [phoenix::bind(&ValueFilterSemanticNode::Instantiate, qi::_val, qi::_1)];
实例化节点:
static void ValueFilterSemanticNode::Instantiate(QVariant &res, QVariant &value)
{
qDebug() << " Creating new Value Node...";
ValueFilterSemanticNode *n = new ValueFilterSemanticNode();
qDebug() << " " << n;
n->value = QVariant(value.toInt());
res = QVariant::fromValue(n);
}
输入:
self.filter(1)
调试出来:
Creating new Value Node...
0x22fdfd0
Creating new Value Node...
0x22fe030
Creating new Value Node...
0x22fde50
[...many many lines...]
Creating new Value Node...
0x22fe238
Creating new Value Node...
0x22fe218
Running Filter test
Value node running... 0x22fe218
Check result = QVariant(int, 1)
因此,如您所见,节点实例化次数过多导致内存泄漏。
即使稍后回溯,语义操作也会触发。
解析器表达式可能会抛出异常。
仅出于这些原因,在语义操作中进行动态分配并不是一个好主意。如果需要,使用智能指针(尽管这仍然是低效的)。
见
- Boost Spirit: "Semantic actions are evil"?
- How can I use polymorphic attributes with boost::spirit::qi parsers?