c – boost :: spirit的规则的复制或引用语义?

前端之家收集整理的这篇文章主要介绍了c – boost :: spirit的规则的复制或引用语义?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图在Boost.Spirit中编写一个 shell语言解析器.但是,我不清楚关于规则语义的一些基本问题.

看文档,有成员r.alias()和r.copy()的规则.国际红十字会,这些成员应分别返回规则的引用和规则内容的副本.但是,当我在另一个规则的定义中使用规则时,没有明确规定会发生什么.从我的实验,我发现相互递归的规则可以定义为:

rule<Iter> r1,r2;
r1 = ... >> r2 >> ...;
r2 = ... >> r1 >> ...;

这表明规则在解析器表达式中被引用.问题是,当变量超出范围时,它会做什么,例如:

rule<Iter> r1;
{ 
  rule<Iter> r2;
  r1 = ... >> r2 >> ...;
  r2 = ... >> r1 >> ...;
}
... // use r1

在同一个注释中,将从包含类型规则工作(r.copy())的值的解析表达式分配给一个规则也将是类型规则的值,不是吗?例如.

rule<Iter> f() { return char_('a') << char_('b'); }
rule<Iter> r1 = ... << f();

任何人都可以启发我关于规则副本和引用的详细语义,并可能纠正这个帖子中的任何误解?

解决方法

答案取决于你所指的圣灵版本.

Spirit.Classic(前Spirit V1.x)实现规则的特殊复制语义.文件说:

When a rule is referenced anywhere in
the right hand side of an EBNF
expression,the rule is held by the
expression by reference. It is the
responsibility of the client to ensure
that the referenced rule stays in
scope and does not get destructed
while it is being referenced.

赋值运算符基本上引用了rhs规则,而不创建深层副本.这样做是为了允许:

rule<> r1,r2;
r1 = ...;
r2 = r1;

但事实证明是高度的混乱,因为它阻止了与“正常”对象相同的处理规则.

因此,有一个成员函数rule :: copy(),允许做一个规则的明确的深层拷贝(例如将它们存储在STL容器中).

同时这个:

r2 = r1.copy();

是纯粹的错误r2将引用从函数copy()返回的r1的(被破坏的)临时副本.

在Spirit.Qi(即Spirit V2.x)中,行为被部分改变.规则现在在解析器之外处理时按预期的方式运行.您可以将它们正常存储在容器中(赋值操作符暴露预期的行为).但是要注意的是,解析器内部的表达式规则仍然被引用保留,这仍然允许以与之前相同的方式引用规则:

rule<> r1,r2;
r1 = ... >> r2 >> ...;
r2 = ... >> r1 >> ...;

有时有必要制作一个规则的深层副本,所以还有成员函数副本.

更改的副本语义有另一个副作用.构造如:

r1 = r2;

现在正在创建一个(深)的r2副本,这可能不是你期望的,特别是如果r2只有在被分配到r1之后才能分配它的rhs.由于这个原因,有一个新的成员函数别名启用此角色的参考语义:

r1 = r2.alias();

无论如何,在两个版本的Spirit中,如果从解析器表达式引用的规则的一部分超出范围,您将最终得到悬挂引用.

BTW,Spirit版本都不实现函数rule :: ref().

猜你在找的C&C++相关文章