任何人都可以为我勾勒出一种算法,可以将任何给定的正则表达式转换为一组等效的CFG规则吗?
我知道如何解决基本问题,例如(a | b)*:
S -> a A
S -> a B
S -> b A
S -> b B
A -> a A
A -> a B
A -> epsilon
B -> b A
B -> b B
B -> epsilon
S -> epsilon (end of string)
但是,我遇到了一些问题,将其形式化为适当的算法,特别是对于可以有许多嵌套操作的更复杂的表达式。
答案 0 :(得分:12)
如果你只是从理论的角度谈论正则表达式,那么有以下三种结构:
ab # concatenation
a|b # alternation
a* # repetition or Kleene closure
你可以做什么:
S -> (fullRegex)
(x)*
中的每个重复字词fullRegex
创建规则X -> x X
和X -> ε
,然后将(x)*
替换为X
。(a|b|c)
创建规则Y -> a
,Y -> b
和Y -> c
,然后将(a|b|c)
替换为Y
只需递归地重复此操作(请注意,所有x,
a
,b
和c
仍然可以是复杂的正则表达式)。请注意,您当然必须为每个步骤使用唯一标识符。
这应该足够了。这肯定不会给出最优雅或最有效的语法,但这就是规范化的目的(它应该在一个单独的步骤中完成,并且有well-defined steps来执行此操作)。
一个例子:a(b|cd*(e|f)*)*
S -> a(b|cd*(e|f)*)*
S -> a X1; X1 -> (b|cd*(e|f)*) X1; X1 -> ε
S -> a X1; X1 -> Y1 X1; X1 -> ε; Y1 -> b; Y1 -> cd*(e|f)*
S -> a X1; X1 -> Y1 X1; X1 -> ε; Y1 -> b; Y1 -> c X2 (e|f)*; X2 -> d X2; X2 -> ε
... and a few more of those steps, until you end up with:
S -> a X1
X1 -> Y1 X1
X1 -> ε
Y1 -> b
Y1 -> c X2 X3
X2 -> d X2
X2 -> ε
X3 -> Y2 X3
X3 -> ε
Y2 -> e
Y2 -> f