用300多行C++代碼寫一個超簡單的編譯器
目標(biāo)
????將一個可以支持輸入任意多個字符串的語言的源代碼編譯成exe格式的可執(zhí)行文件。
????該語言只支持一種語句,格式是【 print(字符串); 】,也就是以【print】開頭,后跟【(】, 再跟著一個【字符串】,最后跟著【)】和【;】?,一條語句只包含5個單詞,一個程序支持任意多條該語句。
????麻雀雖小,五臟俱全。
流程

詞法分析
????詞法分析就是將源代碼分割成一個一個的單詞,舍棄不需要的字符,比如注釋等。
????那么需要先定義單詞的結(jié)構(gòu),先定義單詞的類型:

?然后是單詞:

????只要知道什么單詞以什么開頭,后面跟著什么,以什么結(jié)尾,詞法分析就很簡單了:




錯誤處理
????沒有哪個程序員不會寫錯代碼的,因此,錯誤處理也是必不可少的一部分,這部分的主要目的是識別出語法錯誤,并告訴程序員在哪里出了什么錯誤。
????這里當(dāng)出現(xiàn)錯誤的時候,就簡單地告訴出錯信息和位置,然后結(jié)束編譯。

語法分析
????整個結(jié)構(gòu)和詞法分析差不多。
????

????這是識別具體語句的部分:

????其中還嵌入了語義分析的代碼和中間代碼生成的代碼。
語義分析
????語法分析識別出的是源代碼的結(jié)構(gòu),而語義分析要判斷這個語句是要做什么,能不能這么做。

????因此,這里只需要判斷調(diào)用的那個函數(shù)是不是“print”函數(shù)就行了。
中間代碼生成
????此處,我使用的是三地址碼表示的中間代碼,三地址碼只是一個結(jié)構(gòu),該結(jié)構(gòu)有一個操作碼和3個操作數(shù),并沒有指定實際的操作碼和操作數(shù)是什么。這些需要我們自己定義,也就是構(gòu)造我們自己專屬的指令集。而指令集用什么結(jié)構(gòu)表示都可以,比如三地址碼,抽象語法樹,有向無環(huán)圖等,這是多對多的關(guān)系。
????

匯編生成
????到這一步,就是編譯器的后端了,需要選擇具體的機器的指令集和匯編器。不同的匯編器的匯編代碼的語法可能不同。
????當(dāng)然也可以不生成匯編代碼,直接生成可執(zhí)行文件。但是這就需要了解可執(zhí)行文件的結(jié)構(gòu),以及具體的指令的編碼是什么了,比如nop指令的編碼是0x90。
????這里,我選擇了686指令集已經(jīng)masm32匯編器。
????至于中間代碼怎么轉(zhuǎn)成匯編代碼,基本是一條中間代碼對應(yīng)多條匯編代碼,怎么對應(yīng)?加法對加法,入棧對入棧,賦值對賦值,就是這么回事。
????





測試
????




????如果匯編出錯,那么很可能是沒有安裝masm32!?。?br>