1. 程式人生 > >#編譯原理# 詞法分析(三)第二部分

#編譯原理# 詞法分析(三)第二部分

詞法分析

編譯原理筆記第三部分,由於內容過長所以分為了兩部分,跳轉連結在總閱讀目錄處,內容參考:北航軟院教師邵兵課堂課件及內容、張莉著《編譯原理及編譯程式構造》、國防工業出版社的《編譯原理——學習指導與典型題解析》、AlvinZH的學習筆記以及個人理解

目前是包含了全部內容的版本,後續會推出精簡版和複習知識點版

如有建議或錯誤錯誤歡迎在評論中指出或聯絡我:QQ:847590417

總閱讀目錄

本章總內容

第一部分:

3.1 詞法分析程式的功能及實現方案

3.2 單詞的種類及詞法分析程式的輸出形式

3.3 正則文法及狀態圖

3.4 正則表示式與有窮自動機FA

第二部分:

3.5 有窮自動機、正則文法、正則表示式的轉化

0.正則文法 G轉狀態圖

1.DFA M轉正則文法 G

2.正則文法 G轉DFA M

3.正則表示式轉DFA M

4.DFA M轉正則表示式

5.正則文法 G轉正則表示式

6.正則表示式轉正則文法 G

3.6 詞法分析程式的設計與實現

3.6.1 詞法分析原理

3.6.2 詞法分析程式的構造

3.6.3 詞法分析程式的實現

3.7 詞法分析程式的自動生成器LEX

3.7.1 LEX基礎說明

3.7.2 LEX的實現

題目講解

 

本章總內容

重點:詞法分析介紹、詞法分析單詞種類劃分、正則文法、狀態圖、正則表示式、自動機、自動機的轉化、表示式文法和自動機的轉化、詞法分析程式的設計實現,詞法分析程式自動生成器LEX。

 

之前的內容

詞法分析介紹、詞法分析單詞種類劃分、正則文法、狀態圖、正則表示式、自動機、自動機的轉化會在第三章的第一部分進行介紹。

 

3.5 有窮自動機、正則文法、正則表示式的轉化

轉化流程圖:

以下轉換的順序是按圖上箭頭的順序進行排序的(NFA包含DFA,所以和NFA的轉化可能稱之為DFA的轉化)。

 

0.正則文法G轉狀態圖

繪製左線性文法的狀態圖(狀態圖只能用於左線性文法,這是和後面的DFA的明顯區別)狀態圖的繪製沒有嚴格規定(右線性的暫時不做考慮)

1.文法的非終結符號是一個個的結點

2.設一開始狀態S(句子)

3.對規則Q::=t(t為終結符),需要一條從S到Q的一條弧,弧上標記為t

4.對Q::=Rt,畫一條從R到Q的弧,弧上標記為t

(倒,誰規約於誰,誰指向誰)

5.根據自動機方法,可加上開始狀態和終止狀態標誌,識別符號作終止狀態,用雙圓圈標識

1.DFA M轉正則文法 G

規則:

1.對(A,t) = B,寫成:A→tB(只推右線性,左線性在推導時可能遞迴)

2.對每個可接受狀態Z(終止狀態),增加產生式Z→ε

3.有窮自動機的初態對應文法開始符號,有窮自動機的字母表為文法的終結符號集

例:

 

 

2.正則文法 G轉DFA M

規則:(和狀態圖的轉化類似)

1.字母表(弧上的所有符號組成的表)和G的終結符號相同

2.為G中的每個非終結符生成M的一個狀態,G大的開始符號S是開始狀態S

3.增加一個新狀態Z,作為NFA的終態

4.對G中的形如A→tB,其中t為終結符或空字元,A和B為非終結符號的產生式,構造M的一個轉換函式(A,t)=B

4.對G中形如A→t的產生式,構造M的一個轉換函式(A,t)=Z

例:

 

 

3.正則表示式轉DFA M

他們是等價的

定理:在Σ上的一個字集V,V是Σ*的子集,是正則集合,當且僅當存在一個DFA M使V=L(M).

規則:

一個正則表示式,構建時從左到右拆解分析即可

a. 對空集φ不作處理

b. 對正則式ε,由x射出符號為空符號的弧到y

c. 對字母表中存在的字母符號如正則式a,由x射出符號為該字元的弧到y

 

(x,y為狀態,只是構建的臨時初態終態,符號即是正則表示式中讀取到的字元(從左到右分解))

 

多個正則式,例如s,t,他們的NFA為Ns和Nt

a. R=s|t

 

b. R=st

 

c. R=s*

 

