1.講解解譯器模式1.1解譯器模式定義
給定一個語言,定義它的文法的一種表示,並定義一個解譯器,這個解譯器使用該表示來解釋語言中的句子。
1.2解譯器模式要點
解析器:把描述用戶端調用要求的運算式,經過解析,形成一個抽象文法樹的程式。
解譯器:解釋文法抽象樹
一般一個解譯器處理一個文法規則
1.3解譯器模式的結構圖以及說明
抽象解譯器:聲明一個所有具體運算式都要實現的抽象介面(或者抽象類別),介面中主要是一個interpret()方法,稱為解釋操作。具體解釋任務由它的各個實作類別來完成,具體的解譯器分別由終結符解譯器TerminalExpression和非終結符解譯器NonterminalExpression完成。
終結符運算式:實現與文法中的元素相關聯的解釋操作,通常一個解譯器模式中只有一個終結符運算式,但有多個執行個體,對應不同的終結符。終結符一半是文法中的運算單元,比如有一個簡單的公式R=R1+R2,在裡面R1和R2就是終結符,對應的解析R1和R2的解譯器就是終結符運算式。
非終結符運算式:文法中的每條規則對應於一個非終結符運算式,非終結符運算式一般是文法中的運算子或者其他關鍵字,比如公式R=R1+R2中,+就是非終結符,解析+的解譯器就是一個非終結符運算式。非終結符運算式根據邏輯的複雜程度而增加,原則上每個文法規則都對應一個非終結符運算式。
環境角色:這個角色的任務一般是用來存放文法中各個終結符所對應的具體值,比如R=R1+R2,我們給R1賦值100,給R2賦值200。這些資訊需要存放到環境角色中,很多情況下我們使用Map來充當環境角色就足夠了
1.4解譯器模式的範例程式碼
package demo20.interpreter.example2;/** * 抽象運算式 */public abstract class AbstractExpression {/** * 解釋的操作 * @param ctx 內容物件 */public abstract void interpret(Context ctx);}***************************************************************************************************package demo20.interpreter.example2;/** * 終結符運算式 */public class TerminalExpression extends AbstractExpression{public void interpret(Context ctx) {//實現與文法規則中的終結符相關聯的解釋操作}}*************************************************************************************************package demo20.interpreter.example2;/** * 非終結符運算式 */public class NonterminalExpression extends AbstractExpression {public void interpret(Context ctx) {// 實現與文法規則中的非終結符相關聯的解釋操作}}*************************************************************************************************package demo20.interpreter.example2;/** * 上下文,包換解譯器之外的一些全域資訊 */public class Context {}*************************************************************************************************package demo20.interpreter.example2;/** * 使用解譯器的客戶 */public class Client {//主要按照文法規則對特定的句子構建抽象文法樹//然後調用解釋操作}1.5解譯器模式的本質
分離實現,解釋執行
1.6解譯器模式的優缺點
優點:易於實現演算法,易於擴充新的文法
缺點:不適合複雜的文法,解譯器模式會引起類的膨脹,每個文法都需要產生一個非終結符運算式,文法規則比較複雜時,就可能產生大量的類檔案,為維護帶來非常多的麻煩
1.7何時選用
當有一個語言需要解釋執行,並且可以將該語言中的句子表示為一個抽象的文法樹的時候
文法相對比較簡單
效率要求不高
1.8附註
由於解譯器應用的情況比較少,所以這裡就不舉例子了。