版權聲明:本文爲原創文章,未經博主允許不得用於商業用途。
詞法分析
1、基本概念
- 詞法單元(Token):由詞法單元名和屬性值(可選)組成。其中屬性值用於區分同一符號表中重複的同種詞法單元。
- 模式(Pattern):描述一類詞法單元可能具有的形勢。
- 詞素(Lexeme):源程序中的一個字符序列,可以和某個詞法單元的模式匹配,並被詞法分析器識別爲該詞法單元的一個實例。
可以看出,詞法單元、模式和詞素是"一對一對多"的關係,下圖給出了c語言詞法一個示例:
2、概述
詞法分析在編譯器中位於以下位置:
從圖片上可知,詞法分析將字符串形式的源程序解析爲詞法單元,並且生成符號表。具體來說,詞法分析器具有如下作用:
-
讀入字符流,組成詞素,輸出詞法單元序列
-
過濾空白、換行、製表符、註釋等
-
將詞素添加到符號表中
-
將編譯器生成的錯誤信息和在源程序中的位置聯繫起來(後續)
從作用可以看出,其工作流程分爲掃描階段(去除註釋、多餘的空白符)和詞法分析(生成詞法單元)階段。
3、正則表達式
這裏所說的正則表達式爲最基本的正則表達式,只包含如下四種運算:並(a|b)、連接(ab)、Kleene閉包(a*)、正閉包(a+)。其中運算優先級爲{‘*’,‘+’}>‘連接’>‘|’。
遞歸定義
正則表達式可以通過遞歸定義,設正則表達式集合爲R,則
- 空串,
正則定義
爲了書寫方便,主流語言常常使用了正則定義預定義了常用正則串。正則定義規則如下:
按照如下形式定義串:
其中滿足:
- 爲新符號,不在符號集合中,且各不相同
- 是定義在字母表$\Sigma \bigcup {d_1,d_2,…,d_{i-1}} $上的正則表達式。(避免遞歸定義)
有窮自動機
比正則表達式更加優秀的語言表示方法是有窮自動機。所有的正則表達式都可以用有窮自動機來表示。
一個有窮自動機包含:
- 有限的狀態集合
- 有限的符號集合
- 轉移函數(可以用狀態表表示)
- 初始狀態(有些有窮自動機可以有多個)
- 接受狀態集合
有窮自動機分爲兩類:
- 不確定的又窮自動機(Nondeterministic Finite Automate, NFA),即對狀態圖中邊上的標號沒有限制,特別的,同一符號可以出現在離開同一狀態的多條邊上,且空串可以作爲符號出現在邊上。
- 確定的有窮自動機(Deterministic Finite Automate,DFA),對於每個狀態及一個符號有且只有一條邊。
算法1:NFA到DFA
算法如下:
其中,表示NFA中通過空串符可以從s狀態到達的狀態集合,表示T狀態接收到a字符後可達的狀態集合,表示轉換表中T行a列的表項,即T狀態接收到a字符後的下一個狀態。
算法的流程即將0步可達的狀態合併爲同一個狀態,之後不斷遍歷字符集移動到下一個狀態集合,如果之前沒出現過此狀態集合則定義爲DFA中的新的狀態。
例:NFA轉化爲DFA
初始狀態,接受a後可達,因此下一個狀態爲,之前沒有出現過,因此作爲DFA中的新狀態B。
按順序計算即可得轉換表:
其中A爲初始狀態,E爲接受狀態。
算法2:正則表達式到NFA
正則表達式到NFA的轉化可以通過對四種運算的遞歸獲得。
-
基本規則:
- :
- :
- :
-
歸納部分
- :
- :
- :
- :
算法3:DFA狀態數量最小化
- 把所有可區分的狀態分開 (迭代過程)
- 基本步驟:ε區分了接受狀態和非接受狀態
- 歸納步驟:如果s和t是可區分的,且s’到s、t’到t有標號 爲a的邊,那麼s’和t’也是可區分的
- 最終沒有區分開的狀態就是等價的
例:簡化DFA
如圖,
-
首先區分接受狀態和非接受狀態
-
之後細分第一個集合,根據字符b可以劃分爲和(D收到b後移動到可區分狀態E)
-
之後細分第一個集合,根據字符b可以劃分爲和(B收到b後到達可區分狀態狀態D)
-
對於任何字符都不可區分,因此可以合併爲一個狀態。簡化完成。