1. 程式人生 > >編譯原理——詞法分析(1)

編譯原理——詞法分析(1)

在我們學習詞法分析時,就會思考如何構造一個詞法分析器? 一個詞法分析器可以通過手工構造;也可以通過以下方式自動生成一個詞法分析器:向一個詞法分析器生成工具描述出詞素的模式,然後將這些模式編譯為具有動詞分析器功能的程式碼。

如何對正則表示式進行轉換? 首先轉換為不確定有窮自動機,然後再轉換為確定有窮自動機。

詞法分析器的作用: 1.讀入源程式的輸入字元、將他們組成詞素,生成並輸出一個詞法單元序列,每個詞法單元對應於一個詞素。這個詞法單元序列被輸出到語法分析器進行語法分析。 2.詞法分析器通常還要和符號表進行互動。當詞法分析器發現了一個識別符號的詞素時,它要將這個詞素新增到符號表中。在某些情況,詞法分析器會從符號表中讀取有關識別符號種類的資訊,以確定向語法分析器傳送哪個詞法單元。 3.完成一些識別詞素之外的其他任務。(1)過濾掉源程式中的註釋和空白(空格、換行符、製表符以及在輸入中用於分隔詞法單元的其他字元)(2)將編譯器生成的錯誤資訊與源程式的位置聯絡起來。例如詞法分析器可以負責記錄遇到的換行符的個數,以便給每個出錯資訊賦予一個行號。如果源程式使用了一個巨集前處理器,則巨集的擴充套件也可以由詞法分析器完成。

詞法分析器與語法分析器的互動過程:通常,互動是由語法分析器呼叫詞法分析器來實現的,其中圖中的命令getNextToken所指示的呼叫使得詞法分析器從它的輸入中不斷讀取字元,知道它識別出下一個詞素為止。詞法分析器根據這個詞素生成下一個詞法單元並返回給語法分析器。

詞法分析器分成兩個級聯的處理階段:     1.掃描階段,主要負責完成一些不需要生成詞法單元的簡單處理,比如刪除註釋和將多個連續的空白字元壓縮成一個字元。     2.詞法分析階段,處理掃描階段的輸出並生成詞法單元。

詞法分析中,常見的三個術語。詞法單元,模式和詞素詞法單元(token):詞法單元由一個詞法單元名和一個可選的屬性值組成。詞法單元名是一個表示某種詞法單位的抽象符號,是由語法分析器處理的輸入符號。但是,在很多情況下,詞法分析器不僅僅向語法分析器返回一個詞法單元名字,還會返回一個描述該詞法單元的詞素的屬性值。詞法單元的名字將影響語法分析過程中的決定,而這個屬性則會影響語法分析之後對這個詞法單元的翻譯。一個識別符號的屬性值是一個指向符號表中該識別符號對應條目的指標。模式(pattern)

:描述了一個詞法單元的詞素可能具有的形式。詞素(lexeme):是源程式中的一個字元序列,它和某個詞法單元的模式匹配,並被詞法分析器識別為該詞法單元的一個例項。 光從概念上來看,會覺得十分抽象很難理解,但是結合例子來理解,就會明白他們三者的關係。

正則表示式:正則表示式是一種可以很方便地描述詞素模式的方法。

在很多程式設計語言中,下面的類別覆蓋了大部分或所有的詞法單元:     (1)每個關鍵字有一個詞法單元。一個關鍵字的模式就是該關鍵字本身。比如:if else     (2)表示運算子的詞法單元。它可以表示單個運算子,也可以像comparison那樣,表示一類運算子。     (3)一個表示所有識別符號的詞法單元。     (4)一個或多個表示常量的詞法單元,比如數字和字面值字串。     (5)每一個標點符號有一個詞法單元,比如左右括號、逗號和分號。

當詞法錯誤時,可能採取的其他錯誤恢復動作包括:     (1)從剩餘的輸入中刪除一個字元。     (2)向剩餘的輸入中插入一個遺漏的字元。     (3)用一個字元來替換另一個字元。     (4)交換兩個相鄰的字元。 不過最簡單的策略是看一下是否可以通過一次變換將剩餘輸入的某個字首變成一個合法的詞素。

輸入緩衝     雙緩衝區方案,加快源程式讀入速度的方法,這種方案能安全處理向前看多個符號問題.-,=,< 可能是->,==,<=這樣雙字元運算子的開始,我們將考慮一種改進方法,這種方法用哨兵標記來節約檢查緩衝區末端的時間。

什麼叫緩衝區對?         由於在編譯一個大型程式需要處理大量的字元,處理這些字元需要很多時間,由此開發了一些特殊的緩衝技術來減少用於處理單個輸入字元的時間開銷。一種重要機制是利用兩個交替讀入的緩衝區。

    緩衝區對的具體實現流程         每個緩衝區容量都是N個字元,通常N是一塊磁碟塊大小,如4096位元組             1.程式為輸入維護了兩個指標                  lexemeBegin指標:該指標指向當前詞素的開始處.當前我們正試圖確定這個詞素的結尾.                 forward指標:它一直向前掃,直到發現某個模式被匹配到為止             2. 一旦確定下一個詞素,forward指標將指向該詞素結尾的字元.                  詞法分析器將這個詞素作為某個詞法單元記錄下來並返回,然後使lexemeBegin指標指向剛找到詞素後的第一個位置           處理完後,forward指標也會前移一個位置            3.如果forward指標前移,要求我們首先檢查是否已經到達某個緩衝區的末尾。(哨兵標記優化的地方)                  如果是,我們將N個新字元讀到另一個緩衝區末尾,且將forward指標指向這個新載入符的頭部.         

哨兵標記:

如何優化檢測緩衝區末尾?

檢查是否到了末尾,並且確定讀入的字元

優化後:在緩衝區末尾擴充套件一個絕對不會使用的符號,叫做哨兵(sentinel)字元,一個自然的選擇是eof.