編譯原理學習導論

編譯原理學習導論 php

 

大學課程爲何要開設編譯原理呢?這門課程關注的是編譯器方面的產生原理和技術問題,彷佛和計算機的基礎領域不沾邊,可是編譯原理卻一直做爲大學本科的必修課程,同一時候也成爲了研究生入學考試的必考內容。編譯原理及技術從本質上來說就是一個算法問題而已,固然由於這個問題十分複雜,其解決算法也相對複雜。咱們學的數據結構與算法分析也是講算法的,只是講的基礎算法,換句話說講的是算法導論,而編譯原理這門課程講的就是比較專一解決一種的算法了。在20世紀50年代,編譯器的編寫一直被以爲是十分困難的事情,第一Fortran的編譯器聽說花了18年的時間才完畢。在人們嘗試編寫編譯器的同一時候,誕生了不少跟編譯相關的理論和技術,而這些理論和技術比一個實際的編譯器自己價值更大。就宛如數學家們在解決著名的哥德巴赫猜測同樣,儘管沒有終於解決這個問題,可是其間誕生很多名著的相關數論。算法

 

推薦參考書 數據結構

儘管編譯理論發展到今天,已經有了比較成熟的部分,但是做爲一個大學生來講,要本身寫出一個像Turboc C,Java那樣的編譯器來講仍是太難了。不只寫編譯器困難,學習編譯原理這門課程也比較困難。函數

正是因爲編譯原理學習相對困難,那麼就要求有好的教師和好的教材。教師方面不是咱們能本身更改的,而在教材方面咱們卻可以按本身的意願來閱讀。我如下推薦幾本好的編譯原理的教材。我推薦的書籍都是國外的經典教材,因爲在國內的教材中,確實還沒發現什麼讓人愜意的。工具

 

第一本書的原名叫《Compilers Principles,Techniques,and Tools,另一個響亮的名字就是龍書。緣由是這本書的封面上有條紅色的龍,也因爲這本書在編譯原理基礎領域確實太有名氣了,因此很是多國外的學者都直接取名爲龍書。近期機械工業出版社已經出版了此書的中文版,名字就叫《編譯原理》。該書出的比較早,大概是在8586年編寫完畢的,做者之中的一個仍是著名的貝爾實驗室的科學家。裏面解說的核心編譯原理至今都沒有變過,因此一直到今天,它的價值都非凡。這本書最大的特色就是一開始就經過一個實際的小樣例,把編譯原理的大體內容羅列出來,讓很是多編譯原理的剛開始學習的人很是快內心有了個底,也知道爲何會有這些理論,怎麼運用這些理論。而這一點是我感受國內的教材缺少的東西,因此國內的教材都不是寫給願意自學的讀者,總之讓人看了半天,殊不知道里面的東西有什麼用。學習

第二本書的原名叫《Modern Compiler Design,中文名字叫作《現代編譯程序設計》。該書由人民郵電出版社所出。此書比較關注的是編譯原理的實踐,書中給出了很多的實際程序代碼,還有很是多實際的編譯技術問題等等。此書另一個特色就是其「現代」而字。在傳統的編譯原理教材中,你是不可能看到如同Java中的「垃圾回收」等算法的。因爲Java這種解釋運行語言是在近幾年才流行起來的東西。假設你想深刻學習編譯原理的理論知識,那麼你確定得看前面那本龍書,假設你想本身動手作一個先進的編譯器,那麼你得看這本《現代編譯程序設計》。flex

第三本書就是很是多國內的編譯原理學者都推薦的那本《編譯原理及實踐》。也許是這本書引入國內比較早吧,我記得我是在高中就買了這本書,只是也是在前段時間才把整本書看完。此書做爲新手教程也的確是個不錯的選擇。書中給出的編譯原理解說也至關仔細,儘管不如前面的龍書那麼深刻,但是很是多地方都是點到爲止,做爲大學本科教學已是十分深刻了。該書的特色就是注重實踐,只是感受還不如前面那本《現代編譯程序設計》的實踐味道更重。此書的重點仍是在原理上的實踐,而非前面那本那樣的技術實踐。《編譯原理及實踐》在解說編譯原理的各個部分的同一時候,也在逐步實踐一個現代的編譯器Tiny C.等你把整本書看完,差點兒相同本身也可以寫一個Tiny C了。做者還對LexYacc這兩個常用的編譯相關的工具進行了很是具體的說明,這一點也是很是難在國內的教材中看到的。優化

 

