天天看點

《ANTLR 4權威指南 》一3.4 建構一個語言類應用程式

本節書摘來自華章出版社《antlr 4權威指南 》一書中的第3章,第3.4節,[美] 特恩斯·帕爾(terence parr) 著張 博 譯,更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

我們繼續完成能夠處理數組初始化語句的示例程式,下一個目标是能夠翻譯初始化語句,而不僅僅是能夠識别它們。例如,我們想要将java中,類似{ 99, 3, 451 }的short數組翻譯成"u0063u0003u01c3"。注意,其中十進制數字99的十六進制表示是63。

為了完成這項工作,程式必須能夠從文法分析樹中提取資料。最簡單的方案是使用antlr内置的文法分析樹周遊器進行深度優先周遊,然後在它觸發的一系列回調函數中進行适當的操作。正如我們之前看到的那樣,antlr能夠自動生成一個監聽器接口和一個預設的實作類。這樣的監聽器非常類似于圖形界面程式控件上的回調函數(例如,當一個按鈕被按下時,它會通知我們)或者xml解析器中的sax事件。

我們如果想要通過編寫程式來操縱輸入的資料的話,隻需要繼承arrayinitbaselistener類,然後覆寫其中必要的方法即可。我們的基本思想是,在周遊器進行文法分析樹的周遊時,令每個監聽器方法翻譯輸入資料的一部分并将結果列印出來。

監聽器機制的優雅之處在于,我們不需要自己編寫任何周遊文法分析樹的代碼。事實上,我們甚至都不知道antlr運作庫是怎麼周遊文法分析樹、怎麼調用我們的方法的。我們隻知道,在文法規則對應的語句的開始和結束位置處,我們的監聽器方法可以得到通知。在7.2節我們會看到,這種機制使得我們不需要了解太多antlr的知識——我們回到了自己熟悉的領域,即寫普通的代碼而不是處理語言識别問題。

一個進行翻譯工作的項目意味着要處理這樣的問題:如何将輸入的詞法符号或者詞組翻譯成輸出字元串。為了達到這個目标,最好先從手工翻譯一些有代表性的樣例入手,想辦法提取出通用的轉換邏輯。在下例中,轉換過程是非常直截了當的。

《ANTLR 4權威指南 》一3.4 建構一個語言類應用程式

用自然語言解釋,翻譯過程就是一系列“x映射為y”的過程:

1)将{翻譯為"。

2)将}翻譯為"。

3)将每個整數翻譯為四位的十六進制形式,然後加字首u。

為此,我們需要編寫方法,在遇到對應的輸入詞法符号或者詞組的時候,列印出轉換後的字元串。内置的文法分析樹周遊器會在各種詞組的開始和結束位置觸發監聽器的回調函數。下面是遵循我們的翻譯規則的一個監聽器的實作類。

《ANTLR 4權威指南 》一3.4 建構一個語言類應用程式

我們不需要覆寫每個enter/exit方法,我們隻需要覆寫自己需要的那些。上述代碼中唯一令我們不那麼熟悉的一個表達式是ctx.int(),它從上下文對象中擷取int詞法符号對應的整數值,該詞法符号由比對value規則得來。現在,剩下的事情就是把之前的test類擴充成一個翻譯程式了。

《ANTLR 4權威指南 》一3.4 建構一個語言類應用程式
《ANTLR 4權威指南 》一3.4 建構一個語言類應用程式

這份代碼和之前代碼的唯一差別在于高亮辨別的部分,它建立了一個文法分析樹周遊器,令其對文法分析器生成的文法分析樹進行周遊。在周遊器的周遊過程中,它觸發了我們的shorttounicodestring監聽器的回調函數。請注意:限于篇幅,為了使讀者的注意力更加集中,在本書剩下的章節中,通常僅給出代碼的關鍵部分而非完整代碼。此外,你還可以從本書的網站上擷取完整的代碼壓縮包。

最後,讓我們一起完成這個翻譯器,并使用樣例輸入來測試。

《ANTLR 4權威指南 》一3.4 建構一個語言類應用程式

一切順利。無須深入了解文法的細節,我們就完成了我們的第一個翻譯器。我們所做的一切不過是實作了幾個方法,在這些方法中列印出對輸入文本的适當的翻譯結果。另外,我們可以通過給周遊器傳遞一個不同的監聽器以實作完全不同的輸出。監聽器有效地将語言類應用程式和文法進行了解耦,進而使得同一個文法能夠被不同的程式複用。

下一章,我們将快速學習antlr文法的編寫方法,以及讓antlr文法如此強大和易用的關鍵特性。

繼續閱讀