哪种Xpressive方法最好减少堆栈使用

时间:2012-10-05 15:08:50

标签: regex optimization boost-xpressive

我在当前的嵌入式C ++项目中广泛使用Xpressive。

据我所知,Xpressive是一个很好的用户。但是,Xpressive正则表达式方法是否具有更高的堆栈效率?

E.g。匹配表示32位整数的字符串的正则表达式可能需要测试数字6是否小于或等于6。

Xpressive(以及其他正则表达式引擎,我知道)允许多种方法,例如:

range('0','6')

('0'|'1'|'2'|'3'|'4'|'5'|'6')

set['0'|'1'|'2'|'3'|'4'|'5'|'6']

然后正则表达式可以允许3个以下数字,例如:

repeat<3>(_d) >> _b

_d >> _d >> _d >> _b

但是,考虑到选择,而不是过多关注源代码布局,哪种方法最适合:

a)堆栈;

b)速度;

c)?

1 个答案:

答案 0 :(得分:2)

排序和重复使用堆栈,因为它们需要回溯。我们来看看你的例子。

range('0','6')

这是作为快速检查来实现的,以查看角色是否属于角色范围。它不使用排序或重复,因此它不会吞噬堆栈空间。

('0'|'1'|'2'|'3'|'4'|'5'|'6')

一般情况下,不要放置可以置于一组或一个范围内的替代品。对于这种事情,它们更有效率。我会注意到,这显然不是一个有效的xpressive正则表达式。你会把它写成:

(as_xpr('0')|'1'|'2'|'3'|'4'|'5'|'6')

我相信你知道的。我将对此进行类似的编辑:

set[as_xpr('0')|'1'|'2'|'3'|'4'|'5'|'6']

设置很快。它们被实现为ascii范围的查找表和(对于Unicode)256以上字符代码的稀疏向量。由于某些集的稀疏性,此方案可占用比简单范围更多的堆空间。但这不会影响匹配时使用的堆栈空间量。我会注意到你也可以把它写成:

(set= '1','2','3','4','5','6')

现在重复:

repeat<3>(_d) >> _b

正如我之前所说的,重复通常是通过递归实现的,以便正确地进行回溯。但在这种情况下,xpressive认识到_d只能吃掉一个字符,并且它正在被重复3次。所以在这个有限的情况下,它是用一个循环来实现的,以节省堆栈空间。这与下一个案例形成鲜明对比:

_d >> _d >> _d >> _b

Xpressive不够聪明,不能像_d >> _d >> _d那样对待repeat<3>(_d)。因此,这将为每个_d使用单独的堆栈帧。

短版本:更喜欢专门的结构,你可以使用它们更通用的等价物。这为优化提供了更多的上下文。

此外,了解独立的子表达式。如果您可以在keep()中添加内容,请选择它。为什么? keep()匹配子表达式,然后回收该子匹配使用的堆栈空间。这使得通过回溯到该子表达式来尝试不同的事情是不可能的,但有时你不需要那样。

希望有所帮助。