推薦了這三本教材,都有英文版和中文版的。很是多英文好的同窗僅僅喜歡看原版的書,不個人感受是這三本書的翻譯都很是不錯,沒有必要特別去買英文版的。理解理論的實質比理解表面的文字更爲重要。spa

 

編譯原理的實質 操作系統

前面已經說過,學習編譯原理事實上也就是學習算法而已,沒什麼特別的。僅僅只是這些算法的產生已經造成了一套理論。如下我來看看編譯原理裏面究竟有什麼高深的理論吧。

 

差點兒每本編譯原理的教材都是分紅詞法分析,語法分析(LL算法,遞歸降低算法,LR算法),語義分析,執行時環境,中間代碼,代碼生成,代碼優化這些部分。事實上現在很是多編譯原理的教材都是依照85,86出版的那本龍書來安排教學內容的,因此那本龍書的內容格式差點兒成了現在編譯原理教材的定式,包含國內的教材也是如此。通常來講,大學裏面的本科教學是不可能把上面的所有部分都認真講完的,而是比較偏重於前面幾個部分。像代碼優化那部分東西,就像個無底洞同樣,假設要認真講,就是單獨開一個學期的課也不可能講得清楚。因此,通常對於本科生,對詞法分析和語法分析掌握要求就相對要高一點了。

 

詞法分析相對來講比較簡單。多是詞法分析程序自己實現起來很是easy吧,很是多沒有學過編譯原理的人也相同可以寫出各類各樣的詞法分析程序。只是編譯原理在解說詞法分析的時候,重點把正則表達式和本身主動機原理加了進來,而後以一種十分標準的方式來解說詞法分析程序的產生。這種作法道理很是明顯,就是要讓詞法分析從程序上升到理論的地步。

 

語法分析部分就比較麻煩一點了。現在通常有兩種語法分析算法,LL自頂向下算法和LR自底向上算法。LL算法還好說,到了LR算法的時候,困難就來了。很是多自學編譯原理的都是遇到LR算法的理解成問題後就放棄了自學。事實上這些東西都是僅僅要你們理解就可以了,又不是像詞法分析那樣非得本身寫出來纔算真正的會。像LR算法的語法分析器,通常都是用工具Yacc來生成,實踐中全然沒有比較本身來實現。對於LL算法中特殊的遞歸降低算法,因爲事實上踐十分簡單,那麼就應該要求每個學生都能本身寫。固然,現在也有很多好的LL算法的語法分析器,只是要是換在非C平臺,比方Java,Delphi,你不能運用YACC工具了,那麼你就僅僅有本身來寫語法分析器。

 

等學到詞法分析和語法分析時候,你可能會出現這樣的疑問:「詞法分析和語法分析究竟有什麼?」就從編譯器的角度來說,編譯器需要把程序猿寫的源程序轉換成一種方便處理的數據結構(抽象語法樹或語法樹),那麼這個轉換的過程就是經過詞法分析和語法分析的。事實上詞法分析並非一開始就被列入編譯器的必備部分,僅僅是咱們爲了簡化語法分析的過程,就把詞法分析這樣的繁瑣的工做單獨提取出來,就成了現在的詞法分析部分。除了編譯器部分,在其餘地方,詞法分析和語法分析也是實用的。比方咱們在DOS,Unix,Linux下輸入命令的時候,程序怎樣分析你輸入的命令形式,這也是簡單的應用。總之,這兩部分的工做就是把不「規則」的文本信息轉換成一種比較好分析優勢理的數據結構。那麼爲何編譯原理的教程都終於把要分析的源分析轉換成「樹」這樣的數據結構呢?數據結構中有Stack, Line,List…這麼多數據結構,各自都有各自的特色。但是Tree這樣的結構有很是強的遞歸性,也就是說咱們可以把Tree的不論什麼結點Node提取出來後,它依然是一顆完整的Tree。這一點符合咱們現在編譯原理分析的形式語言,比方咱們在函數裏面使用函樹,循環中使用循環,條件中使用條件等等,那麼就可以很是直觀地表示在Tree這樣的數據結構上。相同,咱們在運行形式語言的程序的時候也是如此的遞歸性。在編譯原理後面的代碼生成的部分,就會介紹一種堆棧式的中間代碼,咱們可以依據分析出來的抽象語法樹,很是easy,很是機械地運用遞歸遍歷抽象語法樹就可以生成這樣的指令代碼。而這樣的代碼事實上也被普遍運用在其餘的解釋型語言中。像現在流行的Java,.NET,其底層的字節碼bytecode,可以說就是這中基於堆棧的指令代碼的。

 

