banner
DIYgod

Hi, DIYgod

写代码是热爱,写到世界充满爱!
github
twitter
follow
bilibili
telegram
email
steam
playstation
nintendo switch

一個完整編譯器的實現(一) 詞法分析

GitHub 地址 各階段源碼 各階段說明集合

為了將一個程序從一種語言翻譯成另一種語言,編譯器必須首先把程序的各種成分拆開,並搞清其結構和含義,然後再用另一種方式把這些成分組合起來。編譯器的前端執行分析,後端進行合成。

而分析一般分為 3 種:詞法分析 句法分析 語義分析

本階段進行的是詞法分析,目的是將輸入文件分解成一個個獨立的詞法符號,即單詞。

根據虎書的提示,在本階段分了三個模塊:

1. 錯誤處理模塊(errormsg.c errormsg.h):用來產生含文件名和行號的報錯信息
2. 詞法分析模塊(lexical.lex token.h):通過 Lex 進行詞法分析
3. 常用工具模塊(util.c util.h):定義一些常用的函數

詞法分析模塊與錯誤處理模塊:兩者通過 errormsg.h 中聲明的變量和函數進行通信:EM_tokPos 變量傳遞每個單詞以字符為單位的位置;EM_newline () 函數記錄行號;EM_error () 輸出報錯信息。

錯誤處理模塊與常用工具模塊:錯誤處理模塊使用 util.h 中聲明的 checked_malloc () 分配內存函數

另外還包含了 驅動程序(driver.c)測試文件(test.c) makefile

下面主要介紹本階段最重要的詞法分析模塊。

tokens.h:定義詞法單詞常量以及 yylval

上述代碼定義了 yylval,yylval 是一個表示不同語義值的集合,其中的 ival cval dval sval 分別用來保存 整數 字符 浮點數 字符串 單詞的語義值。

這段定義了一些常數,這些常數供 lexical.lex 使用,它們指明被匹配的是何種類型的單詞。

lexical.lex:Lex 的源文件,可以通過 Lex 生成一個詞法分析器

Lex 是一個可以將正則表達式轉換成詞法分析器的生成器,它由詞法規範生成一個 C 程序(lex.yy.c)。該規範包含一個正則表達式和一個動作。這個動作將單詞類型(可能和其他信息一起)傳給編譯器的下一處理階段。

第一部分,即位於 %{...%} 之間的部分,包含有若干由此文件其餘部分 C 代碼使用的 include 和聲明。

第二部分,即位於 %}...%% 之間的部分,包含正則表達式的簡寫形式和狀態說明,比如你可以寫上

那麼第三部分中就可以用 {digits} 代替 [0-9]+ 了。

第三部分,即位於 %% 後面的部分,包含正則表達式和動作。每個動作返回一個 int 類型的值(token.h 定義的常數),指出匹配的是哪一種單詞。
其中有兩條匹配的原則來消除二義性:
規則優先:對於一個特定的最長初始子串,第一個與之匹配的正則式決定這個子串的單詞類型;
最長匹配:通過規則優先確定正則式之後,子串取與正則式匹配的最長的字符串。

幾個變量:yytext 是正則式匹配的字符串;yyleng 是所匹配的字符串的長度;charPos 追蹤每一個單詞的位置,並告知 EM_tokPos。

 

詞法分析 Done.

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。