0

我目前正在使用本文所述的正则表达式编写词法分析器:Poor man's "lexer" for C#

虽然它比我已经拥有的要快得多,但我只是不喜欢每个文件仍然花费大约 500 毫秒(使用秒表在 100x36k 令牌的循环中计时)。

在移动我的令牌的优先级之后,我已经将 500 毫秒减半,并且通过向我的大多数令牌添加“简单匹配”布尔值(这基本上意味着它应该使用简单string.Contains(Ordinal)而不是Regex.Match),我获得了额外的 50 毫秒(大约) .

为了获得最佳性能,我显然想摆脱大部分(如果不是全部Regex.Match)电话。为此,我需要一些东西来模拟正则\b表达式中的标签,也就是所谓的单词边界(意味着它应该只匹配整个单词)。

虽然我可以疯狂地编写一个简单的方法来检查我的“简单匹配”之前和之后的字符是否是非单词字符,但我想知道 .NET 是否有这个内置的东西?

如果我最终不得不编写自己的方法,那么最好的方法是什么?在我的单词之后选择字符的索引并检查它的字节值是否低于任何值?任何有关此的提示也将受到欢迎!

4

1 回答 1

1

不知道为什么我最初的问题对我来说被低估了,这似乎很清楚。我不是在修复我的正则表达式之后,因为分析表明即使是最简单的正则表达式仍然比我想要的要多。它可能是一个可怜的人词法分析器,但我仍然希望它尽可能地表现最好。

然而,问题是 .NET 是否有内置词边界的替代方案,如果没有,我将如何在不使用 Regex 的情况下自己实现它。

第一个问题的答案似乎是否定的。

至于第二个,我为这个char类写了一个扩展方法:

public static bool IsWordCharacter(this char character)
{
    return (
        (character >= 'a' && character <= 'z') || 
        (character >= 'A' && character <= 'Z') || 
        (character >= '0' && character <= '9') || 
        character == '_');
}

根据大多数正则表达式文档,这模仿了\w标志(显然用!结果否定了这个方法\W),作为回报,它被用于 in \b,但在结果中没有匹配它。

然后我在类似这样的方法中使用它:

return 
    text.StartsWith(<needle>, StringComparison.Ordinal) 
    && !text[<length of needle>].IsWordCharacter()
        ? <length of needle> 
        : 0;

之后我的底层代码知道它是否必须使用或删除令牌。

免责声明:我知道这不是 的完整实现\b,但它符合我的目的。

此外,在以这种方式转换了我所有的 Regex' 之后,对于完全相同的文件,我从 250 毫秒缩短到了 50 毫秒。对我拥有的所有 110 个脚本文件进行词法分析总共需要不到一秒钟的时间,平均每个文件大约 7 毫秒。

于 2013-10-11T22:32:31.757 回答