【編譯原理】 CS143 斯坦福大學公開課 第二週:詞法分析和有限自動機(下)

youtube :詞法規則

文章較長,是4節視頻的合集,大家看的時候多思考吧。

4.1| Lexical Specification – 詞法規則

回顧:

在這裏插入圖片描述

如何識別任意字符串是否屬於某一語言?

步驟:

  1. 寫出所有token class的正則表達式

比如:

Number = ‘digit'
Keyword = 'if'+'else'+...
identifier = letter (letter+digit)*
OpenPar = '('
  1. Lexical Speicification R = 所有token class的並
R = Keyword + identifier + Number + ...
  = r1 + r2 + r3 + ...
  1. 輸入字符串x1...xn,針對字符串的某個前綴(即子串),判斷其是否屬於L(R)
    for 1 <= i <= n 檢查
        x1...xi 屬於 L(R)
  1. 如果3成立,那麼x1...xi就屬於L(R),否則x1...xi不屬於L(R)
    x1...xi 屬於 L(Rj) 成立對於一些j
  1. x1...xix1...xn中刪除,轉入3繼續判斷,直到x爲空(哦,原來如此,有點神奇呀!)

避免以上流程中的二義性:

  1. 總是選擇最大的前綴x1...ximaximal match

比如: ’==‘不會看成兩個’=‘

  1. 對給定前綴x1...xi,匹配其對應的token class中優先級最大的那個(正想問呢)

比如:'if'可能屬於identifier或者keyword,此時優先識別爲keyword

  1. 設定error集合,表示不屬於該語言的字符串。若輸入此類字符串,則報錯。(定義的規則好像很嚴謹耶,都是大神 /w\ )

Error放到最後(優先級最低),因爲可能我們定義的Error太草率,和前面的正確的正則表達式有重合。

4.2| Finite Automata – 有窮自動機

本節主要講了:如何用有窮自動機實現正則表達式

  • Finite Automata用於等價地實現正則表達式

  • Finite Automata組成:

An input alphabet – 字母表E

A finite set of states – 有限的狀態集合S

A start states – 開始狀態n

A set of accepting states – 終止狀態

A set of transitions – 狀態轉換

  • 有窮自動機的圖示:
    在這裏插入圖片描述
  • language of a FA = set of accepted strings – 有窮自動機對應的語言:其接受(終止狀態)的字符串組成的集合

比如輸入爲字符串'110',經過有窮自動機後,Accepts(接受):
在這裏插入圖片描述


epsilon move 空轉換,不用輸入就可以從狀態A轉換到狀態B

  • DFA 確定型的有窮自動機
  1. 一個輸入對應一個確定的狀態轉換(即一個確定的輸入不會轉換到兩個狀態)

  2. 沒有空轉換

  • NFA 非確定型的有窮自動機
  1. 一個輸入可以同時對應多個狀態轉換

  2. 可以有空轉換

4.3| Regular Expressions into NFAs – 正則表達式轉換爲NFAs

Lexical specification --> Regular Expression --> NFA --> DFA --> Table-driven Implementation of DFA

(詞法規範 --> 正則表達式 --> 不確定的有窮自動機 --> 確定的有窮自動機 --> 一組查詢表和一些遍歷表的代碼)

前面的部分完成了前兩步,定義了NFA、DFA。(瞬間明朗了haha…)


對於每一個正則表達式,定義NFA、以及空字符和字符a如下:

在這裏插入圖片描述

那麼(好秀呀!),這樣的話正則表達式可以直接按照模板套,變成NFA

在這裏插入圖片描述
在這裏插入圖片描述

4.4| NFA to DFA – NFA to DFA

(上課是真滴沒聽懂這一塊QAQ)

  • 定義:epsilon closure – 從某狀態通過空轉換可達到的所有狀態的集合

  • 定義:NFA

起始狀態:A

轉換得到的狀態:a(X)=從X出發由輸入a能達到的所有狀態

終止狀態:F

  • 那麼:從NFA轉換到DFA

起始狀態:epsilon closure(A)

轉換得到的狀態:X-a->Y if Y = epsilon closure(a(X)) (意思就是從X轉換到一個狀態集,包含所有從X出發,經過空轉換或或其他轉換能到達的狀態)

終止狀態:只要當前狀態集中包含F,就是終止狀態

  • 簡單來說:NFA一個輸入可以轉換到不同狀態,DFA一個輸入轉換到一個唯一的狀態集(包含不同狀態)

比如 (1+0)*1 NFA表示如下:

在這裏插入圖片描述

步驟:

  1. 從A(起始狀態)開始,找出epsilon closure(A) = ABCDHI,作爲DFA的起始狀態。(如下圖,紫色圈出)

  2. 可能的轉換是’1’或者’0’,從’0’開始可以到達F,那麼求epsilon closure(F) = FGHIABCD。(如下圖,深藍色圈出)

  3. 從’0’開始可以到達E或者J,那麼求epsilon closure(E) + epsilon closure(F) = ABCDEGHIJ,因爲包含J,所以說終止狀態。(如下圖,紅色圈出)

  4. 對紅圈、深藍圈繼續上面的步驟。

在這裏插入圖片描述

練習(字母我自己標的,不一定正確,結果是正確的):

在這裏插入圖片描述

4.4| Implementing Finite Automata – 實現有窮自動機

一個DFA可以用一個2維數組T實現
一個維度表示狀態
一個維度表示輸入符號
對於每一個轉換 Si --a--> Sk , 定義T[i,a] = k

根據轉換表A處理輸入字符串(pretty cool)

i = 0;              // 初始化指向開始狀態
state = 0;          // 表示當前狀態
while(input[i]) {   // 對於輸入,更新state
    state = A[state][input[i++]];
}

因爲N個狀態的NFA可能對應2^N-1個DFA狀態,所以可以用指針壓縮表,也可以直接將NFA轉換爲表格。

DFA – 更快、不太緊湊

NFA – 慢,簡潔

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章