對於終結符和非終結符的理解:
終結符:通俗的說就是不能單獨出現在推導式左邊的符號,也就是說終結符不能再進行推導。
非終結符:不是終結符的都是非終結符。
如:A->B,則A是非終結符;A->id,則id是終結符。
(一般書上終結符用小寫,非終結符用大寫。)
文法產生語言句子的基本思想:
從識別符號(開始符)開始,把當前產生的符號串中的非終結符替換為相應規則右部的符號串,直到全部由終結符組成。所以文法產生句子的基本思想就是基於產生式(例如A->num)的替換,當所有的非終結符都被終結符替換時,推導結束。
FIRST集求法:
我 對First集的理解:first集應該就是求一個表示文法的字串(一般指非終結符,終結符的first集就是它自身)開頭的所有可能出現的字符的集合。 例如A->aC | bB | cD,根據這個產生式,就可以知道,非終結符A,被替換后,它開頭可能出現字符有a、b 、c, 所以 {a,b,c}是First(A)的一個子集。
求First集的步驟:
-
若X->a..,則將終結符a加入FIRST(X)中;(注意非終結符的情況)
-
若X->e ,則將終結符e加入FIRST(X)中(e表示空集);
-
若 X->BC..D,則將First(B)所有元素(除了空集)加入First(A),然后檢測First(B),若First(B)中不存在空集, 即e,則停止,若存在則向B的后面查看,將First(C)中所有元素(除了空集)加入First(A),然后再檢測First(C)中是否有e...直 到最后,若D之前的所有非終結符的First集中都含有e,則檢測到D時,將First(D)也加入First(A),若First(D)中含有e,則將 e加入First(A)。
對於第三條,其實也很好理解,就是說當X推導出一個字串時,D前面的非終結符都可能推出空串,這個時候,X推出的串的首部,就不是那些推出空串的非終結符了,而是這些推出空串的非終結符后面的文法符號所推導出的字串。
例題:設文法G(S):
S->S+aF|aF|+aF
F->*aF|*a
(1)消除左遞歸和左因子。
(2)構造相應的FIRST集合和FOLLOW集合。
解析:首先,第一個式子,消除左遞歸。S->aFS’|+aFS'。S'->+aFS'|ε (此處的ε和e一樣的 不同的書上印刷的不同)
然后,第二個式子,消除左因子。F->*aF’,F'->F|ε
第三步,求各個非終結符的FIRST集合。FIRST(S)={a,+} 因為S可以導出首字母為終結符a的產生式,和首字符為+的產生式。
FIRST(S‘)={+,ε} FIRST(F)={*},FIRST(F’)={*,ε}
FOLLOW集的求法:
對Follow集,其實也差不多,它應該是指非終結符推出的字串最末端后可能出現的所有字符的集合。例如Follow(U)所表達的是句型中非終結符U所有可能的后隨終結符號的集合,特別地,“$”是識別符號的后隨符。注意Follow集合是從開始符號S開始推導。
求Follow集的步驟:
-
對文法開始符號S,置$於FOLLOW(S)中; (也就是說有關S的FOLLOW集合中,都包含$,也有書中表示為#)
-
對於產生式:A->aBC,將除去空集e的First(C)加入Follow(B)中; (B后面跟着的就是C的首部字符,注意如果是終結符也要搞上)
-
對於產生式:A->aB或者A->aBC,(其中C可以推導出空串,C=>*e,即空串屬於C的first集合),則將Follow(A)加入Follow(B)中。 (注意:此處a可以是空,也可以是其他文法符號);
(A->aB ,那么A推出字串的末端后字符集合,與B推出字串的末端后字符集合,是等價的。)
注意:follow集合是要將所有的產生式都找出來,來求非終結符的follow集合。
剛剛的例題:
FOLLOW(S)={#},FOLLOW(S')={#},可以看出S和S‘ 並沒有其他的末端。
FOLLOW(F)={+,#} (原因是S->aFS’|+aFS'。S'->+aFS'|ε ,由第二條,講S和S’的FOLLOW集合加入到FOLLOW(F)中,且F后面有S‘,因此將 FIRST(S’)出去空集以外,也加入到FOLLOW(F)中 )
FOLLOW(F')={+,#},(F->*aF’,F'->F|ε,互相加入到集合中去)