關於語義分析,語法制導翻譯,類型檢查等等部分,事實上都是一種無缺前面獲得的抽象語法樹的過程。比方說,咱們寫C語言程序的時候,都知道,假設把一個浮點數直接賦值給一個整數,就會出現類型不匹配,那麼C語言的編譯器是怎麼知道的呢?就是經過這一步的類型檢查。像C++語言這中支持多態函數的語言,這部分要處理的問題就不少其它更復雜了。大部編譯原理的教材在這部分都是解說一些比較好的處理策略而已。因爲新的問題老是在發生,舊的辦法不見得足夠解決。

 

原本說,做爲一個編譯器,起做用的部分就是用戶輸入的源程序到終於的代碼生成。但是在解說終於代碼生成的時候,又不得不解說機器執行環境等內容。因爲假設你不知道機器是怎麼執行終於代碼的,那麼你固然沒法知道怎樣生成合適的終於代碼。這部份內容我自我感受其意義甚至超過了編譯原理自己。因爲它會把一個計算機的程序的執行過程都統統排在你面前,你未來可能不會從事編譯器的開發工做,但是僅僅要是和計算機軟件開發相關的領域,都會涉及到程序的執行過程。執行時環境的解說會讓你更清楚一個計算機程序是怎麼存儲,怎麼裝載,怎麼執行的。關於部分的內容,我強烈建議你們看看龍書上的解說,做者從最主要的存儲組織,存儲分配策略,非局部名字的訪問,參數傳遞,符號表到動態存儲分配(malloc,new)都做了十分具體的說明。這些東西都是咱們編寫尋常程序的時候經常要作的事情,但是咱們卻少去探求其內部是怎樣完畢。

 

關於中間代碼生成,代碼生成,代碼優化部分的內容就實在很差說了。國內很是多教材到了這部分都會很是easy地蜻蜓點水講過去,學生聽了也僅僅是做爲了解,不知道怎樣運用。只是這部份內容的東西假設要認真講,單獨開一學期的課程都講不完。在《編譯原理及實踐》的書上,對於這部分的解說就恰到優勢。做者主要解說的仍是一種以堆棧爲基礎的指令代碼,十分通俗易懂,讓人看了後,很是容易模仿,本身下來後就可以寫本身的代碼生成。固然,對於其餘代碼生成技術,代碼優化技術的解說就十分簡單了。假設要細緻研究代碼生成技術,事實上另外還有本叫作《Advance Compiler Desgin and Implement,那本書現在由機械工業出版社引進的,十分厚重,而且是英文原版。只是這本書我沒有把它列爲推薦書給你們,畢竟能把龍書的內容搞清楚,在中國已經就算很是不錯的高手了,到那個時候再看這本《Advance Compiler Desgin and Implement》也不遲。代碼優化部分在大學本科教學中仍是一個不過重要的部分,就是算是實踐過程當中,相信你們也不太運用獲得。畢竟,本身作的編譯器能正確生成運行代碼已經很是不錯了,還談什麼優化呢?

 

關於實踐

