??? 文法是一個四元組:G = {VT,VN,S,P}
?
??? 其中VT是一個非空有限的符號集合,它的每個元素成為終結符號。VN也是一個非空有限的符號集合,它的每個元素稱為非終結符號,并且VT∩VN=Φ。S∈VN,稱為文法G的開始符號。P是一個非空有限集合,它的元素稱為產生式。所謂產生式,其形式為α→β,α稱為產生式的左部,β稱為產生式的右部,符號“→”表示“定義為”,并且α、β∈(VT∪VN)*,α≠ε,即α、β是由終結符和非終結符組成的符號串。開始符S必須至少在某一產生式的左部出現一次。另外可以對形式α→β,α→γ的產生式縮寫為α→β|γ,以方便書寫。
?
??? 注:一般以大寫字母表示非終結符,以小寫字母表示終結符。
?
??? 著名語言學家Noam Chomsky(喬姆斯基)根據對產生式所施加的限制的不同,把文法分成四種類型,即0型、1型、2型和3型。
?
0型文法
?
??? 設G={VT,VN,S,P},如果它的每個產生式α→β是這樣一種結構:α∈(VT∪VN)* 且至少含有一個非終結符,而β∈(VT∪VN)*,則G是一個0型文法。0型文法也稱短語文法。一個非常重要的理論結果是:0型文法的能力相當于圖靈機(Turing)。或者說,任何0型文語言都是遞歸可枚舉的,反之,遞歸可枚舉集必定是一個0型語言。0型文法是這幾類文法中限制最少的一個,所以一般見到的至少是0型文法。
?
1型文法
??? 1型文法也叫上下文有關文法,此文法對應于線性有界自動機。它是在0型文法的基礎上每一個α→β,都有|β|>=|α|。這里的|β|表示的是β的長度。
??? 注意:雖然要求|β|>=|α|,但有一特例:α→ε也滿足1型文法。
??? 如有A->Ba則|β|=2,|α|=1符合1型文法要求。反之,如aA->a,則不符合1型文法。
?
2型文法
?
??? 2型文法也叫上下文無關文法,它對應于下推自動機。2型文法是在1型文法的基礎上,再滿足:每一個α→β都有α是非終結符。如A->Ba,符合2型文法要求。
??? 如Ab->Bab雖然符合1型文法要求,但不符合2型文法要求,因為其α=Ab,而Ab不是一個非終結符。
?
3型文法
?
??? 3型文法也叫正規文法,它對應于有限狀態自動機。它是在2型文法的基礎上滿足:A→α|αB(右線性)或A→α|Bα(左線性)。
??? 如有:A->a,A->aB,B->a,B->cB,則符合3型文法的要求。但如果推導為:A->ab,A->aB,B->a,B->cB或推導為:A->a,A->Ba,B->a,B->cB則不符合3型方法的要求了。具體的說,例子A->ab,A->aB,B->a,B->cB中的A->ab不符合3型文法的定義,如果把后面的ab,改成“一個非終結符+一個終結符”的形式(即為aB)就對了。例子A->a,A->Ba,B->a,B->cB中如果把B->cB改為B->Bc的形式就對了,因為A→α|αB(右線性)和A→α|Bα(左線性)兩套規則不能同時出現在一個語法中,只能完全滿足其中的一個,才能算3型文法。
?
一些相關的定義:
?
??? 1、當G為2型或3型文法時,命題“L(G)是空集、有限集或無限集”才是可判斷的。
??? 2、當G1和G2都是3型文法時,命題“L(G1)=L(G2)”才是可判斷的。
??? 3、最左/右推導:推導的每一步都對最左/右的非終結符使用推導公式
??? 4、若S可以推出mAn,而A可以推出a,則稱a是非終結符號A的、句型mAn的短語。若存在A=>a,則為直接短語。
??? 5、一個句型的最左直接短語稱為該句型的句柄
??? 6、素短語是一個短語,它至少包含一個終結符,并除自身外不包含其他的素短語。
?
*************************************************************************
注:此類問題可以用語法樹來判定,規則如下
?
1.每個句型對應一棵語法樹
2.每棵語法樹的所有葉子結點從左到右排列構成一個句型
3.每棵語法樹的子樹的葉子結點從左到右排列構成一個短語
4.每棵語法樹的簡單子樹(只有父子兩層結點)的葉子結點從左到右排列構成一個簡單(直接)短語
5.每棵語法樹的最左簡單子樹(只有父子兩層結點)的葉子結點從左到右排列構成句柄
6.素短語是至少包含一個終結符的短語,但它不能包含其它素短語
7.最左推導:在每個推導過程中,總是首先考慮對當前最左邊的非終結符號進行推導??
8.最右推導:在每個推導過程中,總是首先考慮對當前最右邊的非終結符號進行推導
?
舉例如下:
?
Vt={a,b,d,(,)}.Vn={S,T},S是開始符
S -> a|b|(T)
T -> TdS|S
句型(Sd(T)db)是S的一個_____,其中___是句柄;____是最左素短語;____是該句型的直接短語,_____是短語。
?
?
語法樹如下:
????????????? S??
??????????? / | \??
?????????? (? T? )??
?????????? /? |? \??
????????? T?? d?? S??
??????? / | \???? |??
?????? T? d? S??? b??
?????? |??? /|\??
?????? S?? ( T )??
?
1.首先在T->S之后還有一個S-b的推導,所以該句型不是最左推導,只是一個簡單的推導
2.再看直接短語,有S,(T),b這3個,其余子樹均大于或等于3層
3.句柄為最左直接短語,即S
4.素短語在短語中從左往右找,S不是排除,Sd(T)包含了(T),排除,最后剩下
(T)為最左素短語
5.短語很多,直接從備選答案里找即可
?
*************************************************************************
-------------------------------------------------------------------------------
?
?
有限狀態自動機
?
??? 注:說明一點,只要是有限狀態自動機,則必定符合3型文法,且可用正則表達。
?
??? 一個確定的有限狀態自動機M(記做DFA)是一個五元組:M=(∑,Q,q0,F,δ)
?
??? 其中:
??? (1) Q是一個有限狀態合集
??? (2) ∑是一個字母集,其中的每個元素稱為一個輸入符號
??? (3) q0∈Q,稱為初始狀態
??? (4) F∈Q,稱為終結狀態集合
??? (5) δ是一個從Q×∑(Q與∑的笛卡爾積)到Q的單值映射:
??????? δ(q,a)=q* (q,q*∈Q, a∈∑)
??????? 以上式子表示當前狀態為q,輸入符號a時,自動機將轉換到下一個狀態q*,q*稱為q的一個后繼。
?
??????? 若Q={q1,q2,...,qn
},∑={a1,a2,...,an},則(δ(qi,aj))n×m是一個n行m列矩陣,稱為DFA的狀態轉換矩陣,或稱轉換表。
?
?
??? 有限狀態自動機可以形象地用狀態轉換圖表示,舉例如下:
?
??? DFA M=({S,A,B,C,f},{1,0},S,{f
},δ)
??? 其中:δ(S,0)=B, δ(S,1)=A, δ(A,0)=f, δ(A,1)=C, δ(B,0)=C, δ(B,1)=f, δ(C,0)=f
, δ(C,1)=f
??? 則對應的狀態轉換圖如下所示:
?
???
??? 其中圈表示狀態結點,雙圈表示終結狀態結點,而邊表示狀態的轉換,代表映射。邊上的符號表示此轉換需要輸入的符號,代表映射的輸入。
?
??? 對于∑上的任何字符串w∈∑*,若存在一條從初始結點到終態結點的路徑,在這條路徑上的所有邊的符號連接稱的符號串恰好是w,則w被DFA所識別(或接受、讀出)。DFA所能識別的符號串的全體記為L(M),稱為DFA所識別的語言。
?
?
NFA介紹
?
??? 之前介紹的是確定的有限自動機,即一個狀態對于待定的輸入字符有一個確定的后繼狀態。而當一個狀態對于特定的輸入字符有一個以上的后繼狀態時,我們稱該有限自動機為非確定有限自動機(記做NFA),其形式定義也是M=(∑,Q,q0,F,δ),且前面的字符定義均和DFA相同,但是δ:Q×∑對應所有Q的任意子集。
?
??? 在NFA中能夠識別的路徑與DFA中定義也相同。
?
??? 對任何一個NFA,都存在一個DFA*使L(M*)=L(M),這時我們稱M*與M等價。構造與M等價的M*的基本方法是讓M*的狀態對應于M的狀態集合。即如果δ(q,a)={q1,q2,...,qn},則把{q1,q2,...,qn}看作M*的一個狀態,即M*中的狀態集合Q*的一個元素。
?
正則表達式的轉換
?
??? DFA和NFA和正則式的轉換比較模式化,看一個例子就明白了,具體的方法可以看下面這篇博客:
?
****************************************************************************************
?
版權聲明:可以任意轉載,但轉載時必須標明原作者charlee、原始鏈接
http://tech.idv2.com/2006/05/08/parse-regex-with-dfa/
以及本聲明。
程序編譯的第一個階段是詞法分析,即把字節流識別為記號(token)流,提供給下一步的語法分析過程。而識別記號的方法就是正則表達式的分析。本文介紹利用有限自動機分析表達式的方法。
概念
-
記號
-
有字母表中的符號組成的有限長度的序列。記號s的長度記為|s|。長度為0的記號稱為空記號,記為ε。
-
有限自動機(Finite State Automaton)
-
為研究某種計算過程而抽象出的計算模型。擁有有限個狀態,根據不同的輸入每個狀態可以遷移到其他的狀態。
-
非確定有限自動機(Nondeterministic Finite Automaton)
-
簡稱NFA,由以下元素組成:
-
1. 有限狀態集合S;
-
2. 有限輸入符號的字母表Σ;
-
3. 狀態轉移函數move;
-
4. 開始狀態 sSUB{0};
-
5. 結束狀態集合F,F ∈ S。
-
自動機初始狀態為sSUB{0},逐一讀入輸入字符串中的每一個字母,根據當前狀態、讀入的字母,由狀態轉移函數move控制進入下一個狀態。如果輸入字符串讀入結束時自動機的狀態屬于結束狀態集合F,則說明該自動機接受該字符串,否則為不接受。
-
確定有限自動機(Deterministic Finite Automaton)
-
簡稱DFA,是NFA的一種特例,有以下兩條限制:
-
1. 對于空輸入ε,狀態不發生遷移;
-
2. 某個狀態對于每一種輸入最多只有一種狀態轉移。
將正則表達式轉換為NFA(Thompson構造法)
算法
算法1 將正則表達式轉換為NFA(Thompson構造法)
輸入 字母表Σ上的正則表達式r
輸出 能夠接受L(r)的NFA N
方法 首先將構成r的各個元素分解,對于每一個元素,按照下述規則1和規則2生成NFA。 注意:如果r中記號a出現了多次,那么對于a的每次出現都需要生成一個單獨的NFA。
之后依照正則表達式r的文法規則,將生成的NFA按照下述規則3組合在一起。
規則1 對于空記號ε,生成下面的NFA。
規則2 對于Σ的字母表中的元素a,生成下面的NFA。
規則3 令正則表達式s和t的NFA分別為N(s)和N(t)。
a) 對于s|t,按照以下的方式生成NFA N(s|t)。
b) 對于st,按照以下的方式生成NFA N(st)。
c) 對于s*,按照以下的方式生成NFA N(s*)。
d) 對于(s),使用s本身的NFA N(s)。
性質
算法1生成的NFA能夠正確地識別正則表達式,并且具有如下的性質:
-
N(r)的狀態數最多為r中出現的記號和運算符的個數的2倍。
-
N(r)的開始狀態和結束狀態有且只有一個。
-
N(r)的各個狀態對于Σ中的一個符號,或者擁有一個狀態遷移,或者擁有最多兩個ε遷移。
示例
利用算法1,根據正則表達式 r=(a|b)*abb 可以生成以下的NFA。
將NFA轉化為DFA
算法
使用以下的算法可以將NFA轉換成等價的DFA。
算法2 將NFA轉化為DFA
輸入 NFA N
輸出 能夠接受與N相同語言的DFA D
方法 本算法生成D對應的狀態遷移表Dtran。DFA的各個狀態為NFA的狀態集合,對于每一個輸入符號,D模擬N中可能的狀態遷移。
定義以下的操作。
操作
|
說明
|
ε-closure(s)
|
從NFA的狀態s出發,僅通過ε遷移能夠到達的NFA的狀態集合
|
ε-closure(T)
|
從T中包含的某個NFA的狀態s出發,僅通過ε遷移能夠到達的NFA的狀態集合
|
move(T, a)
|
從T中包含的某個NFA的狀態s出發,通過輸入符號a遷移能夠到達的NFA的狀態集合
|
令 Dstates 中僅包含ε-closure(s), 并設置狀態為未標記;
while Dstates中包含未標記的狀態T do
begin
? 標記T;
? for 各輸入記號a do
? begin
??? U := ε-closure(move(T, a));
??? if U不在Dstates中 then
????? 將 U 追加到 Dstates 中,設置狀態為未標記;
??? Dtrans[T, a] := U;
? end
end
ε-closure(T)的計算方法如下:
將T中的所有狀態入棧;
設置ε-closure(T)的初始值為T;
while 棧非空 do
begin
? 從棧頂取出元素t;
? for 從t出發以ε為邊能夠到達的各個狀態u do
??? if u不在ε-closure(T)中 then
??? begin
????? 將u追加到ε-closure(T)中;
????? 將u入棧;
??? end
end
示例
將上面生成的NFA轉化為DFA。
最初,Dstates內僅有ε-closure(0) = A = {0, 1, 2, 4, 7}。然后對于狀態A,對于輸入記號a,計算 ε-closure(move(A, a)) = ε-closure(move({0, 1, 2, 4, 7}, a)) = ε-closure({3, 8}) = {1, 2, 3, 4, 6, 7, 8},即 B={1, 2, 3, 4, 6, 7, 8}, Dtran[A, a]=B。對于狀態A,由輸入記號b能夠到達的僅有4->5,因此 C = ε-closure({5}) = {1, 2, 4, 5, 6, 7},即 Dtran[A, b] = C。
以此類推,可得到以下的狀態和Dtran。
A = {0, 1, 2, 4, 7}????????? D = {1, 2, 4, 5, 6, 7, 9}
B = {1, 2, 3, 4, 6, 7, 8}??? E = {1, 2, 4, 5, 6, 7, 10}
C = {1, 2, 4, 5, 6, 7}
狀態
|
輸入符號
|
a
|
b
|
A
|
B
|
C
|
B
|
B
|
D
|
C
|
B
|
C
|
D
|
B
|
E
|
E
|
B
|
C
|
由此得出DFA如下圖所示。
NFA和DFA的效率
給定正則表達式r和輸入記號序列x,判斷r是否能夠接受x。
使用NFA的情況下,由正則表達式生成NFA的時間復雜度為O(|r|),另外由于NFA的狀態數最多為r的2倍,因此空間復雜度為O(|r|)。由NFA判斷是否接受x時,時間復雜度為O(|r|×|x|)。因此,總體上處理時間與 r、x的長度之積成比例。這種處理方法在x不是很長時十分有效。
如果使用DFA,由于利用DFA判斷是否接受x與狀態數無關,因此時間復雜度為O(|x|)。但是DFA的狀態數與正則表達式的長度呈指數關系。例如,正則表達式 (a|b)*a(a|b)(a|b)...(a|b),尾部有 n-1 個 (a-b)的話, DFA最小狀態數也會超過 2SUP{n}。
?
?
?
-The End-