編譯原理 語法分析 一

2021-09-01 12:25:51 字數 3539 閱讀 8543

語法分析器的作用

我們都知道,在使用某一種程式設計編寫程式時,都要遵循一套特定的規則。比如,在c語言中,乙個程式由多個函式組成,乙個函式由宣告和語句組成,乙個語句由表示式組成等等。這組規則精確描述了乙個良構的程式語言的語法。語法分析器能夠確定乙個源程式的語法結構,能夠檢測出源程式中的語法錯誤,並且能夠從常見的錯誤中恢復並繼續處理程式的其餘部分。

乙個語法分析器從詞法分析器獲得乙個詞素序列,並驗證這個序列是否可以由源語言的文法生成。語法分析器會構造一棵語法分析樹,並把它傳遞給編譯器的其他部分進一步處理,在構建語法分析樹的過程中,就驗證了這個詞素序列是否符合源語言的文法。語法分析器在編譯器中的位置如下圖:

文法乙個文法用於系統的描述程式語言的構造的語法。乙個正確設計的文法給出了乙個語言的結構,該結構有助於把源程式翻譯為正確的目標**,也有助於檢測錯誤。

上下文無關文法

乙個上下文無關文法(下文簡稱文法)由終結符號、非終結符號、乙個開始符號和一組產生式組成:

對於產生式頭相同的兩個或多個產生式,可以把它們的產生式體用「|」連線寫成乙個產生式。例如,對產生式e→e+t和e→t,可以寫成e→e+t|t。

乙個貫穿全文的表示式文法

在進入主題之前,先給出乙個簡單的表示式文法,把它稱為文法g,它將作為乙個貫穿全文的例子:

e→e+t|t

t→t*f|f

f→(e)|id12

3在文法g中,有3個產生式。其中,符號」+」、」*」、」(「、」)」、」id」是終結符號,符號」e」、」t」、」f」是非終結符號;符號e是開始符號,表示文法g可以生成的語言。

關於符號的約定

在下文中由於需要會出現大量的符號,為了減少冗餘和方便理解,我們在此對使用的符號有如下約定:

大寫字母表示非終結符號,如a、b、c等;

希臘字母表示任意由非終結符號和終結符號組成的串或者空串,如α、β、γ等。

推導和規約

語法分析器在構建一棵語法分析樹時,常用的方法可以分為自頂向下和自底向上的。顧名思義,自頂向下的方法是從語法分析樹的根結點開始向葉子結點構造的方法,自底向上的方法是從語法分析樹的葉子結點開始向根結點構造的方法。在自頂向下的構造過程中,需要從乙個非葉子結點「推導」出其子樹;在自底向上的構造中,需要把幾個非根結點「規約」成其根結點。

推導從產生式的角度來看,一次推導過程是把產生式的左部替換成產生式的右部的過程。

對文法g,從e到id*id+id的乙個最左推導和最右推導分別為:

其中,id*id+id是文法g的乙個句子,其他中間步驟是文法g的句型。從此亦可看出,對相同句型的推導過程不唯一。

推導過程可以用語法分析樹表示,從e到id*id+id的最左推導的語法分析過程如下圖所示:

每棵語法分析樹對應於某一次推導,從左到右把語法分析樹的葉子結點連線起來就是文法g的乙個句型,也稱為語法分析樹的結果或邊緣,最後一棵語法分析樹的葉子結點從左到右連線起來是文法g的乙個句子。

規約規約是推導的逆過程,一次規約是把乙個與某產生式體相匹配的串替換為該產生式頭的非終結符號。

規約過程可以用於自底向上構造語法分析樹。例如,把id*id+id規約成e,這裡的每次規約是某次最右推導的逆過程,構造的語法分析樹如下圖所示:

設計文法

本節將介紹如何對乙個文法進行轉換使其更適用於語法分析,這些轉換方法包括消除二義性,消除左遞迴和提取左公因子。

消除二義性

如果乙個文法可以為某個句子生成多棵語法分析樹,那麼它就是二義性的,簡單地說,二義性文法就是對同乙個句子有多個最左推導或多個最右推導的文法。

考慮下面的文法:

