接受正则表达式并生成NFA(Java)

时间:2012-09-22 02:14:44

标签: java regex parsing nfa

我正在尝试编写一个程序来接受描述正则表达式的字符串。例如:

10(0U1)*

其中U是联合运算符,*是Kleene星(我们也看到隐含的连接)。

我考虑过对字符串的原子进行标记,并根据运算符和操作数构建机器。我希望在算法上对每个原子进行操作,使用与此类似的规则:http://www.cs.may.ie/staff/jpower/Courses/Previous/parsing/node5.html

我不确定如何以智能方式最好地解析此类输入,以便我可以以编程方式构建NFA。

我的程序的目标是接受上述输入并输出将由其5-touple描述的相应NFA。任何关于实现这一目标的建议都非常感谢。

1 个答案:

答案 0 :(得分:2)

如果你可以使用外部库,你最好有一个现代的解析器生成器,如ANTLR做所有的解析工作,并为你的正则表达式提供一个抽象的语法树,即使它是一个相对简单的语言

否则,如果你需要从头开始编写,你需要先弄清楚你是否需要一个标记器(或“词法分析器”)。如果你的语言是由一个char标记组成的(如你的例子中所示),那么你可以安全地跳过编写一个标记器,然后循环遍历字符串中的字符。然后你必须编写解析器,一个扫描令牌列表并构建语法树的大循环。

在任何情况下,对于您的示例10(0U1)*,您最终都应该使用这样的语法树:

syntax tree

请注意,在语法树中,所有括号和隐式优先级规则都消失了,它们将被树的结构所取代。

之后,您必须以递归方式将树转换为NFA图。

这是一种可能的方式的粗略草图。

为每种语法节点类型编写翻译方法。将以其起始和结束NFA状态作为参数调用该方法,后者是可选的。该方法将绘制自己的图形片段,适当地调用其子元素的转换方法,并返回其结束状态(可能已将其作为参数省略,因此其调用者不知道。)

  • 创建一个开始状态并为语法树的根节点调用转换方法,并将其作为起始状态传递给它。
  • 文字语法节点(在您的示例中为0和1)将从其起始状态到结束状态绘制箭头,如果未提供,则创建新的结束状态:
    enter image description here
  • 星型节点将调用其子节点的转换方法,将其自身的起始状态作为子节点的起始和结束状态(以便NFA能够根据需要多次“循环”此状态。)< / LI>
  • concat节点将调用第一个子节点,使其处于起始状态但没有结束状态;然后它将召唤第二个孩子,将第一个孩子的结束状态作为起始孩子;依此类推,建立一个单向的子图序列,每个孩子一个。

你应该明白这一点。

将NFA图构建为状态的链接结构(并可能将其显示为实际图形,以便进行调试或记录),您可以将其转换为正式元组并输出。