只要模式是完整的单词:你不想or
匹配storage
;空格和标点符号是匹配锚,那么一个简单的方法是将您的词典转换为扫描仪生成器输入(例如您可以使用flex),生成一个扫描仪,然后在您的输入上运行它。
扫描器生成器旨在识别输入中出现的标记,其中每个标记类型由正则表达式描述。Flex 和类似程序可以快速创建扫描仪。默认情况下,Flex 最多可以处理 8k 条规则(在您的情况下是词典条目),并且可以扩展。生成的扫描仪以线性时间运行,实际上速度非常快。
在内部,令牌正则表达式在标准的“Kleene 定理”管道中进行转换:首先转换为 NFA,然后转换为 DFA。然后将 DFA 转换为其唯一的最小形式。这是在 HLL 表中编码的,该表在通过引用表来实现扫描器的包装器内发出。这就是 flex 所做的,但其他策略也是可能的。例如,可以将 DFA 转换为goto
代码,其中 DFA 状态在代码运行时由指令指针隐式表示。
space-as-anchors 警告的原因是,由像 Flex 这样的程序创建的扫描仪通常无法识别重叠匹配: 例如,strangers
不能同时匹配strangers
和range
。
这是一个与您提供的示例词典相匹配的 flex 扫描器:
%option noyywrap
%%
"good" { return 1; }
"bad" { return 2; }
"freed"[[:alpha:]]* { return 3; }
"careless"[[:alpha:]]* { return 4; }
"great"[[:space:]]+"loss" { return 5; }
. { /* match anything else except newline */ }
"\n" { /* match newline */ }
<<EOF>> { return -1; }
%%
int main(int argc, char *argv[])
{
yyin = argc > 1 ? fopen(argv[1], "r") : stdin;
for (;;) {
int found = yylex();
if (found < 0) return 0;
printf("matched pattern %d with '%s'\n", found, yytext);
}
}
并运行它:
$ flex -i foo.l
$ gcc lex.yy.c
$ ./a.out
Good men can only lose freedom to bad
matched pattern 1 with 'Good'
matched pattern 3 with 'freedom'
matched pattern 2 with 'bad'
through carelessness or apathy.
matched pattern 4 with 'carelessness'