ll(k)語法分析技術是建立在**分析的技術之上的。我們先來了解**分析技術。考慮以下文法:
當使用該文法對(1*2-3)+4和(1*2-3)進行分析,前者因該呼叫e->e+t,而後者應該呼叫e->t,怎麼確定到底使用哪個產生式呢?這就要使用**分析技術來構建**分析語法分析器,ll(k)是其一種。**分析技術的關鍵是構建乙個無衝突的**分析表。所謂**分析表就是程式可以根據當前的狀態來查詢該錶,然後確定下一步使用哪個產生式。
構建**分析表要要用到兩個集合,分別是first集合和follow集合。γ是終結符和非終結符組成的字串,first(γ)是從γ中可以推到出的任意字串中所包含的開頭終結符所組成的集合。a是乙個非終結符,follow(a)的意思可以直接跟在a後面的所有終結符的集合。這兩個集合的求法可以描述為如下:
first集合的求法:
first集合最終是對產生式右部的字串而言的,但其關鍵是求出非終結符的first集合,由於終結符的first集合就是它自己,所以求出非終結符的first集合後,就可很直觀地得到每個字串的first集合。
1. 直接收取:對形如u-a…的產生式(其中a是終結符),把a收入到first(u)中
2. 反覆傳送:對形入u-p…的產生式(其中p是非終結符),應把first(p)中的全部內容傳送到first(u)中。
follow集合的求法:
follow集合是針對非終結符而言的,follow(u)所表達的是句型中非終結符u所有可能的後隨終結符號的集合,特別地,「#」是識別符號的後隨符。
1.反覆傳送:對形如u-…p的產生式(其中p是非終結符),應把follow(u)中的全部內容傳送到follow(p)中
2. 直接收取:注意產生式右部的每乙個形如「…ua…」的組合,把a直接收入到follow(u)中。
3.直接收取:對形如「…upa…」(p是非終結符)的組合,把first(p)直接收入到follow(u)中。如果p的first集合包含由空(ε),則first(a)也要放入follow(u)中。
需要注意的是,空是只能在first集合中不能在follow集合中。
從上面的求法中可以知道,其實first集合就是乙個非終結符的等價終結符的可選集合,也就是說a可以直接推到出這些終結符,如果first集合可以為空,則說明a可以直接忽略,這個時候,為了**a為空後的情形,我們構建了follow集合。可見,者兩個完全是為了**分析而產生的集合。
**分析表是乙個二維表,用非終結符符標註每行,用終結符好標註每一列,根據這first和follow兩個集合,我們使用如下規則構建乙個**分析表:從產生式集合中取出乙個產生式a->γ,如果終結符a在first(γ)中,則講a->γ放入(a,a)確定的位置中,如果γ可以為空且a在follow(a)中,也則講a->γ放入(a,a)確定的位置中。這樣我們根據文法以下文法得到其相應的**分析表:
如何使用這個分析表呢?要知道,我們所分析的資料是由詞法分析其產生的,對於語法分析器而言,詞法分析器產生的資料都是終結符。我們利用堆疊(用到堆疊的地方一般也可以用遞迴來解決,可以參考虎書英文版的第47頁**)來記錄當前正在分析的非終結符,從詞法分析器得到乙個終結符a,以及棧頂的資料來查表,然後確定使用的產生式,如果產生式的右面有非終結符,將其從右到左壓棧(保證每次從對產生式的最左面的非終結符開始推到,稱為左推到),然後繼續使用使用a對棧頂元素分析。直到找到乙個產生式的右只包含終結符a,然後將a拋棄,重新讀取新的終結符,繼續分析。如果在過程中無法得到只包含終結符a的產生式,那麼說明有語法錯誤。
上面的演算法過程就是乙個**分析過程我們稱為ll(1)演算法,第乙個l是left to right parse,第二個l是leftmost derivation ,1是1-symbol lookahead.意思就是從左到右的分析詞法分析器產生的資料,採用最左推到原則,每次只看超前檢視乙個終結符來確定後續動作。
但是就對上面這張表而言,(z,d)的位置有兩個產生式,那麼說明該文法是二義的,說明它是不是ll(k)文法。就不能使用**分析技術來解析該語言,要使用功能更強大的lr(k)技術。
這裡介紹兩種可能產生二義性的例子,第乙個為左遞迴。檢視下左圖,因為first(t)正好是first(e+t)的子集合,所以,一定會產生衝突。我們使用右圖來替換原來的產生式,稱為消除左遞迴。
還有一種情況,我們解決的辦法稱為提取右因子。
以上就是ll(k)文法的全部,相比lr(k)文法,它的功能不夠強大(我們在lr(k)中進行比較),但是想要構造乙個**分析表卻十分的簡單。對於某些lr(k)處理不了的情況,我們可以快速的建立相應的ll(k)分析表來解決。
現代編譯原理 第二章(語法分析之上下文無關文法)
我們知道了詞法分析是專注於乙個檢測乙個語言中是否有不合格的單詞,以及將單詞進行分類。那麼為什麼要分類呢?其目的就是為了規範化。只有無限的東西規範到乙個範圍內,我們才能對其進行識別和分析。例如,我們定義在加號兩邊只能是兩個id。這樣,如果出現if plus id 這樣的結構就說明是不正確的,其犯了語法...
編譯原理 語法分析(二)
在第一篇文章中,我們介紹了如何用上下文無關文法描述一種語言的語法,和如何使用推導和規約構造一棵語法分析樹,以及如何對文法進行轉換使之能夠更適用於語法分析。在本篇文章中,我們將介紹如何使用自頂向下的方法進行語法分析,進一步的,我們將介紹一種更高效的 分析方法。為了下文需要和減少重複,我們先給出在下文中...
編譯原理 語法分析 二
在第一篇文章中,我們介紹了如何用上下文無關文法描述一種語言的語法,和如何使用推導和規約構造一棵語法分析樹,以及如何對文法進行轉換使之能夠更適用於語法分析。在本篇文章中,我們將介紹如何使用自頂向下的方法進行語法分析,進一步的,我們將介紹一種更高效的 分析方法。文法 約定 為了下文需要和減少重複,我們先...