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



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

据我所知,Xpressive是该堆栈的优秀用户。但是,是否存在更具堆栈效率的Xpressive正则表达式方法?

例如,匹配表示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) ?

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

range('0','6')

这是作为一种快速检查来实现的,以查看字符是否在字符范围内。它不使用排序或重复,因此不会占用堆栈空间。

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

一般来说,不要把可以放在一组或一个范围内的东西放在一个替代品中。他们在这方面的效率要高得多。我会注意到,这显然不是一个有效的表达式正则表达式。你会把它写成:

(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

正如我之前所说,重复通常通过递归来实现,以获得正确的回溯。但在这种情况下,expression识别出_d只能吃掉一个字符,并且它正被重复3次。因此,在这种有限的情况下,它是用一个循环来实现的,以节省堆栈空间。这与下一种情况形成对比:

_d >> _d >> _d >> _b

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

短版本:更喜欢可以使用的专用构造,而不是更通用的等价构造。这为expression提供了更多的优化上下文。

此外,了解独立的子表达式。如果你能在keep()中放入一些东西,那就去吧。为什么?keep()匹配一个子表达式,然后回收该子匹配所使用的堆栈空间。这使得不可能通过回溯到该子表达式来尝试不同的东西,但有时你不需要这样。

希望能有所帮助。

最新更新