天天看點

計算First集合

說明:文章内容可能随時修改。

=======================================================

        在文法分析過程中,文法符号的First集合是一個很重要的概念。因為是文法分析,是以我們所說的文法,一般都是指正則文法。

        First集合是一個隻可能包含終結符和空字元ε的集合,可以針對文法符号——空字元、終結符和非終結符,以及文法符号串——其中可以同時包含終結符和非終結符,來計算First集合。通常用First(X)來表示文法符号X的First集合,用First(α)來表示文法符号串α的First集合。

一、First集合的定義和計算

        終結符号的First集合很好計算,就是隻包含它本身的集合,例如:假設a是某個文法中的一個終結符,那麼First(a)={a}。空字元ε的First集合也是這樣,即First(ε)={ε}。

        非終結符号First集合的計算相比就沒有這麼簡單了。書上的算法如下圖所示。

計算First集合

        其中部分過程是這樣的,算是上面第2個for循環的循環體吧。假設X是某個文法中的一個非終結符,并且,對于X存在産生式“X→X1X2⋯Xn”。

        1. 初始狀态:First(X)=∅,i=1;

        2. 如果i<=n,那麼First(X)=First(X)∪(First(Xi)-{ε}),否則跳到步驟4;

        3. 如果ε∈First(Xi),那麼i=i+1,然後跳轉到步驟2,否則向下執行步驟4;

        4. 如果i>n,那麼First(X)=First(X)∪{ε},否則First(X)不變,計算完畢。

        對于文法符号串,其First集合的計算方法和非終結符号類似,隻是将X換成α,Xi換成αi,這裡αi表示文法符号串α中的第i個符号,另外,n表示的将是這個串的長度。

        ------- 書上關于First集合的定義如下。

計算First集合

        ------- 書上關于非終結符First集合的算法

        (1)如果存在空産生式:

計算First集合

        (2)如果沒有空産生式,那麼算法可以得到簡化:

計算First集合

        -------

二、First集合的含義

        對于終結符和空字元ε,其First集合就表示它們本身,沒有提供任何别的資訊,但是對于終結符和空字元定義First集合是必要的,不僅僅是因為這樣使得First集合顯得更完整,對于所有的文法符号都有意義,更是為了給計算文法符号串的First集合奠定基礎,而且這樣建立了終結符和非終結符的一緻性,使算法顯得更簡潔。

        對于非終結符,First集合其實說明了一件事情,那就是什麼樣的句子有可能規約成這個非終結符,更進一步地說,隻有以某些特定終結符開頭的句子,才可能通過規約得到這個非終結符,而這些特定的終結符,也就是相應的First集合中的元素。當然,也可以換一個方向來看,First集合說明的是從這個非終結符推導出來的句子,它的第一個符号可能是哪些終結符。

        類似地,對于文法符号串可以這樣了解。從不同的情況來看,如果文法符号串中隻包含有終結符,那麼它就是一個句子,它的First集合隻是說明了這個句子開頭的第一個終結符是什麼;如果文法符号串中包含非終結符——我們不妨認為它是文法的一個“句型”,當然,它不一定是,對于文法符号的任意組合,我們都可以按照前面說的方法計算First集合,隻是沒有什麼特殊的意義,這裡為了便于說明和了解,就暫時把句型的定義放在一邊,但是用雙引号标記以表示非嚴格意義上的句型,相應地,“句子”也就不一定是文法的一個句子——它的First集合就說明了滿足這個“句型”的“句子”,或者說從這個“句型”可以推導出來的“句子”,其第一個符号可能會是哪些終結符;如果First集合中包含空串ε,那麼說明這個“句型”可以推導出空“句子”。這裡不宜從規約的角度來了解,那樣會顯得非常不自然。

三、其它

        另外,我們可以引入一個概念——其實隻是一個說法:如果一個非終結符可以推導出空串,那麼我們說它是可空的(nullable)。

        順便引入一個定理——其實你可以隻把它當成一個結論,另外,暫時沒發現它有什麼用:一個非終結符是可空的,當且僅當它的First集合中包含空字元。

        這個定理可以按照推導過程的長度用數學歸納法進行證明,當然,需要從兩個方向上證明:充分性和必要性。假設有一個非終結符X,它可以推導出空串,如果這個推導的長度為1,即X可以直接推導出空串,那麼顯然空字元屬于First(X);如果推導的長度為n,那麼首先我們需要假設,當推導長度小于n時,這個結論都是成立的,然後我們來考慮這個推導過程。這個推導總有第一步,那麼我們不妨将這個推導寫成:X⟹ X1X2⋯Xn⟹⋯⟹ε,對于Xi,它必須能夠推導出空串,否則最後一定會出現終結符,而這個推導過程一定是小于n步的,是以根據假設,First(Xi)一定包含空字元,那麼根據First集合的定義,顯然First(X)也包含空字元。到此,一個方向證明完畢。另外一個方向可以類似證明。

        ------- 書上的定義、定理,以及證明:

計算First集合
計算First集合

        -------

四、舉例

計算First集合
計算First集合
計算First集合

        答案依次如下:

計算First集合
計算First集合
計算First集合

♪ 參考資料

Louden, K. C. (1997). Compiler Construction: Principles and Practice: PWS Pub. Co.

繼續閱讀