从正则表达式创建NFA的步骤

时间:2012-08-05 18:58:16

标签: theory compiler-theory nfa

从正则表达式创建NFA时,我遇到了“描述每个步骤”的问题。问题如下:

将以下正则表达式转换为非确定性有限状态自动机(NFA),清楚地描述您使用的算法的步骤: (B | A)* B(A | B)

我制作了一个简单的三态机器,但它非常直观。 这是我的讲师在过去的考试中提出的一个问题,他也写了以下Thompson算法的解释:http://www.cs.may.ie/staff/jpower/Courses/Previous/parsing/node5.html

任何人都可以清楚地“清楚地描述每一步”吗?它看起来像是一组基本规则,而不是一个步骤可以遵循的算法。

也许我已经在某个地方掩饰了一种算法,但到目前为止,我只是用一种有根据的猜测来创建它们。

3 个答案:

答案 0 :(得分:62)

一般方法的简短版本。
有一个算法称为Thompson-McNaughton-Yamada构造算法,有时只是“Thompson Construction”。一个构建中间NFA,沿着路径填充碎片,同时尊重运算符优先级:第一个括号,然后是Kleene Star(例如,a *),然后是连接(例如,ab),然后是交替(例如,a | b)。

以下是构建(b | a)* b(a | b)的NFA

的深入演练

构建顶级

  1. 处理括号。注意:在实际实现中,通过对其内容的递归调用来处理括号是有意义的。为了清楚起见,我会推迟对parens内部任何内容的评估。

  2. Kleene Stars:只有一个*,所以我们建立一个名为P的占位符Kleene Star机器(后来将包含b | a)。 中间结果:
    Non-Deterministic Finite Automata for P*

  3. 连接:将P附加到b,并将b附加到名为Q的占位符机器(将包含(a | b)。中间结果:
    Non-Deterministic Finite Automata for P*bQ

  4. 括号外没有替换,所以我们跳过它。

  5. 现在我们坐在P * bQ机器上。 (请注意,我们的占位符P和Q只是连接机器。)我们用BFA替换P边缘为b | a,并通过递归应用上述步骤将Q边缘替换为NFA用于| b。


    构建P

    1. 跳过。没有parens。

    2. 跳过。没有Kleene明星。

    3. 跳过。没有连接。

    4. 为b | a构建交替机器。中间结果:
      NFA for b or a


    5. 整合P

      接下来,我们回到那台P * bQ机器,我们撕掉了P边缘。我们将P边缘的用作P机器的起始状态,并且P边缘的目的地用作P机器的目标状态。我们也使该州拒绝(剥夺其作为接受国的财产)。结果如下:
      enter image description here


      构建Q

      1. 跳过。没有parens。

      2. 跳过。没有Kleene明星。

      3. 跳过。没有连接。

      4. 为a | b构建交替机器。顺便说一下,交替是可交换的,因此a | b在逻辑上等价于b | a。 (阅读:从懒惰中跳过这个小脚注图。)


      5. 整合Q

        除了用我们构建的机器中间体b替换Q边缘之外,我们用上面的P做了。结果如下:
        enter image description here

        多田!呃,我的意思是,QED。


        想知道更多?

        以上所有图片均使用an online tool for automatically converting regular expressions to non-deterministic finite automata生成。您可以在线找到source code for the Thompson-McNaughton-Yamada Construction algorithm

        该算法也在Aho's Compilers: Principles, Techniques, and Tools中得到解决,尽管其解释在实现细节上很少。你也可以向优秀的Russ Cox学习an implementation of the Thompson Construction in C,他在一篇关于regular expression matching的热门文章中详细描述了它。

答案 1 :(得分:1)

在下面的GitHub存储库中,您可以找到Thompson构造的Java实现,首先从正则表达式创建NFA,然后输入字符串与该NFA匹配:

https://github.com/meghdadFar/regex

答案 2 :(得分:0)

https://github.com/White-White/RegSwift

没有多余的单词。查看此存储库,它将您的正则表达式转换为NFA,并直观地显示NFA的状态转换。