編譯原理 龍書第二版 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)*)*

發佈了16 篇原創文章 · 獲贊 2 · 訪問量 6991
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章