e→e+e

e→e*e

e→(e)

e→id12

34它對句子id+id*id有兩個最左推導,下圖給出了推導過程和相應的語法分析樹:

可以看出,這兩個推導過程反映了加法和乘法的優先順序問題,左邊的推導乘法優先順序比加法高,右邊的推導加法的優先順序比乘法高。實際上,左邊的推導過程更符合我們的觀念。

通過把該文法改寫成文法g的形式,可以解決這個二義性問題,該文法和文法g都生成同樣的語言。

消除左遞迴

如果乙個文法對乙個非終結符號a,經過一次或多次推導後得到串aα,那麼這個文法是左遞迴的。如果該文法中存在形如a→aα的產生式,則該產生式是立即左遞迴的。

在介紹消除文法的左遞迴之前,我們先介紹如何消除產生式的立即左遞迴。對任意立即左遞迴的產生式,可以用下面的方法消除立即左遞迴:

右邊的兩個產生式生成的串集合和左邊的產生式生成的串集合是相同的,並且右邊的兩個產生式沒有左遞迴,這樣就消除了產生式的左遞迴。

現在正式介紹對乙個左遞迴的文法如何消除其左遞迴。對乙個左遞迴的文法,用下面的方法消除左遞迴:

對文法g,消除它的左遞迴:

將非終結符號排序為e、t、f;

當i=1時,對符號e,產生式e→e+t|t是立即左遞迴的,把它替換為e→te'和e'→+te'|ε;

當i=2時,對符號t,產生式t→t*f|f中沒有e,但它是立即左遞迴的,把它替換為t→ft'和t'→*ft'|ε;

當i=3時,對符號f,產生式f→(e)|id中有e,把e替換為te'後得到f→(te')|id,它不是立即左遞迴的,演算法結束;

最後得到的非左遞迴文法為:

e→te'

e'→+te'|ε

t→ft'

t'→*ft'|ε

f→(te')|id12

345提取左公因子

當使用自頂向下的方法構造語法分析樹時,如果在「展開」乙個非終結符號的結點時,有不止乙個產生式可以選擇,此時無法明確知道該使用哪乙個產生式。為了解決這個問題,我們可以通過改寫產生式來推後這個決定,等獲得足夠的資訊後再做出正確的選擇。

例如,對於產生式a→+α|+β,假設α和β開頭的符號不同,當看到輸入「+」時,不能明確決定使用+α還是+β來替換a,只有繼續讀入下乙個輸入,才能確定到底使用哪乙個產生式。對此,可以把a→+α|+β轉換成a→+a'和a'→α|β,這樣當看到輸入「+」時,可以把a替換為a',再根據後續的輸入決定如何替換a'。

對乙個文法提取左公因子,對於每個非終結符號a,找出它的兩個或多個選項之間的最長公共字首α,如果α不是空串,那麼將所有頭為a的產生式做如下替換:

語法分析 編譯原理

實驗目的 對迴圈語句和條件判斷語句編寫詞法分析編譯程式,只能通過一遍掃瞄完成。用c 實現 實驗要求 1 關鍵字 for if then else while do 所有關鍵字都是小寫。2 運算子和分隔符 3 其他識別符號 id 和整型常數 num 通過以下正規式定義 id letter letter...

編譯原理 語法分析

根據上課內容順序寫的部落格,並不是按照書的目錄來的 使用龍書以及編譯程式設計原理 第二版 金成植 金英編著 老師的ppt是英文的,我自己隨便翻的,不一定對 上下文無關文法 語法分析書和抽象語法樹 二義性簡單語言的語法 知識圖譜 語法分析器的功能輸入 詞法單元 詞法單元序列 輸出 語法結構的內在表示式...

編譯原理 語法分析(二)

在第一篇文章中,我們介紹了如何用上下文無關文法描述一種語言的語法,和如何使用推導和規約構造一棵語法分析樹,以及如何對文法進行轉換使之能夠更適用於語法分析。在本篇文章中,我們將介紹如何使用自頂向下的方法進行語法分析,進一步的,我們將介紹一種更高效的 分析方法。為了下文需要和減少重複,我們先給出在下文中...