手把手教你構建 C 語言編譯器(9)
恭喜你完成了自己的 C 語言編譯器,本章中我們發一發牢騷,說一說編寫編譯器值得注意的一些問題;編寫編譯器時遇到的一些難題。
手把手教你構建 C 語言編譯器系列共有10個部分:
虛擬機器與目的碼
整個系列的一開始,我們就著手虛擬機器的實現。不知道你是否有同感,這部分對於整個編譯器的編寫其實是十分重要的。我認為至少佔了重要程度的50%。
這裡要說明這樣一個觀點,學習編譯原理時常常著眼於詞法分析和語法分析,而忽略了同樣重要的程式碼生成。對於學習或考試而言或許可以,但實際編譯專案時,最為重要的是能“跑起來”,所以我們需要給予程式碼生成高度的重視。
同時我們也看到,在後期解析語句和表示式時,難點已經不再是語法分析了,而是如何為運算子生成相應的彙編程式碼。
詞法分析
我們用了很暴力的手段編寫了我們的詞法分析器,我認為這並無不可。
但你依舊可以學習相關的知識,瞭解自動生成詞法分析器的原理,它涉及到了“正則表示式”,“狀態機”等等知識。相信這部分的知識能夠很大程度上提高你的程式設計水平。
同時,如果今後你仍然想編寫編譯器,不妨試試這些自動生成工具。
語法分析
長期以來,語法分析對我而言一直是迷一樣的存在,直到真正用遞迴下降的方式實現了一個。
我們用了專門的一章講解了“遞迴下降”與 BNF 文法的關係。希望能減少你對理論的厭惡。至少,實現起來並不是太難。
如果有興趣,可以學習學習這些文法,因為已經有許多自動生成的工具支援它們。這樣你就不需要重複造輪子。可以看看 yacc 等工具,更先進的版本是 bsion
題外話,最近知道了一個叫“PEG 文法”的表示方法,無論是讀起來,還是實現起來,都比 BNF 要容易,你也可以學習看看。
關於編程式碼
這也是我自己的感慨吧。無論多好的教程,想要完全理解它,最好的方式恐怕還是要自己實現它。
只是在編寫程式碼的過程中,我們會遇到許多的挫折,例如需要考慮許多細節,或是除錯起來十分困難。但也只有真正靜下心來去克服它,我們才能有所成長吧。
例如在編寫表示式的解析時,大量重複的程式碼特別讓人崩潰。還有就是除錯編譯器,簡直痛苦地無話可說。
P.S. 如果你按這個系列自己編寫程式碼,記得事先寫一些用於輸出彙編程式碼的函式,很有幫助的。
還有就是寫這個系列的文章,開始的衝動過了之後,每寫一篇都特別心煩,希望文章本身沒有受我的這種情緒影響吧。
結語
程式設計有趣又無趣,只有身在其中的我們才能體會吧。