我需要NFA用于正则表达式
(a+b)?c
据我所知,它应该包含从最后一个节点之前的零节点到节点的epsilon(例如,匹配字符串“c”)。
要查看我的NFA,请使用“Regular Expression to NFA Visializaton web service”, 但我的正则表达式在此服务上的图形不包含来自零节点的epsilon。
是服务中的错误,还是我误解了什么?
谢谢!
答案 0 :(得分:4)
好像是一个错误。如果我尝试使用相同语言的(aa*b)?c
,则NFA看起来非常不同(并且正确)。此外,当我尝试使用自动化库时,我不久前开发了自己,我得到了这个:
./fatool --in 're:^(a+b)?c$' --out dot:- | dot -Gdpi=70 -Tpng -onfa.png /dev/stdin
如果您感兴趣,可以使用图书馆:https://github.com/wader/libfa
答案 1 :(得分:3)
这对我来说似乎是个错误。为了减少问题,a+?
也失败了。
还有另一个错误,a|
应该等同于a?
,导致来自服务器的HTTP错误500.
扮演魔鬼的拥护者,他们有可能忽略某些案件,因为他们没有以常规语言关闭。如果他们接受表达式语言的一些非常规扩展,这将是可能的。
也许你的例子不是真正的常用语言。如果是这种情况,那么该工具可能正在按预期执行。也就是说,如果给出一个表示常规语言的正则表达式,那么它会产生一个识别该常规语言的NFA和DFA。但是,反过来可能不成立。
为了给这个回复增加更多的重量,我会证明你的例子确实是一种常规语言。
首先我们定义常规语言是什么。空ε
和字母表的任何符号都是常规语言。如果x
和y
是常规语言,则:连接x·y
,选择x|y
和重复x*
是常规语言。
对于表示法,从最低到最高的优先级为:|
,·
,*
。另外,我们添加通常的括号,它们具有最高优先级。 |
和·
都是关联的,例如(a·b)·c
和a·(b·c)
将被写为a·b·c
。
现在可以通过构建它来展示示例是常规语言。假设字母表包含'a','b'和'c'。为简洁起见,此演绎树未标记所使用的规则,但很容易推断出来。
--
a
-- --
a a*
----- --
a·a* b
---------- --
a·a*·b ε
-------------- --
(a·a*·b)|ε c
-------------------
((a·a*·b)|ε)·c
可以假定这些定义。
x+ ≡ x·x*
x? ≡ x|ε
xy ≡ x·y
然后通过使用定义,可以获得该示例。 +
和?
的优先级与*
相同。
((a·a*·b)|ε)·c
((a+·b)|ε)·c
((a+b)|ε)·c
(a+b)?·c
(a+b)?c
这不是了解常规语言的唯一方法。此外,我还没有定义构造语言中实际使用的单词,因此与您的示例等效是理所当然的 - 通过使用的约定我希望等效性足够明显。