unix maximal-munch是如何实现的?

nkhmeac6  于 2023-04-11  发布在  Unix
关注(0)|答案(1)|浏览(125)

我正在学习编译器,学习词法分析。我知道一个将每个词素指定为正则表达式,并使用flex,可以自动生成词法分析器。我正在进一步学习如何将正则表达式转换为NFA,然后将其转换为DFA,在那里可以快速评估。
然而,我的问题是,maximal-munch规则是如何实现的?在内部,词法分析器如何知道“继续”找到最长的可能的词素?

8e2ybdfx

8e2ybdfx1#

最大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状态Map到具有优先级的接受NFA状态的组件来表示这一点。
    1.通过添加一个额外的(且唯一的)sink状态来完成DFA是很容易的,该状态是不可接受的,并且只具有到自身的转换。然后我们可以添加sink状态作为任何其他未指定转换的转换。如果我们调用sink状态,那么将清楚如何修改提供的算法;在实践中,这是完全没有必要的,因为在实践中,我们不关心DFA是不完整的,但它确实对状态最小化算法有一些影响。

相关问题