「編譯原理」“根據LL(1)求FIRST集” 書本算法的解析及改進


筆者使用的是 劉堅編著的《編譯原理基礎(第二版)》2008年9月第2版 2012年5月第8次印刷的版本。

書P74頁中
算法3.5 計算X的FIRST集合
輸入:文法符號X。
輸出:X的FIRST集合。
方法:應用下述規則,
(1)若X是終結符,則FIRST(X) = {X}。
(2)若X是非終結符且有X→ε,則加入ε到FIRST(X)中。
(3)若X是非終結符且有X→Y1Y2…Yk,並令Y0=ε,Yk+1=ε,則從左到右對所有j(0≤j≤k),若a∈FIRST(Yj+1)且ε∈FIRST(Yj),則加入a到FIRST(X)中。

以下為自己的一些想法,如有紕漏,還望指正!

首先,解釋一下什么是FIRST集

對於一個符號X最后轉化為實例(只由終結符組成)時,這個實例的第一個字符(如果實例長度為0則用ε表示這個字符)的所有可能情況組成的集合稱為X的FIRST集合簡稱FIRST(X)

對於算法3.5執行流程,我的理解是這樣的:

規則(1):對於終結符a,因為它的實例只有a一個,所以FIRST(a)必然是{a}
規則(2):對於非終結符A,存在文法 A→ε,那么A的實例為空,即長度為0所以用ε表示該實例的第一個字符,將ε加入到FIRST(A)中。
規則(3):對於非終結符A,存在文法 A→BCDE,將該文法的右部看成εBCDEε
①判斷ε∈FIRST(ε),如果符合的話則將FIRST(B)加入到FIRST(A)中
②判斷ε∈FIRST(B),如果符合的話則將FIRST(C)加入到FIRST(A)中
③判斷ε∈FIRST(C),如果符合的話則將FIRST(D)加入到FIRST(A)中
④判斷ε∈FIRST(E),如果符合的話則將ε加入到FIRST(A)中

對於規則(1)(2)較為容易理解,我也並沒有什么可改進的。
對於規則(3)我的理解如下:

按照FIRST集的定義,對於文法A→BCDE,FIRST(A)是指A的所有實例第一個字符的集合,那么我們將BCDE轉換為實例有兩種可能:
1) B不為空時,這時符號A的第一個字符必然屬於B不為空時所有可能第一個字符的集合,即應該將 FIRST(B)-{ε} 加入 FIRST(A)
2) B為空時,這時文法A→BCDE就縮減成A→CDE,這個時候只需要重復上面的步驟即可。

那么我們需要考慮的問題是如下:
算法3.5 為什么要做

從左到右對所有j(0≤j≤k),若a∈FIRST(Yj+1)且ε∈FIRST(Yj),則加入a到FIRST(X)中

我們再看上面的算法執行流程:

①判斷ε∈FIRST(ε),如果符合的話則將FIRST(B)加入到FIRST(A)中
②判斷ε∈FIRST(B),如果符合的話則將FIRST(C)加入到FIRST(A)中
③判斷ε∈FIRST(C),如果符合的話則將FIRST(D)加入到FIRST(A)中
④判斷ε∈FIRST(E),如果符合的話則將ε加入到FIRST(A)中

~

在第一步做看似毫無意義的判斷ε∈FIRST(ε)的原因是:符號B作為文法A→BCDE右部的第一個符號,必然需要將FIRST(B)加入到FIRST(A)中,所以判斷本身並不重要,但做判斷后能提高算法的統一性和表達的簡潔性,如果單列出來,算法會顯得過於冗長;

在后續步驟中,不斷判斷ε∈FIRST(B/C/D/E)的原因是:考慮到B/C/D/E有可能為空,則文法形式可能會不斷縮減,極端的實例是BCDE都為空,則文法變成A→ε,所以在最后將ε加入FIRST(A)

這么看來算法3.5好像沒有什么問題,但我注意到:

推論:如果B絕對不為空,即文法A→BCDE絕對不會縮減成A→CDE,這時會怎么樣?也就是說無論CDE是否可能為空,那么文法一定是A→B……,那么對於這個文法,FIRST(A)必然等於FIRST(B)

那么按照這個設定(ε∉FIRST(B),ε∈FIRST(C)),我們再看算法的執行過程

①判斷ε∈FIRST(ε),符合!將FIRST(B)加入到FIRST(A)中;
②判斷ε∈FIRST(B),不符合;
③判斷ε∈FIRST(C),符合!將FIRST(D)加入到FIRST(A)中

這個時候FIRST(A)包含了FIRST(B)和FIRST(D),但是按照我們推論,FIRST(A)必然等於FIRST(B),而FIRST(B)和FIRST(D)之間的關系是不明確的,所以按照算法3.5得到的結果存在問題

所以我認為該算法應該做一定修改,以下是我做出修改后的算法

算法3.5改 計算X的FIRST集合
輸入:文法符號X。
輸出:X的FIRST集合。
方法:應用下述規則,
(1)若X是終結符,則FIRST(X) = {X}。
(2)若X是非終結符且有X→ε,則加入ε到FIRST(X)中。
(3)若X是非終結符且有X→Y1Y2…Yk,對於j(1≤j≤k),若ε∈FIRST(Yj),則將到 FIRST(Yj)-{ε} 加入 FIRST(X)中,其中若j=k,則將ε加入 FIRST(X)中;否則,將FIRST(Yj)加入 FIRST(X)中,直接結束算法。

按照這個修改后的算法執行設定(ε∉FIRST(B),ε∈FIRST(C)):

①判斷ε∈FIRST(B),不符合!將FIRST(B)加入到FIRST(A)中,結束算法;

這時FIRST(A)等於FIRST(B),符合預期。

 

原創文章,轉載請全文轉載並注明出處

http://www.cnblogs.com/777777-716/p/5003960.html 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM