(一)編譯程序整體結構git
ZhouPascalCompiler是一個簡化版的的Pacal編譯器,由詞法分析器、語法分析器、語義分析與中間代碼生成器以及貫穿於前三個階段的符號表管理器和出錯處理器組成。它的工做流程爲:輸入源程序code.txt,詞法分析分析出其中的單詞符號,若是在分析過程當中未出現詞法錯誤,則生成中間文件lex.txt,不然向屏幕打印錯誤類型提示並定位出錯位置,程序終止。這樣設計的好處在於先進行比較簡單的詞法分析,避免了沒必要要的計算開銷,節省了計算機資源。由於若是設計成以語法分析器爲核心的結構,則在分析過程當中一旦發現某個詞法錯誤,那麼以前全部的語法分析和翻譯動做都白作了。若詞法分析成功生成lex.txt,語法分析器進行語法分析工做:須要一個單詞時,就從lex.txt讀出一行,根據預測分析表和狀態棧、符號棧的棧頂符號決定將此單詞壓棧/規約,若規約成功,則輸出「accept」;不然,輸出「error」和錯誤緣由。採用語法制導翻譯的方式,在語法分析的同時進行語義分析和中間代碼生成,可翻譯的語句類型有:含嵌套過程的聲明語句、含數組的賦值語句、布爾表達式、if/while/for/repeat、過程調用語句、輸入輸出語句。符號表管理器用於管理程序中的各類標識符、過程名、過程嵌套關係等。出錯處理對器程序不符合詞法或語法要求的地方進行定位並提示出錯信息。程序員
該編譯程序的源代碼在https://github.com/zhouliyan/PascalCompilergithub
這學期在《編譯原理》這門課的實驗中收穫了不少。最重要的是學習了一種系統設計的思想,一種對全局把握的能力。系統是一個很龐大的工程,它裏面包含不少模塊,模塊之間相互聯繫,雖然儘可能使用「高內聚,低耦合」的設計思想,但系統越大,不可避免地會提升模塊之間的耦合程度,這時就須要設計者既有一種縱觀全局的開闊眼界,又有對每個細節的精準把握。在編寫這個編譯器的過程當中個人體會是:代碼越多,調試越困難。由於代碼越多,程序一旦編寫錯了,定位出錯位置就比較難了。好比我在編寫語法分析器的過程當中發現有一個錯誤如何調試都不對,後來發現不是語法分析的代碼有錯,而是以前編寫的詞法分析器有一個隱性的錯誤當時測試時沒有發現,這讓我感到其實程序測試也是很重要的一項的工做,尤爲是在比較大型的系統編寫過程當中,須要對以前編寫的代碼進行充分的測試,保證在開始新工做以前之前的代碼都是正確的。另外一個讓我印象深入的錯誤是在編寫符號表的過程當中,是一個很低級的錯誤,但卻花費了我好幾天也沒調試出來,就是聲明一個指針int *pint;那麼在訪問過程當中如pint+1,這個1的單位不是字節,而是這個pint類型的size,在這裏至關於加了4個字節。這個錯誤在於我對C語言的掌握不夠,之前的知識模糊。調試這個錯誤的過程當中IDE提示的出錯位置不是在這,而是在另外一個malloc申請內存的語句處,這是由於之前錯誤對不應訪問的地址訪問、賦值,致使程序在申請堆上空間時出錯。數組
C語言的指針很強大,但用很差也會致使災難。我以爲這正是這門語言的迷人之處,它和別的語言不一樣,程序員對每一個變量都必須清楚地知道它是從哪來的,將要到哪去,何時消失。換句話說,程序員對細節必須徹底清楚。好比我,若是我聚精會神地編一上午Python代碼,幾乎一運行就能經過,結果正確。而聚精會神地編一上午C代碼,調試可能仍是會有點小問題須要修改。數據結構
這門課的另外一個好處是讓我複習了之前學過的一些有用的數據結構,好比棧、鏈表、隊列等。並且我也收穫到了如何建立本身的數據結構,而且讓它更高效的經驗。學習
還有一個很大的收穫就是學習到一種「折中」的思想,這在系統設計過程當中尤其重要。有時候咱們無法達到魚與熊掌兼得,效率與空間兼得,這是就須要衡量一下什麼對咱們來講更重要。有時候須要犧牲空間換取效率,在另外一些時候則反之,須要具體狀況具體分析。好比我在設計符號棧中的數據結構token的時候,由於這個符號多是整型、實型、數組型等等,不一樣的類型有不一樣的屬性,也就是須要不一樣的域,能夠設置一個拓展的指針域存放該節點的屬性們,也能夠直接將這些屬性當成節點的域,每一個節點擁有的域都是相同的,對應不一樣類型的token向不一樣域存屬性便可,其餘域沒有用。前面一種方案看起來能夠大大節省節省空間,但我選擇了後者。這樣作的緣由是:減小了不一樣類型token使用指針尋址,查找的時間,提升了效率。並且後來我改進了這種方案,即將token從符號棧中彈出的同時銷燬token所佔的空間,這樣很是好地解決了空間問題,token佔的多餘空間幾乎沒有;另外在程序編寫過程當中,我發現token的一些閒置域還能夠放其餘的東西,更加減小了浪費。測試
在這門課中我完成了編譯器的詞法分析、語法分析、中間代碼生成模塊,符號表管理和出錯處理還須要加強,在之後有時間的時候我會繼續作下去,指望本身能完成剩餘的中間代碼優化、目標代碼生成部分,完善符號表管理模塊,加強出錯處理功能。若是未來有一天能把這些完成了,我就能真正和別人說我作了一個pascal編譯器了。雖然這門課結束了,但我探索編譯之路纔剛剛開始。優化