摘要:針對編譯原理教學實際,在分析和修改工業級開源編譯器實現代碼的基礎上,提出一個基于Java的編譯原理課程案例教學過程,結合Java這種日益普及的面向對象程序設計語言,這種教學過程在編譯原理課程教學方面取得良好效果。
關鍵詞:Java字節碼;Java類文件;Javac;Java編譯器;編譯原理
編譯原理是計算機與軟件專業的核心基礎課程,是關聯匯編語言程序設計、高級語言程序設計等相關課程的紐帶。如何深入進行編譯原理課程教學改革,更好地幫助學生理解和掌握編譯器的設計原理與基本實現方法,更好地在教學過程中體現計算機軟件核心思想,更好地依托一個載體緊密結合工程實踐與理論研究,是新時期編譯原理課程教學面臨的挑戰。
1案例教學在編譯原理中的作用
1.1編譯原理課程的內容組織
編譯原理在軟件學科中占據核心位置,起著重要作用。編譯原理包括詞法分析、語法分析、語義分析和中間代碼生成、代碼優化、運行時存儲組織等[1]。除了上述基本知識點外,了解編譯原理在現實世界中的廣泛應用,知道編譯器在計算機與軟件專業課程體系中的關鍵地位,是激發學生認真學習和掌握本門課程基礎知識及專業工具的有效手段。
1.2案例教學的作用
為了更有效地組織編譯原理課程的教學工作,避免傳統式教育存在的“重基礎、輕實踐”的弊端[2],針對新時期研究型大學本科生的特點,我們提出了如下基于主流編譯器的編譯原理課程案例教學方法:先讓學生對編譯原理課程的教學載體,即一個較為完整的編譯器,建立初步認識,再借助學生較強的自學能力和動手能力,在實踐中學習和體會程序設計語言編譯過程的基本原理,切實保證理論聯系實踐,尤其是強調“學中練、練中學;練中闖、練中創”[3]。首先讓學生了解一個典型編譯器的輸入和輸出,同時通過圖形化方式使得學生對編譯過程的主要階段建立感性認識;進而熟悉作為課程載體的一個編譯器原型,并對其進行改造;最終達到學習編譯原理基礎知識,并對規范化程序設計有所深入理解的目的。
2基于Java的編譯原理案例實驗設計
作為一個主流的面向對象程序設計語言,Java已經占據了近20%的份額[4],在計算機網絡等應用中起著越來越重要的作用,不僅覆蓋了從大型網絡應用系統開發到SIM卡芯片上的認證程序等大量應用,而且保持著強勁的發展勢頭。鑒于此,本課程考慮基于Java的編譯原理案例教學。
2.1實驗設計
基于Java的編譯原理實驗包括了解實驗目標和進行具體實驗操作兩階段。實驗目標包括源、目的和轉換過程三部分,分別涉及對源語言(Java程序設計語言)的理解,對目標語言(Java類文件,包括Java字節碼)的理解,和對編譯過程的理解。鑒于前導課程Java語言程序設計已充分介紹了Java源程序,本課程主要介紹后兩部分。
具體的實驗操作可以細分三個層面。一為使用現有詞法器/語法器的自動生成工具(如JLex、CUP)實現一個Java編譯器,二為依據編譯原理的基礎理論手工設計實現一個Java編譯器,三為構造詞法器/語法器等程序的自動生成工具,并基于這些工具實現Java編譯器。可根據具體教學情況側重某一層面。
2.2Java類文件的講授
Java類文件包含常量池、接口表、域表、方法表和屬性表等信息。Java字節碼是Java類文件的關鍵組成部分,字節碼序列出現在方法的Code屬性項中。為了讓學生了解Java源程序的編譯過程,并掌握Java類文件的結構,采用如下案例。首先給出一個簡單的Java源文件然后將上述文件編譯為Java類文件,并通過“javap –c Act”命令展示對應的字節碼序列,并向學生予以講解。接著,按十六進制打印輸出Act.class文件(如圖1所示),并在課堂上作為補充材料發給學生。
進一步地,我們通過一個Java Applet程序(如圖2所示)向學生逐步展示Java虛擬機是如何以流的方式單步裝載圖1中的Java類文件的[5]150,并在補充材料上予以標注學習。
2.3Java編譯過程的圖形化展示
在講解編譯過程時,充分考慮以圖形化方法展示關鍵步驟,使學生們能夠首先建立感性認識,進而研討具體的編譯算法并為此制作一些演示程序。例如,我們通過prefuse工具,制作了從源程序到詞法單元(token)流的映射過程。對于輸入的一段Java源程序,可以形象地以樹的方式展示其對應的token集合。如圖3所示,對應左側窗口的一個Java源程序,在右側窗口出現一個詞法單元序列。除了注釋符和空白符號外,源文件中的每個詞素都對應一個詞法單元,包括詞法單元名字和屬性值。
在語法分析過程中,也通過可視化的方式將一個語句塊及其對應的樹狀結構予以形象表達。如圖4所示,對應左側的一個語句塊,在右側以圖形化的方式表達出一個樹狀結構。
3基于Java的編譯原理案例教學實踐
為了更好地講授編譯器的設計與實現,以一個設計良好的工業級編譯器Javac為課程案例,展示編譯器的設計原理與實現方法。課堂上剖析的對象是OpenJDK中的Javac編譯器[6]。
3.1Javac的結構及特點
OpenJDK中的編譯器Javac包括137個java文件。其重要的類和包如表1所示。
Javac使用的是LL(1)遞歸下降分析方法,同時使用算符優先分析方法對二元運算表達式進行分析。Javac具有模塊清晰、代碼風格統一、注釋完善等優點,并且使用了大量典型的設計模式。
當然,Javac編譯器的源代碼也存在一些不足,例如沒有充分應用代碼優化技術。但是,考慮到本科編譯原理教學的重點一般是詞法分析和語法分析,使用Javac在現階段還是可行的。此外,學生可以通過其它方式來學習和掌握一定的代碼優化技術。
3.2Javac的教學實踐
在詞法分析階段,學生的任務是分析輸入的Java源程序并生成對應的token流。在語法分析階段,學生的任務是用CUP工具生成LALR(1)語法分析器,并將其集成入Javac。其關鍵步驟是在com.sun.tools. javac.parser.ParserFactory中重寫newParser方法,實現語法分析器的替換。具體如下所示:
public Parser newParser(CharSequencein