maximal-munch是如何实现的?

时间:2013-11-22 10:33:22

标签: regex parsing unix compiler-construction flex-lexer

我正在研究编译器,并且正在学习词汇分析。我理解一个人将每个lexeme指定为正则表达式,并且使用flex,可以自动生成词法分析器。我正在进一步了解正则表达式如何转换为NFA,然后转换为DFA,可以快速评估它。

但是,我的问题是,如何实施最大规则?在内部,词法分析者如何“继续”找到最长的lexeme?

谢谢!

1 个答案:

答案 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

如果算法返回⊥,则没有识别出令牌,输入流将被重绕到初始位置。


注意:

  1. NFA通常在状态和接受动作之间具有明确的同态,但是DFA构造算法可以将两个接受NFA状态与不同动作组合。在这种情况下,flex算法将优先考虑输入文件中的第一个动作。在上面的算法中,我们通过将每个接受DFA状态映射到接受具有优先级的NFA状态的组件来表示这一点。

  2. 通过添加一个不接受并且只有自身转换的附加(且唯一)sink状态,可以很容易地完成DFA。然后我们可以将sink状态添加为任何其他未指定的转换的转换。如果我们调用sink状态⊥那么将很清楚如何修改所提供的算法;在实践中,这根本不是必要的,因为在实践中我们并不关心DFA是不完整的。但它确实对状态最小化算法有一些影响。