我试图弄清楚如何基于给定的正则表达式构造CFG(无上下文语法)。 例如,a(ab)*(a | b) 我认为有一个算法可以通过,但它确实令人困惑。 这是我到目前为止所得到的:
S->aAB;
A->aAb|empty;
B->a|b;
这看起来不错吗? 任何帮助将不胜感激。
答案 0 :(得分:3)
分为三个部分构建CFG,每个部分适用于a
,(ab)*
和(a|b)
。
对于(a|b)
,您的B -> a | b
是正确的。
(ab)*
表示ab
,abab
,ababab
等字符串。所以A -> abA | empty
将是正确的制作。
因此,完整的语法变为:
S -> aAB
A -> abA | empty
B -> a | b
注意:A -> aAb | empty
会派生出ab
,aabb
,aaabbb
等字符串,而不是regular language,并且不可能代表regular expression。
答案 1 :(得分:3)
为给定的正则表达式构造无上下文语法的另一种方法是:
X -> t Y
形式的规则。如果您的CFG表示法不允许这样的规则,那么对于从终端t的状态X到最终状态F的每次转换,产生规则F -> epsilon
(除了已经描述的规则X -> t
之外)。结果是一个常规语法,一个无上下文的语法,遵循每个右侧最多有一个非终端的额外约束。对于给出的示例,假设我们构造了以下FSA(许多接受与正则表达式相同的语言):
由此可以直接推导出以下常规语法:
X -> t F
或者,如果我们不想要具有空右侧的规则,请删除该语法的最后三个规则并添加:
S -> a A1
A1 -> a A2
A2 -> b B3
B3 -> a A2
B3 -> a A4
B3 -> b B5
A1 -> a A4
A1 -> b B5
A4 -> epsilon
B5 -> epsilon
epsilon ->
与其他方法相比,这种方法的缺点是结果语法比它需要的更冗长,并且推导可以完全机械化的优点,这意味着它更容易正确而不必刻意思考。