是否应将每个可能的 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
,则需要备份输入以便只接受一个点作为标记。
我正在尝试实现确定性有限自动机来为项目创建词法分析器。在 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
,则需要备份输入以便只接受一个点作为标记。