從名字很容易看出來,自下而上分析法對應的就是自上而下分析法,這里我首先簡單區分一下這兩種分析方法的區別。
自上而下分析法是多個推導的過程,而自下而上分析法是多個歸約的過程。那么歸約和推導又是什么呢?下面通過一個簡單的例子說明。
例如有一個文法G(S) : ①S -> aAcB ,②B->b,假如有一個輸入符號串為aAcb。說明:G(S)中的S說明S是開始符號。
推導(從開始符號開始):第一步:S->aAcB,第二步:B->b。
經過兩步之后我們就能推到出輸入符號串aAcb。而第一步中我們從S推出aAcB的過程就是推到的過程,同理第二步中B推出b也是推到的過程。
歸約(從輸入符號串開始):第一步:aAcb中的b歸約為B,第二步:aAcB歸約為S。
經過兩步之后我們將輸入符號串aAcb中的b根據②中的規則替換(歸約)為B,這時輸入符號串從aAcb變為aAcB,然后再根據規則①將aAcB歸約為S。
通過這個例子我們可以總結一句話:推導的過程就是從某個產生式的左部(S)推導出右部(aAcb)的過程。歸約的過程是從某個產生式的右部(aAcb)歸約(替換)為左部(S)的過程。
多個推導的過程能夠組成自上而下分析即從開始符號到輸入符號串的過程,多個歸約的過程能夠組成自下而上分析即從輸入符號串到開始符號的過程。
(一)什么是自下而上分析法
自下而上分析法定義:從輸入串開始,逐步進行歸約,直至文法的開始符號。
在自下而上分析法中使用的方法(移進-歸約法):使用一個符號棧,把輸入符號逐一移進棧,當棧頂形成某個產生式右部時,則將棧頂的這一部分替換(歸約)成該產生式的左部符號。(下圖就是一個移進-歸約的例子)。
-
- 符號棧方式展示移-進歸約法
- 符號棧方式展示移-進歸約法
從圖中可以發現移進-歸約法就是將輸入符號串(從左到右)依次讀入,每讀入一個字符就和所有產生式的右部對比,查看是否能歸約為產生式左部。(即圖中符號棧最后三個狀態),讀入b時和產生式②對比可歸約為B,此時符號棧變為aAcB,又和產生式①對比可歸約為S。
2.分析樹方式展示移-進歸約法
從分析樹中,從根節點到葉子節點就是自上而下分析法,從葉子節點逆推到根節點就是自下而上分析法。
(二)自下而上分析法之短語、直接短語、句柄
上邊我們簡單了解了一下什么時自上而下分析法,下邊我們在說明如何進行歸約前先搞清楚幾個定義(短語、直接短語、句柄)。 直接上圖給出這三個比較標准的定義。
下邊通過分析樹中的文法對這三個定義進行分析(以下為個人見解)。
給出文法(如下圖)求句型aAbcde的短語、直接短語、句柄。(畫出從S推導出aAbcde的分析樹)
短語:在分析樹中,所有父節點的最終葉子節點組成的集合。
例如:根節點S,它直接指向的節點為aAcBe,但是A和B還有子節點,因此A和B就不是根節點S的最終葉子節點。應該將A->Ab,然后B->d。最終得出aAbcde是關於S的短語。
父節點A,它直接指向的節點為Ab,而A和b均為葉子節點,因此Ab就是關於A的短語。
父節點B,它直接指向的節點為d,而d為葉子節點,因此d是關於B的短語。
直接短語:只需要一步轉換的短語稱為直接短語。
例如:父節點 A,A->Ab可一步推導出,因此Ab屬於直接短語。
父節點B,B->d可一步推導出,因此d屬於直接短語。
根節點S,因為S->aAbcde不能一步推導出來,還需要將A->Ab,B->b,因此aAbcde就不屬於直接短語。
句柄:分析樹中最左側的直接短語。如上圖中直接短語Ab位於最左側,而直接短語d在Ab的右邊,所以Ab是句柄。
注意:具有二義性文法的句柄可能不唯一。例如:文法G(E): E-> E+E | E*E | (E) | i ,給出句型E+E*E的句柄。
(1)E -> E+E -> E+E*E> 句柄為E*E
(2)E -> E*E -> E+E*E 句柄為E+E
(三)規范歸約
規范歸約定義:將句柄替換成相應產生式左部符號而得到的,則該序列是一個規范歸約。最左歸約的過程就是不斷將句柄轉換成產生式左部(每歸約一次句型的句柄就變化一次)。
例如上圖中規范規約的過程:
①句柄為b,根據A->b,將句柄b(左側的b)歸約為A,此時句柄變為Ab。
②句柄為Ab,根據A->Ab,將句柄Ab歸約為A,此時句柄為d。
③句柄為d,根據B->d,將句柄d歸約為B,此時句柄為aAcBe。
④句柄為aAcBe,根據S->aAcBe,將句柄aAcBe歸約為S,最左推導過程結束。
其實最左推導的過程就是“剪枝"的過程,①將b節點剪去,②將Ab節點剪去,③將d節點剪去,④將aAcBe剪去,最終只剩下S節點。
規范歸約的基本問題:
1、如何找出或確定可歸約串——句柄?
2、對找出的可歸約串——句柄替換為哪一非終結符號?
基於上述兩個問題,實現移進-歸約分析的一個方便途徑是用一個棧和一個輸入緩沖區,用#表示棧底和輸入的結束。
對於棧和輸入緩沖區的使用可嘗試推導下圖中的例子,由於例子較為復雜,篇幅有限這里不做詳細詳解。
對於語法分析的操作(即上圖中的動作)共有四種狀態:
1、移進:下一輸入符號移進棧頂,指針(讀頭)后移。
2、歸約:檢查棧頂若干符號能否進行歸約,若能,就以產生式左部代替該符號串,同時輸出產生式編號。
3、接受:移進-歸約的結局是站內只剩下棧底符號和文法開始符號,(指針)讀頭也指向語句的結束符。
4、出錯:發現了一個語法錯誤,調出出錯處理程序。(可歸約串一定處於棧頂位置,而不可能出現在棧頂的下方,因為一旦出現可歸約串就會及時將其歸約掉,不會出現棧頂有歸約串而繼續讀入符號的情況)。
以上均為個人學習總結,如有錯誤或異議歡迎提出(自下而上分析法未完待續......)。