Compiler construction 如何使用有限自动机实现扫描仪

Compiler construction 如何使用有限自动机实现扫描仪,compiler-construction,lexical-analysis,finite-automata,Compiler Construction,Lexical Analysis,Finite Automata,我正在制作一个简单的扫描仪。假设为我的语言定义了以下标记: !, !=, !==, <, <<, { !,!=,!= 最常见的规则是“maximalmunch”,它总是选择尽可能长的令牌 一般来说,使用DFA扫描单个令牌的算法如下:(要对输入进行令牌化,重复此算法,直到到达输入端,每次扫描从上一次扫描留下的输入光标开始。) 将DFA状态设置为启动状态。然后,对于顺序中的每个输入字符: 如果DFA在角色上有转换,则移动到IIindicated状态。如果该状态为接受状态,则记录

我正在制作一个简单的扫描仪。假设为我的语言定义了以下标记:

!, !=, !==, <, <<, {
!,!=,!= 最常见的规则是“maximalmunch”,它总是选择尽可能长的令牌

一般来说,使用DFA扫描单个令牌的算法如下:(要对输入进行令牌化,重复此算法,直到到达输入端,每次扫描从上一次扫描留下的输入光标开始。)

将DFA状态设置为启动状态。然后,对于顺序中的每个输入字符:

  • 如果DFA在角色上有转换,则移动到IIindicated状态。如果该状态为接受状态,则记录当前输入光标和状态编号

  • 否则,将输入倒回上次记录的接受位置,并返回记录的状态编号

这里,接受状态号用于指示遇到了哪个令牌。在实践中,通常会将每个接受状态与令牌代码关联,因为某些令牌类型将具有多个接受状态

并不总是需要使用上述回溯算法。在某些情况下,对DFA的分析将表明,最后一个接受状态始终位于紧接前的输入位置。但是,许多语言需要回溯


例如,
..
都是标记但不是
的语言(如C)必须在输入
.1
时回溯,该输入应标记为
.1
。在该输入的标记化过程中,第一次扫描将接受第一次
,继续第二次
(不是接受状态),然后在输入
1
上找不到转换。然后,它将报告它找到了一个
(记录的已接受标记),并将输入光标重置到第二个字符位置,以便下次扫描将看到标记
.1

您到底在问什么?@melpomene,我的问题是如何处理这些机器?如何解析许多标记的实际字符串?你是在要求我们为你编写代码吗?@melpomene,这个方法,我不提代码。如果你不是在谈论代码,那么我不知道你所说的“方法”是什么意思。我真的看过一篇论文,讲的是一种可以在O(n)中实现基于正则表达式的最大munch标记化的算法(也就是说,没有回溯)。它只是没有在实践中使用。@sepp2k:如果你有一个参考,我很乐意看到它。我不相信O(N)词法在恒定空间中是可能的,但我很高兴被证明是错误的。(如果你放松空间限制,那么它应该是可行的,但那就没那么有趣了。)在实际语言中,通过添加诸如未终止字符串和注释之类的模式,通常可以将回溯限制为O(1)个字符,在这种情况下,标记化是O(N)。因此,使用更复杂算法的动机是有限的。@rici,非常感谢。我发现:dfa应该一直运行,直到达到当前状态S在下一个字符上没有传出转换的点。此时,实现必须决定它匹配了哪个正则表达式。如果S是接受状态te,则dfa已在该语言中找到一个单词,并应报告该单词及其语法类别。否则,如果dfa在前往S的途中经过一个或多个接受状态,则识别器应返回到最新的此类状态。此策略匹配输入字符串中最长的有效前缀。如果它从未到达接受状态状态,则输入字符串的前缀不是有效单词,识别器应报告错误。这似乎正是您在回答中建议的,对吗?
!=?=? | { | <<?
!!=!<!==<<!{