Lex/Flex 如何匹配多个用户定义的正则表达式

问题描述

我是编译器的新手,我正在学习使用 Dragon Book(编译器原理)提供的算法来实现扫描器。我已经实现了将正则表达式直接转换为 DFA 的算法 3.36

由于扫描器使用许多正则表达式来定义不同的标记,因此我对 Flex 如何在翻译后处理多个 DFA 感兴趣。一个非常直观的想法是尝试每个 DFA 并模拟 DFA。如果令牌在 DFA 中达到结束状态,则返回相应的令牌标识符。

然而,我也认为这种方法可能比 regex-to-NFA 和 NFA-to-DFA 方法的计算量更大,即使试验可以使用并发线程完成。因为在这方法中,我们可以将所有 NFA 与 $\epsilon$ 动作从开始状态生成并运行该算法以形成完整的 DFA。

非常感谢您的帮助!

解决方法

它将所有 NFA 组合到一台机器中(这是一个微不足道的操作,以至于它实际上不需要任何代码;flex 所做的只是添加新规则作为从开始状态的转换)。然后使用子集构造将组合的 NFA 简化为 DFA。如此构造的机器在几个重要方面与理论 DFA 不同:

  1. 每个接受状态都与规则编号相关联。 (在子集构造中,如果一个状态集包含多个接受状态,则使用最小的规则编号,这意味着机器将接受第一个匹配规则。)

  2. 机器在扫描的时候,每次经过一个接受状态,都会记录那个状态的编号和输入的偏移量。当机器到达 sink 状态(即没有传出转换的状态)时,则将输入备份到记录的偏移量,并返回与记录状态对应的规则编号。 (Flex 有一个优化,可以在 DFA 中的每个状态都接受的情况下避免记录信息。如果您仔细编写您的模式,您可以激活此优化。)