d. R=(s),和R=S的NFA一樣

 

例:

 

1.從裡開始構建NFA

 

 

 

2.從外開始構建

 

 

4.DFA M轉正則表示式

規則:

(1)在M上加兩個結點x,y。從x用空符號弧連線到M的所有初態節點,從M的所有終態節點用空符號弧連線到y,形成和M等價的的M’,此時只有一個初態一個終態。

(2)消除M’中的其他節點(除了x,y)

1.鄰合併

 

2.並變或

 

3.遞迴加邊加星號

 

 

即正則表示式轉NFA倒過來

 

例:

 

 

 

 

5.正則文法 G轉正則表示式

三個規則,可將正則文法轉換為一個只剩一個開始符號的產生式,並且右側不含非終結符,僅含對應的表示式。轉換後的產生式應用擴充的BNF表示,而在識別符號好的0~n次重複時應該用*代替

(1)代入規則:對A→xB,B→y轉化為A→xy

(2)消除遞迴規則:對A→xA|y轉化為A→x*y

(3)BNF規則:對A→x,A→y轉化為A→x|y

注:左線性的話,對A→Ax|y轉化為A→yx*

例如:

 

例:

 

 

6.正則表示式轉正則文法 G

規則如下:

(1)對任何正則表示式r,選擇一個非終結符S作為識別符號,併產生產生式S→r

(2)若x,y是正則表示式:

1.對A→xy,轉化為A→xB,B→y,B為新的非終結符

2.對A→x*y,轉化為A→xA,A→y(注:對A→x*y,則需要轉化為A→xA,A→ε)

3.對A→x|y的產生式

例如:

 

例:

 

左線性的話:(會死迴圈)

 

3.6 詞法分析程式的設計與實現

3.6.1 詞法分析原理

說明:

1.對於註釋符號是不輸出的

2.各單詞之間用空白符號(空格、製表、回車)分開

 

在得知文法後

需要根據文法將所有終結符號的轉化過程給繪製出來(初始符號就是每個終結符號)

 

這裡出現的其他字元,實際是任意字元,例如讀到+後再讀入+,後一個+相對於前一個也是其他字元。

 

然後將這些轉化過程都結合起來,初始狀態當做傳入的符號串。合併後還需要注意:對重複符號進行特殊處理(單雙字元分界符處理合並),還需要一個出錯的狀態(符號串不屬於任一流程)。

 

3.6.2 詞法分析程式的構造

不同狀態的做法

開始狀態:利用程式依次讀入字元,讀到空字元就跳過,然後對每一個非空字串轉到程式中進行處理。

識別符號狀態:在組合成識別符號後,判斷是保留字還是使用者自定義的

整數狀態:組成數字後還要做數字字元到二進位制數值的轉換

單字元分界符狀態:判斷對應的類別編碼即可

冒號狀態:需要和下一個字元結合進行判斷,是單字元還是雙字元

斜豎狀態:同樣需要判斷後面的字元,作為字元還是跳過註釋

錯誤狀態:列印錯誤資訊並跳過

 

注:在詞法分析時為了判別是否已經讀到了單詞的右端符號,有時候需要向前多讀一個字元,例如在識別符號和無符號整數等狀態。這是為了防止跳過某個不該跳過的字元。所以在返回呼叫程式前應該將讀字元指標後退一個字元。(字元指標後退實際就是退到前一個字元,因為在讀取字元時可能多讀一個字元,導致後面讀取時這個字元就被忽略了,所以需要後退(字元指標是一直前進的,後退就是向上一個讀的字元吐出來一個))

 

3.6.3 詞法分析程式的實現

一個詞法分析程式需要:1.單詞及內部表示 2.詞法分析程式需要引用的公共(全域性)變數和過程 3.詞法分析程式演算法

1.輸出形式:即按單詞及內部表示的規定進行(一般是二元式,一個是類別編碼,一個是對應的單詞值)

2.全域性變數和過程(即一個詞法分析程式需要引用的變數和過程,一般提前定義好需要使用的,需要用時呼叫即可)

 

 

3.詞法分析程式演算法

其實演算法程式的具體結構還是由開發者決定的,例如是否進行字元流的回退,如何進行型別的判斷等等,都是由具體的實現進行決定的。

 

將之前的完整狀態圖構造為演算法即可

虛擬碼:

 

當詞法分析程式作為子程式時,一般由語法分析程式呼叫,當詞法分析程式組合出一個單詞時就返回給語法分析語句,並且返回時應將單詞的類別碼送入變數單元symbol。(語法分析程式中會設有變數class,用於存放單詞的類別碼)

 

