我正在研究编译器,并且正在学习词汇分析。我理解一个人将每个lexeme指定为正则表达式,并且使用flex
,可以自动生成词法分析器。我正在进一步了解正则表达式如何转换为NFA,然后转换为DFA,可以快速评估它。
但是,我的问题是,如何实施最大规则?在内部,词法分析者如何“继续”找到最长的lexeme?
谢谢!
答案 0 :(得分:4)
最大的munch算法是通过向DFA执行器添加少量可变状态,并添加DFA执行器的能力来“回放”输入来实现的:实际上,它为tell()
提供了函数。和seek()
。
同样值得注意的是,DFA并不完整,因为转换功能尚未完成。某些{state, input}
对没有定义的结果。 [注2]
考虑到这一点,算法如下:
Set Accepted NFA State to ⊥
Set Accepted Position to Tell(Input Stream)
Set State to Starting State
Repeat:
If State ∈ Accepting:
Set Accepted NFA State to Accepting NFA State for State [Note 1]
Set Accepted Position to Tell(Input Stream)
Read one symbol from Input Stream into Next Symbol
If there is a transition from {State, Next Symbol} to New State:
Set State to New State
Continue the loop
Otherwise:
Rewind Input Stream to Accepted Position
Return Accepted NFA State
如果算法返回⊥,则没有识别出令牌,输入流将被重绕到初始位置。
注意:
NFA通常在状态和接受动作之间具有明确的同态,但是DFA构造算法可以将两个接受NFA状态与不同动作组合。在这种情况下,flex算法将优先考虑输入文件中的第一个动作。在上面的算法中,我们通过将每个接受DFA状态映射到接受具有优先级的NFA状态的组件来表示这一点。
通过添加一个不接受并且只有自身转换的附加(且唯一)sink
状态,可以很容易地完成DFA。然后我们可以将sink
状态添加为任何其他未指定的转换的转换。如果我们调用sink
状态⊥那么将很清楚如何修改所提供的算法;在实践中,这根本不是必要的,因为在实践中我们并不关心DFA是不完整的。但它确实对状态最小化算法有一些影响。