編譯原理(3):詞法分析

聲明:本系列文章,是根據中國大學MOOC網 哈工大的編譯原理 這門課學習而成的學習筆記。


一、正則表達式

正則表達式

  • 語言是一個集合,因此我們可以在語言上進行多種集合運算。比如說並運算,乘積運算(即連接運算),閉包運算等等。接下來我們看一個語言的例子,如下圖所示:

在這裏插入圖片描述
這個語言的字首是字母 a,接下來連接一個任意長度的 a,b串,再接下來連接一個空串。連接一個空串就代表句子已經結束了。除此之外,我們還可以連接一個點號(.)或者下劃線(_)或者一個長度大於等於1 的 a,b串。

在這裏插入圖片描述

正則表達式的定義

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

在這裏插入圖片描述

  • 十進制整數的正則表達式:第一個符號是1~9中的一個數字,接下來連接若干個 0~9 的數字,或者連接符號 0。
  • 八進制整數的正則表達式:第一個符號是數字0,第二個符號是1~7中的一個數字,接下來連接若干個 0~7 中的數字。
  • 十六進制整數的正則表達式:第一個符號是0,第二個符號是 x,第三個符號是1f中的符號,接下來連接若干個0f 中的符號。

正則語言

  • 可以用RE定義的語言叫做正則語言(regular language)或正則集合(regular set)
  • 正則表達式也遵循一些代數定律,如下圖所示:
    在這裏插入圖片描述

正則文法與正則表達式等價

  • 對任何正則文法 G,存在定義同一語言的 正則表達式 r
  • 對任何正則表達式 r,存在生成同一語言的 正則文法 G

二、正則定義(Regular Definition)

  • 爲了方便起見,我們可以給某些正則表達式命名,像使用字母表中的符號一樣,使用這些名字來構造正則表達式。
    在這裏插入圖片描述

在這裏插入圖片描述

  • digit,表示0~9中的某個數字
  • letter_,表示一個字母(小寫字母或大寫字母)和一個下劃線。
  • id,首先是一個 letter_,接下來連接一個 letter _ 或 digit 構成的字符串。這個表達式表示的是字母打頭的字符數字串。(正是標識符的定義)

在這裏插入圖片描述

  • digit,表示一個數字
  • digits,digit 連接上一個 digit 的克林閉包,表示的是一個長度>=1 的數字串。
  • optionalFraction,點號(.)後面連接一個 digits 或 這個表達式是一個空串。(這個符號表示的是一個小數部分,或一個空串)代表可選的小數部分。
  • optionalExponent,大寫字母 E 後面連接一個 + (正號)或 一個 -(負號)或直接連接一個長度大於等於1 的數字串(digits),或者這個表達式爲空串。可選的指數部分。
  • number,長度大於等於1 的數字串,連接一個可選的小數部分,連接一個可選的指數部分。

三、有窮自動機 ( Finite Automata,FA )

  • 一類處理系統建立的數學模型
  • 具有一系列離散的輸入輸出信息有窮數目的內部狀態(狀態:概括了對過去輸入信息處理的狀況)
  • 系統只需要根據當前所處的狀態和當前面臨的輸入信息就可以決定系統的後繼行爲。每當系統處理了當前的輸入後,系統的內部狀態也將發生改變

FA模型

在這裏插入圖片描述

  • 輸入帶:用來存放輸入符號串
  • 讀頭:從左向右逐個讀取輸入符號,不能修改(只讀),不能往返移動
  • 有窮控制器:具有有窮個狀態數,根據當前的狀態和當前輸入符號控制轉入下一狀態。

FA 的表示:轉換圖

在這裏插入圖片描述

  • 結點:FA 的狀態
    初始狀態(開始狀態):只有一個,由 start 箭頭指向
    終止狀態:可以由多個,用雙圈表示
  • 帶標記的有向邊:如果對於輸入 a ,存在一個從狀態 p 到狀態 q 的轉換,就在 p、q 之間畫一條有向邊,並標記上 a。

