正則表達
語言是一個集合。因此可以在語言上進行運算(並U,或 | ,閉包 等)。
eg: L = {a}{a,b}*( {ε} U ( {.,_}{a,b}{a,b}*) ) //常規語言 (ε (epsilon)爲空串)
意思是:句首是a ,接下連接連接任意長度的a、b 串。然後有兩隻情況:1.連接空串,句子就結束了
2.連接.或_,然後連接長度>= 1的 a、b串。
正則表達式 (Regular Expression, RE)
描述正則語言的,緊湊的表示方法。
eg : 上面的表達式用正則是:r = a(a|b)*(ε | (.|_) (a|b) (a|b)* )
正則表達式 可由較小的正則表達式 ,按照特定的規則遞歸構建的。
正則表達式的定義
ε是RE,L(ε) = L(ε) ; //空串 是正則表達是,只表示空串。
a <- ∑ ,則 a 是RE, L(a) = {a}; //字母表了任意符號是RE,表示語言包含它自身。
假設r 和s 都是RE,表示語言爲 L(r) 和 L(s),
則 :r|s 是一個RE,L(r|s) = L(r) U L(s);//或
rs 是一個RE,L(rs) = L(r) L(s);
r* 是一個RE,L(r*) = (L(r) )* ;//Lr 的 克林閉包(任意長度 ,可爲ε 空串(0)
(r) 是一個RE,L( (r) ) = L(r) ;
運算優先級是:*、 連接、|
eg : 令 ∑ = {a, b} ,/// 符號表包含兩個字母a ,b 。
L(a|b) = L(a) U L(b) = {a}U{b} = {a,b} //一個符號 a 或 b
L((a|b)(a|b)) = L(a|b) L(a|b) = {a,b} {a,b} = {aa, ab, ba, bb} //兩個符號
L(a*) = (L(a))* = {a}* = {ε ,a,aa,aaa …} //一個符號 a 或 b
L((a|b)*) = (L(a|b))* == {a|b}* = {ε ,a,b,ba,bb,aa …}
L(a|a*b) = { a,b,ab,aab,aaab …}
C語言中符號整數的RE
十進制整數的RE : (1|...|9)(0|...|9)*
八進制整數的RE : (1|...|9)(0|...|9)*
十六進制整數的RE:0x(1|...|9|a|...|f)(1|...|9|a|...|f)*
正則定義
給某些RE命名,並在之後的RE中像字母表一樣使用這些名字。
d1 -> r1;
d2 -> r2;
...
每個d1, d2 都不在字母表∑中。
C語言中標識符的RE
digit -> 0|1|2|...|9
letter_ -> A|...|Z|a|...|z|_
eg 1 : id = litter_( litter_ | digit)* ///字母打頭的字母數字串
eg 1:(整數或浮點型)無符號數的RE定義
digit -> 0|1|2|...|9
digits -> digit digit* ///長度大於0 的數字
optionalFraction -> .digit|ε /// 可選的小數部分
optionalExponent -> (E (+|-| ε) digit) | ε;///可選的指數部分
number= digits optionalFraction optionalExponent
有窮自動機 (Finite Automata, FA)
概念
對一類處理系統建立的數學模型
特徵:1.具有一系列離散的輸入輸出信息和有窮數目的內部狀態。(狀態概況了對過去輸入信息的處理的狀況)
2.系統只需要根據當前所處的狀態和當前面臨的輸入信息就可以決定系統的後繼行爲。每當系統處理了當前輸入後,系統內部狀態也將發生改變。
FA的例子:電梯控制裝置
輸入:乘客的乘梯需求。
狀態:電梯所處的層數+運動方向。
電梯控制裝置 並不需要記住先前所有的服務要求,只需知道當前的狀態和未滿足的需求。
FA模型
輸入帶:存放輸入符號串
讀頭:從左至右逐個讀取輸入符號,不能修改,不能往返移動。
有窮控制器:具有有窮個狀態數,根據當前狀態和當前輸入符號,控制轉入下一狀態。
FA的表示
轉換圖
匹配原則
最長子串匹配原則:當輸入串的多個前綴,與一個或多個匹配時。總是選擇最長的前綴進行匹配。
有窮自動機分類
確定的FA :DFA 非確定的FA:NFA
DFA(確定的有窮自動機)
定義爲五元組。 M = (S, ∑, δ, S0, F);
S :有窮狀態集。
∑ :輸入字母表,即輸入符號集合。假設ε不是 Σ中的元素
δ :S*∑ 映射到S的轉換函數。δ(s,a)表示從s 出發沿着標記爲a的邊所到達的狀態。
S0:開始狀態 (或初始狀態),s0∈S
F:接收狀態(或終止狀態)集合,F⊆ S
例:一個DFA
NFA(非確定的有窮自動機)
M = (S, ∑, δ, S0, F)
∑ :輸入符號集合,即輸入字母表。假設ε 不是Σ中的元素
δ:將S×Σ映射到2S的轉換函數。s∈S, a∈Σ, δ(s,a)表示從狀態s出發,沿着標記爲a的邊所能到達的狀態集合
例:一個NFA
DFA和NFA的等價性
對於任何DFA D,存在識別同一語言的NFA N .
對於任何NFA N,存在識別同一語言的DFA D .
此三者是等價的。RE <=> NFA <=> DFA
NFA更直觀,DFA在計算機裏更容易去實現。
帶有"ε-"邊的NFA
M = (S, ∑, δ, S0, F)
∑ :輸入符號集合,即輸入字母表。假設ε 不是Σ中的元素
δ:將S×(Σ U {ε})映射到2的s次方 轉換函數。s∈S, a∈Σ, δ(s,a)表示從狀態s出發,沿着標記爲a的邊所能到達的狀態集合
帶有和不帶有 "ε-"邊的NFA的等價型
DFA的算法實現
輸入:以文件結束符eof結尾的字符串x。DFA D 的開始狀態s0,接收狀態集 F,轉換函數move。
輸出:如果 D接收 x,則回答“yes”,否則回答“no”。
方法:將下述算法應用於輸入串 x。
s = s0 ;
c = nextChar();
while(c! = eof ){
s = move ( s , c ) ;
c = nextChar ( ) ;
}
if (s在F中) return“yes”;
else return “no”;
函數nextChar( )返回輸入串x的下一個符號
函數move(s, c)表示從狀態s出發,沿着標記爲c的邊所能到達的狀態
從正則表達式到有窮自動機 (RE ->DFA)
eg: r = (a|b)*aabb對應的DFA爲。以下是分解步驟
從NFA到有DFA的轉化 (NFA -> DFA)
例1 :NFA -> DFA
R = aa*bb*cc*
帶有 "ε-"邊的NFA到DFA的轉換
R = 0*1*2*
子集構造法
識別單詞的DFA
識別標識符的DFA
識別各進制整數的DFA
十進制數的DFA
八進制數的DFA
十六進制的DFA
統一的:識別各進制整數的DFA
識別註釋的DFA
識別各類Token的DFA
詞法分析的錯誤處理
錯誤類型:單詞拼寫、非法字符串。
詞法錯誤檢測
當前轉換狀態與當前輸入符號在轉換表中對應的項目爲空,則報錯,調用錯誤處理。
錯誤處理
查找字符串中最後一個對應某終態的字符
找到了則說明在前面識別了一個單詞。將該字符和前面的單詞識別爲一個單詞。將輸入指針退回到該字符,掃描器從新回初始狀態,繼續掃描下一個。
沒找到則出錯了
恐慌模式來恢復。(一直刪除直到正確,編譯通過)
參考 :哈工大 陳鄞老師《編譯原理》視頻筆記。僅供自己複習參考使用,如有問題歡迎指出