摘要:結合編譯課程教學特點,收集當前常用的編譯資源,并從編程語言和教學知識點兩個角度對這些資源進行歸類分析;在此基礎上,探討如何利用這些資源開展編譯課程的課堂教學和實踐教學。
關鍵詞:編譯原理;工具資源;實踐教學
1.背景
編譯理論與技術是計算機科學中發(fā)展最迅速、最成熟的一個重要分支,程序設計語言和編譯的發(fā)展集中體現了計算機科學的重要成果與精華。編譯原理課程是計算機科學與技術專業(yè)的專業(yè)必修課程,主要講授程序設計語言編譯程序構造的基本原理和方法。編譯程序的開發(fā)堪稱經典理論和先進技術緊密結合的典型示范,因此理論學習和實踐的緊密結合是本課程的突出特色。通過編譯程序構造的問題,可以體驗到如何從實際需求中提出理論問題、理論研究推動技術進步、運用技術工具解決實際問題的過程。
在經典理論的支持下,在編譯程序的研制過程中,產生了非常豐富的工具資源。在這些工具資源的支持下,編譯程序開發(fā)的自動化程度得到了顯著提高;相對其他軟件開發(fā)任務,編譯程序開發(fā)在效率和質量上的優(yōu)勢非常明顯。更為重要的是,編譯的理論和技術對于計算機科學中的其他領域也有重要的影響。一直以來,編譯的理論和技術在程序設計語言的實現、針對計算機體系結構的優(yōu)化、新的計算機體系結構的設計、自然語言理解、網絡信息處理、網絡協議的分析與實現等領域都是不可或缺的。國外著名大學(如美國哥倫比亞大學、哈佛大學和斯坦福大學等)的編譯課程教學都特別重視相關的課程實踐項目。以哥倫比亞大學為例,在編譯原理的課程教學中開展了貫穿整個學期的課程實踐項目。在項目中,學生分成小組,自主設計并實現一個小的語言,而這個語言涉及了豐富的領域,包括量子計算、音樂合成、計算機圖形學、游戲、矩陣計算和很多其他領域。在這些教學實踐中,很多編譯開發(fā)工具都被應用于各種案例中,包括ANTLR、LEX和YACC等編譯領域經典的開源軟件工具。
通過收集編譯資源(包括開源的編譯器和編譯程序開發(fā)工具),以及這些工具在計算機科學各領域中的成功應用案例,可以為開展案例式教學改革打下堅實的基礎。筆者收集了編譯領域常用的開源軟件工具及其應用案例,并對其進行歸類分析和整理,以形成支撐編譯課堂教學和實踐教學的資源庫?;谠撡Y源庫,在今后的編譯原理課程教學中,可以通過采取基于案例的教學方法,形象地向學生展示編譯研究中“經典理論和先進技術有機結合”的突出特點,使學生能夠通過具體的案例切實體驗編譯經典理論在各領域的重要作用。
2.編譯資源分析
在幾十年的研究過程中,編譯領域已經形成了很多編譯資源,如LEX、YACC、JavaCC為代表的編譯模塊開發(fā)工具,以及精簡語言編譯器、產品級開源編譯器等。這些工具實現了從Ada、C、Pascal等面向過程語言到Java、C++等面向對象語言的編譯程序,覆蓋了文法、詞法分析、語法分析、中間代碼生成、代碼優(yōu)化、目標代碼生成等編譯原理教學中所有的知識點?;谶@些工具也開發(fā)了SQL、XML分析等計算機科學其他領域的應用。下面,筆者從生成語言、知識點覆蓋等角度對互聯網上的編譯資源進行整理分析。
2.1從編程語言的角度分析
從編譯資源所面向的程序語言來看,從面向特殊領域的Fortran語言、DSP語言,面向過程的C語言、Pascal語言,到常見的面向對象的Java語言、C++、C#語言等,均有種類繁多的分析器、生成器、目標代碼優(yōu)化器等可用于案例教學的編譯資源。
1)面向過程語言的編譯資源。
這方面的編譯資源主要針對C語言和Pascal語言。C語言作為最被廣泛使用的編程語言,也擁有最多的編譯工具資源,如YACC、LEX、ACCENT、BANSHEE等經典工具均可用來產生C語言編程的分析器、生成器。其中,最知名的C語言解析器生成器YACC已經在各種場合得到了廣泛應用。YACC也是常用于編譯課程教學的工具,它采用LALR(1)語法分析方法,最初由AT&T為Unix操作系統(tǒng)開發(fā),在漫長的演變中產生了如Berkeley YACC、GNU BISON、MKS YACC和Abraxas YACC等變種版本,也出現了AYACC、YACC++等面向ADA、c++其他語言的編譯器。由于所產生的解析器需要詞法分析器配合,因此YACC經常和詞法分析器產生器LEX一起使用,目前已有IEEE相關標準對YACC和LEX的功能進行了標準化描述。此外,ACCENT、BEG、CKIT等面向c語言的編譯資源也可以用于編譯課程教學。據我們初步統(tǒng)計,目前互聯網上可用的針對c語言的編譯資源多達20余種,涵蓋了詞法分析、語法分析、前端、后端生成器、代碼優(yōu)化、程序分析等編譯過程中的各個環(huán)節(jié)。
2)面向對象語言的編譯資源。
面向對象語言已成為程序開發(fā)的主流語言,在應用層軟件、網絡服務開發(fā)上占據著絕對優(yōu)勢地位。因此,目前也相應出現了很多針對面向對象編程語言的編譯資源,特別是C++語言和Java語言。C++語言由于與C語言一脈相承,許多針對c語言的編譯工具也擴展了c++版本,如YACC++、Berkeley YACC、IDC-C等,均可以生成C/C++語言的分析器。
Java語言在最近20年一直是最流行的編程語言。Java語言為了實現跨平臺的目標,在編譯時僅生成字節(jié)碼,再由不同平臺的JVM生成目標代碼執(zhí)行;因此,Java語言的編譯執(zhí)行具有明確的前端后端,非常有利于編譯程序的開發(fā)和編譯原理知識點的分解。目前針對Java語言的編譯資源與工具種類繁多,如JavaCC、JastAdd、Jax、Jfront、Soot、PAT等,我們目前已經收集到相關編譯資源20余種,既有JavaCC等綜合編譯環(huán)境,又有Jfront前端工具、PAT正則表達式分析器、OOPS分析優(yōu)化工具等編譯工具資源。
3)其他專用語言、平臺的編譯資源。
為了符合特殊應用場景的計算需求,出現了一些針對特定領域、特定平臺的程序語言,同樣,在這些領域中對編譯器往往也存在獨特的需求,如嵌入式系統(tǒng)、科學計算等,如針對SPARC平臺的編譯器BEG就能對Fortran、Modula等專用語言進行分析編譯,而Archelon編譯器則針對DSP芯片為執(zhí)行代碼生成做了專門的優(yōu)化。ELI是這一類編譯資源的典型代表,它除了支持上述流行編程語言及專用語言如c、Fortran外,甚至支持對用戶定義的語言生成獨有的編譯器,從而幫助用戶快速地實現一種專業(yè)程序語言。
2.2從知識點的角度分析
為利于編譯原理課程的教學,我們更希望從知識點的角度梳理相關資源,在講授相關課程時,可以介紹這些經典的編譯工具。通過認識真實編譯系統(tǒng)的工作流程和開發(fā)技術,幫助學生理解關鍵知識點。我們從詞法分析、語法分析、編譯前端、編譯后端、程序分析及優(yōu)化、完整的編譯器平臺等類別對現有的編譯資源進行了梳理和分類。
1)詞法分析。
詞法分析器以UNIX/LINUX上的LEX為典型代表,能夠生成c語言描述的詞法分析器;而AFLEX作為LEX的變種,能生成ADA語言描述的詞法分析器;Quex還能生成C/C++、Python語言描述的詞法分析器;相關的資源還包括LOLO、FLEX等。
2)語法分析。
支持語法分析的編譯工具最為豐富,從簡單到復雜的相關開發(fā)案例也最多,可以很好地用于支撐課程教學。如前文所述,語法分析器以YACC為典型代表,這一系列的語法分析器還包括AYACC、BISON、BYACC、BEG。CUP、Jell等Java語言開發(fā)的語法分析器生成器,可以生成Java語言描述的語法分析器。ANTLR是一種用Java開發(fā)的強大的語法分析器生成工具,可以生成各種語言描述的語法分析器,包括Ada、C、C#、Java、JavaScript、Objective-C等,以及Perl、Python和Ruby等較新的互聯網程序語言和腳本語言,甚至包括SQL、一階邏輯、XPath等應用語言等。ACCENT則是一個包含了詞法分析器和語法分析器的生成工具。JavaCC是當前應用非常廣的一種語法分析器生成工具,能產生Java語言描述的LL(K)分析程序。值得一提的是,目前已經有非常多的利用JavaCC開發(fā)的各種語言的分析程序,包括了表達式等簡單語言,如DTD、IDL、RTF等應用語言,以及PHP等實用的腳本語言。隨著技術的發(fā)展,甚至出現了OOPS等面向對象的分析器生成工具。
3)編譯前端。
面向c語言的中間代碼生成工具最著名的是Ckit,它支持將c語言程序翻譯譯成SML類型的中間語言,也支持用戶擴展C語言語法的前端編譯。EDG則能將C++和Java等語言翻譯成一種高級的樹結構中間語言,并具有錯誤檢查功能。在面向Java語言方面,比較知名的編譯器前端包括Jfront等。此外,為滿足特定應用場景需求,還出現了IDC-C、SUIF等編譯前端及中間代碼優(yōu)化工具。
4)編譯后端。
編譯器后端方面的資源相對前端來說較少,比較知名的編譯器后端是BEG,以BEGL中間語言為輸入,可用于生成Motorola 68020、SPARC、MIPSl Intel 386、Pentium?Inmos T800和PowerPC等平臺的目標代碼。在Java語言方面,Sable研究小組基于XML提出了JIL中間表示語言,利用XML的特性為執(zhí)行代碼的生成和優(yōu)化提供便利。此外,還有Trimam等針對并行環(huán)境生成執(zhí)行代碼并優(yōu)化的后端編譯器生成器等工具。
5)程序分析及代碼優(yōu)化。
在程序分析及代碼優(yōu)化方面的編譯工具較多,如BANSHEE、CodeSurfer、Omega、OOPS、PAG、SOOT等。其中BANSHEE、CodeSurfer、Kimwitu、MEMPHIS、PAG等工具針對C/C++程序進行分析,Omega、PAT等工具則可以對Fortran、Java程序進行分析,SOOT、OOPS提供了對Java等語言編譯器的優(yōu)化,上文中提到的Trimam及SUIF等則針對并行環(huán)境進行了代碼優(yōu)化。
6)編譯器平臺。
除上述實現了部分編譯模塊的開發(fā)工具之外,還存在著大量實現了從詞法分析、語法分析直至最后目標代碼生成所有環(huán)節(jié)的編譯器平臺資源,這些資源用于案例教學可以幫助學生對編譯的全過程進行一個整體的理解和把握。這些平臺可以分為兩類:一類是以精簡語言為源語言的小型編譯器,如PL語言(PASCAL子集)編譯器、與ADA和PASCAL類似的TINY編譯器,以及斯坦福大學開發(fā)的COOL(The Classroom ObiectOriented Language)編譯器,這些編譯器都是面向專門為教學設計的某種精簡的編程語言,將其翻譯成某種抽象機代碼,借助抽象機解釋器執(zhí)行;另一類是以GCC、LCC為代表的產品級開源編譯器,面向C/C++這類主流的編程語言,提供開源、實用的編譯程序。
3.編譯資源在課程教學中的應用
通過上面的分析,我們看到編譯開發(fā)工具和相關案例是非常豐富的,但是如何將這些工具和案例很好地結合到教學中,則需要做仔細的選擇和考慮。不論從課程教學,還是實踐教學來看,編譯原理課程的學習可以從局部知識點和系統(tǒng)整體兩個層次開展。課程教學需要在掌握編譯各階段的具體知識點的基礎上,加強各知識點之間的融會貫通,并恰當及時地從局部向系統(tǒng)整體引申。
在詞法分析、語法分析、語義分析、優(yōu)化、目標代碼生成等知識點的學習過程中,可以引人相應模塊的開發(fā)工具作為案例。如在講解詞法分析時可以結合LEX、在講解自上而下分析時結合JavaCC、講解自下而上分析時結合BISON,甚至可以在課堂教學時展示這些工具的核心代碼,加深學生對相關算法的印象。也可以在課外安排實踐作業(yè),要求學生選擇這些工具提供的案例資源,以已有的案例為基礎(為調動學習興趣,可以有意識地選擇學生在其他課程中已經熟悉的語言,如數據庫中的SQL、操作系統(tǒng)中的Shell命令語言、離散數學中的謂詞邏輯等),實際生成一個編譯模塊,閱讀分析生成程序,在此基礎上,可要求學生擴展原有案例。通過結合這些工具講解理論知識,并通過實踐作業(yè),使得學生能夠理解局部知識點,并掌握相關成熟的工具的使用。
在系統(tǒng)開發(fā)層面,編譯程序的開發(fā)是一個典型復雜的軟件開發(fā)任務。如果能在理解局部知識點的基礎上,為學生提供一個理解編譯程序整體全貌的平臺,以編譯過程為指導帶動課程知識點的學習,也是非常有益的。如何在編譯程序的功能實用性和教學可用性兩方面保持平衡,一直是編譯教學的難題。開展綜合性實驗,是提高學生對編譯程序整體理解和開發(fā)能力的主要途徑。在這方面,有兩種思路。一種是側重整體體驗,主要是面向一個為教學而專門設計的精簡語言,如前文介紹的PL、TINY和COOL等,這些語言通常包含現代程序設計語言典型成分,但更為精簡,學生可以通過課程學習,最后為該語言實現一個完整的編譯器。按照這種方案開展綜合性實驗,有利于學生體驗一個完整的編譯程序開發(fā)過程。第二種思路側重實用性和真實性,主要以GCC、LCC這類實用的,甚至是產品級的開源編譯器為平臺開展實踐。由于GCC、LCC這類實用編譯程序代碼量非常大,如何引導學生在紛繁復雜的代碼中理清頭緒、找到和教學知識點相關的程序段,需要教師做好充分的準備。這種思路,對于將來從事編譯程序開發(fā)的學生,其收獲可能更大。
4.結語
理論和實踐的完美結合是編譯程序研制的突出特點,也是編譯課程教學力圖為學生展示的特色。為了使學生切實體驗編譯經典理論在編譯程序研制以及其他領域發(fā)揮重要作用,我們收集了一批編譯開發(fā)工具,并對這些資源從公開程度、開發(fā)語言、生成語言、系統(tǒng)平臺、涉及課程知識點、應用領域和是否提供案例等方面進行分析和標注。到目前為止,已收集60余項軟件工具資源,并在課程網站上發(fā)布。下一步,我們將繼續(xù)擴大收集編譯資源的規(guī)模,并進一步提高分析和標注的準確性,積極探索如何結合這些資源開展課堂教學和實踐教學改革,利用這些資源向學生展示編譯研究中“經典理論和先進技術有機結合”的突出特點,并使學生切實體驗編譯經典理論在各領域的重要作用,培養(yǎng)學生的計算思維,提高課程教學的效果。