FA定義(接受)的語言

  • 給定輸入串 x,如果存在一個對應於 串 x 的從初始狀態到某個終止狀態的轉換序列,則稱 串 x 被該 FA 接受。
  • 由一個有窮自動機 M 接受的所有串構成的集合稱爲是該 FA定義(或接收)的語言,記爲 L(M)。
    在這裏插入圖片描述

最長子串匹配原則

  • 當輸入串的多個前綴與一個或多個模式匹配時,我們總是選擇最長的前綴進行匹配。
  • 在到達某個終態之後,只要輸入帶上還有符號,就繼續前進,以便找到儘可能長的匹配。
    在這裏插入圖片描述

四、有窮自動機的分類

  • 確定的有窮自動機(DFA)
  • 不確定的有窮自動機(NFA)

確定的有窮自動機(DFA)

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

DFA 的算法實現

  • 輸入:以文件結束符 eof 結尾的字符串 x,DFA 的開始狀態爲 s0,接受狀態集 F,轉換函數 move
  • 輸出:如果 D 接受x,則回答“yes”,否則回答“no”
  • 方法:將下述算法應用於輸入串 x
    在這裏插入圖片描述

不確定的有窮自動機(NFA)

在這裏插入圖片描述
NFA和DFA的唯一的區別是:從狀態 s 出發,能到達的狀態可能有多個。
轉換函數爲集合而不是元素。

在這裏插入圖片描述

帶有ε邊的NFA

在這裏插入圖片描述

  • 在狀態 a,不需要遇到任何符號,即可進入狀態 b,在狀態 b,不需要任何符號,即可進入狀態 c。
  • 一旦進入狀態 b,就不再接受符號 0,同理,一旦進入狀態 c,就不在接受符號 1。

帶有ε邊和不帶有ε邊的NFA的等價性

在這裏插入圖片描述

DFA 和 NFA 的等價性

  • 對任何非確定的有窮自動機N,存在定義同一語言的確定的有窮自動機D。
  • 對任何確定的有窮自動機D,存在定義同一語言的非確定的有窮自動機 N。

DFA 和 NFA 可以識別相同的語言

在這裏插入圖片描述
DFA 和NFA 都識別的是以 abb結尾的 a,b 串。

五、從正則表達式到有窮自動機。

根據 RE 構造 NFA

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

例子:r=(a|b)*abb 對應的 NFA
在這裏插入圖片描述
可以看出不停的分解子表達式,即可求得最終的 NFA。

六、從NFA 到DFA 的轉換

從NFA 到DFA 的轉換

在這裏插入圖片描述

從帶有ε邊的NFA到DFA的轉換

在這裏插入圖片描述

子集構造法

在這裏插入圖片描述

計算ε-closure 空閉包函數

在這裏插入圖片描述

七、識別單詞的 DFA

識別標識符的DFA

在這裏插入圖片描述

識別無符號數的DFA

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

識別各進制無符號整數的 DFA

在這裏插入圖片描述

識別註釋的 DFA

在這裏插入圖片描述

識別 token 的 DFA

在這裏插入圖片描述

詞法分析階段的錯誤處理

詞法分析階段可檢測錯誤的類型

  • 單詞拼寫錯誤,例:int i=0x3G,float j=1.05e
  • 非法字符,例:~@

詞法錯誤檢測

  • 如果當前狀態與當前輸入符號在轉換表對應項中的信息爲空,而當前狀態又不是終止狀態,則調用錯誤處理程序。

錯誤處理

  • 查找已掃描字符串中最後一個對應於某終態的字符
  • 如果找到了,將該字符與其前面的字符識別成一個單詞。然後將輸入指針退回到該字符,掃描器重新回到初始狀態,繼續識別下一個單詞
  • 如果沒找到,則確定出錯,採用錯誤恢復策略。

錯誤恢復策略

  • 最簡單的錯誤恢復策略:“恐慌模式”恢復
  • 從剩餘的輸入中不斷刪除字符,直到詞法分析器能夠在剩餘輸入的開頭髮現一個正確的字符爲止。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章