編譯原理的課程畢竟還僅僅是解說原理的課程,不是專門的編譯技術課程。這兩門課程是有很是大的差異的。編譯技術更關注實際的編寫編譯器過程當中運用到的技術,而原理的課關注解說其基本理論。但是計算機科學自己就是一門實踐性很是強的課程,假設能夠學以至用,那才叫真正的學會。李陽在解說瘋狂英語的時候就說到,僅僅要當你會實際中運用一個單詞一個詞組的時候你才幹叫學會了這個單詞或者詞組,而不是僅僅是知道了它的拼寫和意思。事實上不論什麼學習都是同樣的,假設缺乏了實踐的結合,你不能算學會。

 

編譯原理的課程主要就是解說編譯器產生的理論和原理,那麼很是easy,本身寫個編譯器就是最好的實踐過程了。只是你得當心,編譯系統多是所有軟件系統中最複雜的系統之中的一個,否則爲何大學裏面還會把編譯器的編寫開成一門叫作編譯原理的課程來說?我很是佩服那些學了操做系統原理就開始本身寫操做系統,學了編譯原理就開始本身寫編譯器的人們,確實,在中國,敢這麼作的學生太少了。且不管你這樣作能不能作成功,至少有了這個嘗試,會讓你的程序設計,系統規劃安排的功底增進很多。我如下給出一些關於實踐過程當中可能會遇到的困難,但願能夠在你陷入困境的前幫你一把。

 

1.       LexYacc. 這兩工具是做爲詞法分析很是語法分析的工具。假設你本身寫一個編譯器,我十分不建議你連詞法分析這樣的事情都親手來寫。LexYacc應該是做爲每本編譯原理的教材的必備內容,可是在國內的教材中缺很是少看到。這兩個工具是Unix系統下的小東西,假設你要在Windows中運用,那麼你最好去下在cygwin這個軟件。它是個在Windows下模擬Unix的東東,裏面就包括了flex.exebison.exe(yacc)這兩個工具.這兩個工具使用起來還挺麻煩的(事實上unix 下的很是多十分實用的工具都是這樣), 只是在《編譯原理與實踐》這本書上對於這兩個工具的解說十分具體,還列舉了很多實際的樣例。

2.       作解釋型語言比作生成機器代碼的編譯器簡單。儘管說,作解釋型的編譯器,像Java那樣的,你還得本身去寫解釋器,只是這樣你就沒必要去查找機器代碼的資料了。假設你作生成的終於機器代碼編譯器可能會遇到問題還有就是寄存器爲基礎的代碼生成方法。前面說過,假設你生成的是以堆棧爲基礎的代碼,那麼其代碼生成過程十分簡單,需要考慮的東西也很少,假設你考慮終於的機器代碼生成的話,你必須考慮機器的寄存器怎樣分配等麻煩的問題。

3.       考慮用別人已經生成的語法文件,儘可能不要本身動手寫詞法文件和語法文件.之前一個朋友之前說過,寫出一個好的程序語言的語法定義,就差點兒完畢了一個編譯器的一半.確實是這樣,語法文件的編寫是個很是難的事情.現在網上處處都可以找到比方C語言,C++,Java, Tiny C,Minus C等語言的詞法文件和語法文件,你全然可以本身下下來來用.

 

在《編譯原理及實踐》的書中,做者給出了一個Tiny C的全部代碼.我自我感受做者的這個編譯器作得很是不錯,相對於其餘php,perl等語言的源碼來講,簡單得多,easy看懂,而且很是清晰地展示了一個完畢的編譯系統的實現過程.其源碼可以在做者的站點上下載.

 

後話

編譯原理的學習可能算是一個困難的歷程,特別是對於那些不正確編譯系統感興趣的同窗來講.既然它已經做爲了大學本科的必修課程,那麼就說明的它引伸出來的一套理論在整個計算機科學領域仍是佔有相對重要的地位.

假設咱們考究一下歷史,就會發現很是多被稱爲程序設計大師的人都是編譯領域的高手.寫出第一個微型機上執行的Basic語言的比爾蓋茨,設計出DelphiBorland世界上最厲害的程序猿」, SunJAVA之父, 貝爾實驗室的C++之父

相關文章
相關標籤/搜索