是否应将每个可能的 Ascii 字符添加到有限自动机的转换 Table

Should every possible Ascii Character be added to a Transition Table for a Finite Automaton

我正在尝试实现确定性有限自动机来为项目创建词法分析器。在 C++ 中创建转换 table 时,我创建了一个映射,它使用当前状态作为键,并将可能的转换作为另一个映射存储在值中。我是否必须为所有状态的每个可能输入遍历并添加每个可能的转换,或者是否有更有效的方法来完成此任务?

有很多可用的优化。

如果从当前状态到当前输入字符没有转换,那么词法分析器已经找到匹配项(但它可能不在当前输入点,见下文)。因此,您可以选择将转换存储到特殊的“拒绝”状态,或者根本不存储转换并使用“拒绝”作为默认查找值。如果您使用的是地图,那么不存储非过渡是有道理的。但通常最好使用更高效的数据类型向量(或固定大小的数组),并在索引中使用字符代码作为整数。

无论哪种方式,您几乎总是可以显着减少 table 大小,方法是根据该字符的一组转换将字符分组为等价的 classes。 (也就是说,如果每个状态在两个字符上都有相同的转换,或者在任何一个字符上都没有转换,则两个字符具有相同的等价性 class。)等价性 classes 可以表示为 small整数;在典型的词法语法中,即使使用 Unicode 字符集,也有五十或六十个等价 classes,这比 256 个 8 位字符少很多,也比超过一百万个 Unicode 字符少得多。

转换table可以压缩更多;大多数相关教科书中都描述了标准压缩技术。但是现在内存足够便宜,等价 class 压缩可能就足够了。

另一个问题是知道当您遇到没有有效转换的状态时该怎么做。通常不能保证当前状态是接受状态,因此您可能必须备份输入光标。

举个简单的例子,考虑像 C 这样的语言,其中 .... 是标记,但 .. 不是。结果,输入:

a.b       => VAR(a) '.' VAR(b)
a..b      => VAR(a) '.' '.' VAR(b)
a...b     => VAR(a) '...' VAR(b)

如果处理的输入是..并且下一个字符是b,则需要备份输入以便只接受一个点作为标记。