1

我在我当前的嵌入式 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) ?

4

1 回答 1

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 >> _drepeat<3>(_d). 因此,这将为每个_d.

短版:更喜欢专门的构造,而不是更通用的构造。这为优化提供了更多的上下文。

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

希望有帮助。

于 2012-10-05T23:43:21.930 回答