3.7 詞法分析程式的自動生成器LEX

3.7.1 LEX基礎說明

功能:輸入LEX源程式便可經過LEX後生成詞法分析程式L

然後輸入S.P.字串經過L便可輸出S.P.單詞字串

 

主要由三部分組成:

1.規則定義式,定義識別規則中要用到的正則表示式名

2.識別規則,用正則表示式給出單詞的定義和在識別後的下一步行為(例如要直行的程式碼片段)

3.使用者子程式,給出使用者需要的其他操作

各部分之間需要用%%分開

 

規則定義式:如下形式的LEX語句

,D為正則表示式名字,簡名;R為正則表示式

例如:

 

 

 

 

識別規則:一串如下形式的LEX語句

P為定義在Σ∪{D1,D2,D3.....}上的正則表示式,詞形

A為語句序列,是指識別出詞形為P的但此後,詞法分析器所應做的動作,基本動作即返回單詞的類別編碼和單詞值。

 

一個完整的LEX源程式:

 

小提示:正則中{}+,表示至少1次重複

 

3.7.2 LEX的實現

LEX的功能是根據LEX源程式構造一個此法分析程式,該詞法分析器實質上是一個有窮自動機。

LEX生成的詞法分析程式由兩部分組成:狀態轉換矩陣DFA和控制執行程式。則有LEX的功能即根據LEX源程式生成狀態轉換矩陣和控制程式。

LEX的處理過程:

 

NFA(空符號,多後繼),DFA一定是NFA

轉化成的DFA,每個新的終止狀態所識別的單詞型別,根據該子集包含的原NFA的終止狀態而定,只包含一個,則就是那個終止狀態是別的單詞,如果多個,則需要加一個或。

 

1.掃描每條識別規則P構造一相應的非確定有窮自動機M

2.將各條規則的有窮自動機Mi合併成一個新的NFA M

3.NFA確定化為DFA

4.生成該DFA的狀態轉換矩陣和控制執行程式

 

LEX的二義性原則,兩原則

例如begin是關鍵字還是識別符號

1.最長匹配原則

在識別單詞過程中,有一字串根據最長匹配原則,應識別為這是一個符合Pk規則的單詞而不是小範圍的:

 

2.最優匹配原則

如有一字串,有兩條規則可以匹配,那麼用規則序列中位於前面的規則相匹配,即排列在前面的的規則優先權高。

 

LEX例項:

 

1.得出單獨的NFA

 

2.合併為一個NFA

 

3.確定化

 

4.最後寫出狀態轉換矩陣和控制程式即可

 

分析過程:

 

構造出的LEX是一個通用的工具,用它可以生成各種語言的語法分析程式,只需要根據不同的語言書寫不同的LEX原始檔就可以了。

LEX不但能自動生成詞法分析其,而且也可以產生多種模式識別器及文字編輯程式。

 

題目講解

在描述推導過程是,如果有了根據...,則不必再說一個“可得”了

做題時注意判斷所有的終結符和非終結符,看題

判斷短語:在一句型的語法樹中,對任意結節點U,如果以其為根節點的子樹高度不為0,將此子樹的所有葉節點連線得到串u,u則是相對於U的對於該句型的短語,也就是說即使在樹的最後,只要有f→p,且p後無延伸,則p本身也是一個短語,且是一個簡單短語。

在繪製特定描述的字串自動機時,直接編寫語法可能會不夠隨機,可以用狀態圖進行輔助。

在根據集合獲取對應字元的後繼集合時,步驟如下:遍歷集合的每個狀態,獲取每個狀態通過任意長度符號為該符號的弧到達的狀態以及從該狀態經過任意長ε弧到達的狀態(不包含出發的那個狀態,除非可以通過這兩種方法到達)。遍歷結束後彙總獲取到的狀態即可獲得新的集合。

左右線性:根據右側非終結符的位置而定,在左則左。

左右線性文法生成狀態圖:後續補充。

 

給出描述的正則表示式時,注意幾個點:保持隨機,分段構造表示式,注意符號的真正含義(*是重複,並且是從0到無窮的,並且如果沒括號只能重複一個,例如(11)*就是偶數個重複)。

表示式構造FA:從外開始從左開始,並且*轉時,兩個ε不是必需的,何時使用??

進行確定化時由於是集合型別,所以注意看清

判斷NFA:同一個符號兩個後繼、有ε弧

FA的五元:全部狀態,全部符號,轉化矩陣,開始狀態(非空開始集合),終止狀態集合。注意狀態轉化後如果是{},就是多個後