詞法分析
編譯原理筆記第三部分,由於內容過長所以分為了兩部分,跳轉鏈接在總閱讀目錄處,內容參考:北航軟院教師邵兵課堂課件及內容、張莉著《編譯原理及編譯程序構造》、國防工業出版社的《編譯原理——學習指導與典型題解析》、AlvinZH的學習筆記以及個人理解
目前是包含了全部內容的版本,后續會推出精簡版和復習知識點版
如有建議或錯誤錯誤歡迎在評論中指出或聯系我:QQ:847590417
總閱讀目錄
3.1 詞法分析程序的功能及實現方案
3.2 單詞的種類及詞法分析程序的輸出形式
3.3 正則文法及狀態圖
3.4 正則表達式與有窮自動機FA
第二部分:
本章總內容
重點:詞法分析介紹、詞法分析單詞種類划分、正則文法、狀態圖、正則表達式、自動機、自動機的轉化、表達式文法和自動機的轉化、詞法分析程序的設計實現,詞法分析程序自動生成器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的五元:全部狀態,全部符號,轉化矩陣,開始狀態(非空開始集合),終止狀態集合。注意狀態轉化后如果是{},就是多個后繼。