考虑语言?= {a 3 n ; n> = 0}
答案 0 :(得分:1)
我在这里的策略是查找字符串的各个部分,以了解它们之间的关系。我看到了该字符串的三个主要部分:
我们看到a和b的数量是相关的,但是c的数量是完全不相关的。如果我们仅能获得前两个部分的语法,则可以连接一个符号,该符号是另一部分的语法的开始符号,并获得所有三个部分的语法。在符号中:
S -> S' S''
S' -> (first two parts)
S'' -> (third part)
让我们先做第三部分的语法,首先是c的语法。属于该部分的最短字符串是长度为1的字符串c;因此,我们可以添加像S'' -> c
这样的产品。给定一个已经是有效的第三部分的长字符串,我们可以添加另一个c;这表明产生了S'' -> S'' c
。实际上,我们可以确认这两个产品可以让我们生成所有有效的第三部分。我们的语法如下:
S -> S' S''
S' -> (first two parts)
S'' -> S'' c | c
现在让我们尝试前两个部分。实际上,我们也可以将其分为两部分:与a和b匹配的部分,以及额外的+2 b实例的部分。我们的语法现在看起来像这样:
S -> S' S''
S' -> S''' S''''
S'' -> S'' c | c
S''' -> (matched a and b)
S'''' -> bb
要获得匹配的a和b(剩下的唯一部分)的语法,我们可以使用与第三部分相同的过程。匹配的a和b的最短字符串是空字符串(此处,我们不要求数字严格为正)。这意味着S''' -> e
。给定一个匹配的a和b的有效字符串,您可以通过在前面加上a并在后面加上b来获得下一个:S''' -> a S''' b
。我们完成的语法如下:
S -> S' S''
S' -> S''' S''''
S'' -> S'' c | c
S''' -> a S''' b | e
S'''' -> bb
现在,为了简化此语法,我们可以消除空乘,并且可以消除仅代表一连串终端的非终端符号,例如S''''。为了消除空的生产,我们需要添加多余的生产,并在其中有S'''的现有生产中删除S'''。有两个这样的产品,因此我们将添加两个产品并删除空的产品:
S -> S' S''
S' -> S''' S'''' | S''''
S'' -> S'' c | c
S''' -> a S''' b | ab
S'''' -> bb
摆脱S''''很容易,只需将其任何实例替换为bb:
S -> S' S''
S' -> S''' bb | bb
S'' -> S'' c | c
S''' -> a S''' b | ab
应该或多或少地做到这一点。证明是一种练习。