動手編寫1個編譯器,學習1下較為底層的編程方式,是1種學習計算機究竟是如何工作的非常有效方法。
編譯器通常被看做是10分復雜的工程。事實上,編寫1個產品級的編譯器也確切是1個龐大的任務。但是寫1個小巧可用的編譯器卻不是這么困難。
秘訣就是首先去找到1個最小的可用工程,然后把你想要的特性添加進去。這個方法也是Abdulaziz Ghuloum在他那篇著名的論文“1種構造編譯器的捷徑”里所提到的辦法。不過這個辦法確切可行。你只需要依照這篇論文中的第1步來操作,就能夠得到1個真正可用的編譯器!固然,它只能編譯程序語言中的非常小的子集,但是它確切是1個真實可用的編譯器。你可以隨便的擴大這個編譯器,然后從中學到更多更深的知識。
遭到這篇文章的鼓舞,我就寫了1個C編譯器。從某種意義上來講這比寫1個scheme的編譯器要困難1些(由于你必須去解析C那復雜的語法),但是在某些方面又很便利(你不需要去處理運行時類型)。要寫這樣1個編譯器,你只需要從你那個可用的最小的編譯器開始。
對我寫的編譯器來講,我把它叫 babyc,我選了這段代碼來作為我需要運行的第1個程序:
沒有變量,沒有函數調用,沒有額外的依賴,乃至連if語句,循環語句都沒有,1切看起來是那末簡單。
我們首先需要解析這段代碼。我們將使用 Flex 和 Bison 來做到這點。這里有怎樣用的例子可以參考,幸虧我們的語法是如此簡單,下面就是詞法分析器:
這里是語法分析器:
終究,我們需要生成1些匯編代碼。我們將使用32位的X86匯編,由于它非常的通用而且可以很容易的運行在你的機器上。這里有X86匯編的相干網站。
下面就是我們需要生成的匯編代碼:
然后加上上面的詞法語法分析代碼,把這段匯編代碼寫進1個文件里。恭喜你!你已是1個編譯器的編寫者了!
Babyc 就是這樣誕生的,你可以在這里看到它最開始的模樣。
固然,如果匯編代碼沒辦法運行也是枉然。讓我們來用編譯器生成我們所希望的真實的匯編代碼。
非常棒!接著讓我們來真實的運行1下編譯以后代碼來確保它能得到我們所想的結果。
我們踏出了第1步,接下去怎樣做就全看你了。你可以依照那篇文章所指點的全部做1遍,然后制作1個更加復雜的編譯器。你需要去寫1個更加精致的語法樹來生成匯編代碼。接下去的幾步分別是:(1)允許返回任意的值(比如,return 3; 1些可履行代碼);(2)添加對“非”的支持(比如,return ~1; 1些可履行代碼)。每個額外的特性都可以教你關于C語言的更多知識,編譯器究竟是怎樣履行的,和世界上其他編寫編譯器的人是如何想的。
這是構建 babyc 的方法。Babyc 現在已具有了if語句,循環,變量和最基礎的數據結構。歡迎你來check out它的代碼,但是我希望看完我的文章你能夠自己動手寫1個。
不要懼怕底層的1些事情。這是1個非常奇妙的世界。
上一篇 透過CPU看應用程序的性能
下一篇 GIS中的WKB介紹