侯書東,常家琦,劉 恒
(安徽工業大學 計算機科學與技術學院,安徽 馬鞍山 243002)
編譯原理作為計算機類專業的傳統核心課程,對學生專業系統能力的培養具有重要意義。編譯原理課程的重要性在于:編譯器的開發是計算機軟件開發的一個綜合;解決問題的思想方法有利于計算思維的培養,對于計算機專業素養形成十分必要[1]。
計算機類專業本科生學習本專業的第一門語言課程是C語言。C語言由于其類型不安全性,容易出現一些難以捉摸的錯誤,使得學生難以定位和解決問題。如果能讓學生根據編譯器提供的提示信息,精確定位程序中的錯誤類型和位置,把編譯原理中所學用于實際C語言編程需求,這既完成了課程的教學內容,也提升了學生的軟件編程和系統分析的能力。
從普通高等院校的編譯原理教學實際出發,其課程覆蓋范圍一般僅限于編譯器的前端,即詞法分析、語法分析和語法制導翻譯等內容[2]。這其中包括大量抽象且邏輯復雜的理論知識點,如形式語言理論、正規式、有限自動機、上下文無關文法、屬性文法和語法制導翻譯等。傳統的教學方式強調知識點的灌輸,讓學生解決孤立的單一問題,缺乏各知識點之間的關聯。這種“只見樹木,不見森林”的教學方式會極大地削弱學生的學習積極性,導致整體效果不佳。
理論教學的重要性不言而喻,然而面對當前社會“碎片化學習”,要確保授課效果的高質量,需要對課堂內容的選擇和教學方式的安排進行精心設計。尤為重要的是激發學生的學習熱情,實現從被動接受到主動學習過程的角色轉換。
理論知識的來源一般都有其確定的問題背景。脫離實際問題來進行理論教學,對學生實際能力的提升沒有益處。編譯原理課程中的大量理論知識,存在一種銜接遞進的關系,每個知識點的引入和拓展,都是對于現實遇到問題的解決路徑再現。因此,整個授課過程就在重現這種解決方案演變的變化歷程。而實現這一目標的關鍵之處,是教師從之前的“站到講臺前”變到現在的“坐在學生中”。這一變化絕不僅僅是簡單地將所有問題留給學生,從“講授”變成“答疑”,而是從問題設計、思考啟迪、討論引導到過程管理等各方面都對教師提高了要求。特別是現代高級語言發展日新月異,各種新問題層出不窮,如何在面對開放性的未知問題時,從系統和整體的角度給出學生解決問題的方式方法,而不是給出具體每個問題的回答[3],這是對教師能力的一種新考驗。
計算機類專業課程教學的目的,歸根結底是以培養和提升學生們現實動手能力為主題。“考試高分”僅是手段,“實踐高手”才是目的。通過精心設計的問題場景,激發學生的學習興趣,逐步引導討論內容,得到初步解決方案,再層層優化,最后比較與經典方法的優劣之處。這樣的理論與實踐交叉的教學方式,可以讓學生從根源上理解并掌握理論技術的來龍去脈,避免繁雜的死記硬背以及理論與實踐脫節,在實踐中學習和總結規律。
在編譯原理課程教學里,以詞法分析為例闡述如何從正規式構造等價自動機的內容必不可少。在先修的高級語言課程中,學生只需知道如何運用正規式。而在本課程學習中,則需進一步掌握正規式的實現原理。正規式的實現方式主要有非確定有限自動機(NFA)和確定有限自動機(DFA)兩種引擎方式。在教學過程中,常規流程都是給定正規式,構造其NFA,在此基礎上轉化為DFA,最后進行最簡化處理。這在無形中向學生暗示了DFA才是詞法分析實現的最終手段,其實不然,兩種引擎方式各有其優缺點和應用場景。DFA是文本主導,執行速度快,可以確保匹配最長的可能字符串,滿足結果一致性。NFA是表達式主導,需要反復的吃、吐字符,存在著大量的回溯過程,速度慢。但是其特性豐富,可以捕獲子表達式匹配和匹配的反向引用。子表達式編寫方式不同,對于DFA是無差異的,但是對NFA的控制方式是不同的。如果能從編碼實現的角度考慮這兩種方式的異同,啟迪學生的獨立思考能力,其教學效果要明顯優于枯燥的理論知識傳授。
以編譯原理課程教學中語法分析中的算符優先分析為例,在討論終結符之間的優先關系時,與傳統認知是有一定區別的。此處有必要回顧“離散數學”中對于“關系”的定義。回顧恒等關系的定義,需要同時滿足自反性、對稱性和傳遞性。顯然,算符之間的優先關系是可以不滿足這三種性質的。以四則運算為例,存在+>+,即加號的優先級是大于加號的,不滿足自反性。同時,由于(=),而不存在)=(,所以不滿足對稱性。另外,同時存在+<(、(<+和+>+同時成立,不符合傳遞性的性質。這中間的區別就在于不僅需要考慮待比較的兩個算符,算符出現的先后順序也至關重要。至此,算符之間的優先級,與自然數的大小比較、或者與線程調度中的優先級等概念中的區別之處自然顯現。這也引出了后續算符優先函數的方便與不足之處。這種先后課程之間知識點的貫通,既加深了對已有知識的理解,同時也更新了知識圖譜。
編譯原理課程教學理想情況,學生應該能夠獨立自主完成小型編譯系統的構造。實際教學中,學生只需吃透關鍵的幾條原理知識,如NFA的確定化,LL(1)文法中FIRST和FOLLOW集合的構造,LR(1)文法中識別活前綴DFA構造等,基本上已經滿足了課程考試要求。然而,僅靠理論學習對實現一個基礎編譯器來說是遠遠不足的。相比較于學生對理論知識的接受程度,學生自主動手完成編譯系統的能力缺乏就更為明顯。如何面對全體學生,制定出一套適用的實踐方案,是課程實際效用的關鍵。
對于編譯原理課程復雜實現機理可以在后續過程中逐步展開,串聯起數據結構、操作系統、組成原理等一系列關聯課程,讓其學而有物。對于學有余力的學生,可以提高要求,讓其完成類C編譯器。對于確實難以獨立完成的,最基本的要求是可以復現課程演示的四則運算。要求不同,體現在設計語言的復雜度不同。囿于師資力量薄弱,對于編譯器的設計要求以前端為主,關于目標代碼生成了解即可,不做具體要求。
以布爾表達式的翻譯模式為例,通過語法制導翻譯內容的學習,對于條件表達式中的短路規則的設計初衷已了然于胸。然而如何最小化跳轉語句的出現,掌握回填技術的使用,乃至初涉獨立于機器的優化過程,對于編譯器實現質量的優劣影響至遠。僅僅明白基本原理的應用,缺乏對軟件實現細節的敏感度和執行效率的考量,很難滿足實用性的要求。特別是在面對“流量決定一切”的時代,用戶體驗對于產品品質的要求日益挑剔,任何細節之處的忽略都可能面臨致命的打擊。不求功能的復雜全面,但求體驗的流暢舒適,在系統設計實現的全過程中,將用戶需求作為第一位,對于端正學生的學習和工作態度,是一次很好的鍛煉機會。
通過精心設計的問題引導與自動化編譯工具,逐步展開編譯器設計的主要內容,教學既不失課程的專業性要求又吸引了學生的興趣點,能有效提升學生的綜合實踐能力。在后續教學改革中,借助慕課、反轉等多樣教學形式,增加課堂討論、啟發、互動的過程,最大限度地激發學生的學習熱情,仍需不斷地探索和嘗試。