编译原理 龙书第二版 3.3节练习 部分习题解答

编译原理 龙书第二版 3.3节练习 部分习题解答

练习3.3.5 写出下列语言的正则定义:
1)2)比较简单,就不写出答案了
3)注释,即/* 和 */ 中间的串,且串中没有不在双引号"里面的*/
这道题是说,/* 和 */ 中间的内容可能会出现 “*/”

解答:\/\*([^"*/]|\"\*\/\")*\*\/
首先,注释由是 /* 和 */包围的,再因为/、*是正则表达式保留字,所以要转义:\/\* \*\/。然后,里面是([^"*/]|\"\*\/\")*。这个正则表达式表明要匹配除"*/之外的字符([^"*/])或者(|)字符串 “ “*/” ”(\"\*\/\")。
!!4)所有不重复数位组成的字符串
(?!.*?(\d).*?\1.*?$)\d+

这个正则表达式亲测可用,首先(?!exp)\d+的意思是断言exp后面的数字串(\d+)无法匹配exp。也就是说,对于这一题,exp匹配重复的数字。
再看exp的表达式,.*?(\d).*?\1.*?$,首先匹配了任意的0个或多个字符(.*),后面的?代表的是这次匹配使用懒惰模式,即匹配最短的串。也就是说,.*?匹配的是最短的任意字符组成的串。然后\1表示引用前面(\d)的匹配结果,也就是说,.*?(\d).*?\1.*?$表示的是在一个串内同一个数字至少重复两次,$表示的是要匹配到整个字符串的结尾。再配合上前面的(?!exp)\d+,exp表示匹配有重复数字的串,那么这整个表达式(?!.*?(\d).*?\1.*?$)\d+自然就是匹配所有不重复数位组成的字符串了。

!!5) 最多有一个重复数位组成的串

(?!.*?(\d).*?\1.*?\1.*?$)\d+

沿用上题的结论,我们要想出exp的表达式,我们首先想到“最多有一个重复数位组成的串”的否定形式是“有2个及以上重复数位组成的串”,我们可以取这个否定命题的简单情况“有三个重复的数位组成的串”,而如果我们找到了三个重复的数位就一定可以推导出这是“有2个及以上重复数位组成的串”。因此exp要做到的推断就是“有三个重复的数位”。
因此可以写出对应的正则表达式:(?!.*?(\d).*?\1.*?\1.*?$)\d+

!!6) 所有由偶数个a和奇数个b构成的串
我们首先在习题3.3.2的!!5)看到了偶数个a、偶数个b的表示方法:
(aa|bb)*((ab|ba)(aa|bb)*(ab|ba)(aa|bb)*)*
首先(aa|bb)*表示的是两个字符连着出现(出现偶数次)的情况。由于a b两个字符在串中出现的情况无非aa、ab、ba、bb四种情况,因此我们在后面定义了ab、ba出现的情况。(ab|ba)表示的是ab或者ba出现一次的情况,然后他的前面、后面可能会出现0次或者多次两个字符连着出现并且出现偶数次的情况,即(aa|bb)*(ab|ba)(aa|bb)*。又由于题目要求a、b都要出现偶数次,而上述的表达式中不是a出现奇数次就是b出现奇数次,因此我们要重复(ab|ba)。同样的,考虑到它的后面可能会出现两个字符连着出现并且出现偶数次的情况,整个正则表达式最后的结果是(aa|bb)*((ab|ba)(aa|bb)*(ab|ba)(aa|bb)*)*

我们在上述讨论的基础上继续探究如何匹配所有由偶数个a和奇数个b构成的串。

我们首先定义上述正则:

even_ab -> (aa|bb)*((ab|ba)(aa|bb)*(ab|ba)(aa|bb)*)*

然后考虑如何使得让b变为奇数个。我们可以发现,若是我们在上述表达式前加b,那么就得到了匹配以b开头的偶数a、奇数b的正则定义。即:

even_a_odd_b_withPrefix_b -> b(aa|bb)*((ab|ba)(aa|bb)*(ab|ba)(aa|bb)*)*

我们再考虑在even_ab前面加a的情况,那么就得到了匹配以a开头的偶数b、奇数a的正则定义。即:

even_a_odd_b_withPrefix_a1 -> a(aa|bb)*((ab|ba)(aa|bb)*(ab|ba)(aa|bb)*)*
此时我们为了使得a、b奇偶性倒过来,结合上面的讨论,我们自需要再加上(ab|ba)(aa|bb)*即可,即:

even_a_odd_b_withPrefix_a -> a(aa|bb)*((ab|ba)(aa|bb)*(ab|ba)(aa|bb)*(ab|ba)(aa|bb)*)*

最终的正则定义是:
even_a_odd_b -> even_a_odd_b_withPrefix_a | even_a_odd_b_withPrefix_b
even_a_odd_b_withPrefix_b -> b(aa|bb)*((ab|ba)(aa|bb)*(ab|ba)(aa|bb)*)*
even_a_odd_b_withPrefix_a -> a(aa|bb)*((ab|ba)(aa|bb)*(ab|ba)(aa|bb)*(ab|ba)(aa|bb)*)*
even_ab -> (aa|bb)*((ab|ba)(aa|bb)*(ab|ba)(aa|bb)*)*

posted @ 2020-02-17 15:29  NathanLi97  阅读(1344)  评论(0)    收藏  举报