自定義語言的實現——解釋器模式(四) – JAVA編程語言程序開發技術文章

18.4 完整解決方案
      為瞭能夠解釋機器人控制指令,Sunny軟件公司開發人員使用解釋器模式來設計和實現機器人控制程序。針對五條文法規則,分別提供五個類來實現,其中終結符表達式direction、action和distance對應DirectionNode類、ActionNode類和DistanceNode類,非終結符表達式expression和composite對應SentenceNode類和AndNode類。
      我們可以通過抽象語法樹來表示具體解釋過程,例如機器人控制指令“downrun 10 and left move20”對應的抽象語法樹如圖18-4所示:

圖18-4   機器人控制程序抽象語法樹實例
      機器人控制程序實例基本結構如圖18-5所示:

圖18-5   機器人控制程序結構圖
      在圖18-5中,AbstractNode充當抽象表達式角色,DirectionNode、ActionNode和DistanceNode充當終結符表達式角色,AndNode和SentenceNode充當非終結符表達式角色。完整代碼如下所示:
[java] view plaincopy
//註:本實例對機器人控制指令的輸出結果進行模擬,將英文指令翻譯為中文指令,實際情況是調用不同的控制程序進行機器人的控制,包括對移動方向、方式和距離的控制等 
import java.util.*; 
 
//抽象表達式 
abstract class AbstractNode { 
    public abstract String interpret(); 

 
//And解釋:非終結符表達式 
class AndNode extends AbstractNode { 
    private AbstractNode left; //And的左表達式 
    private AbstractNode right; //And的右表達式 
 
    public AndNode(AbstractNode left, AbstractNode right) { 
        this.left = left; 
        this.right = right; 
    } 
     
    //And表達式解釋操作 
    public String interpret() { 
        return left.interpret() + "再" + right.interpret(); 
    } 

 
//簡單句子解釋:非終結符表達式 
class SentenceNode extends AbstractNode { 
    private AbstractNode direction; 
    private AbstractNode action; 
    private AbstractNode distance; 
 
    public SentenceNode(AbstractNode direction,AbstractNode action,AbstractNode distance) { 
        this.direction = direction; 
        this.action = action; 
        this.distance = distance; 
    } 
     
    //簡單句子的解釋操作 
    public String interpret() { 
        return direction.interpret() + action.interpret() + distance.interpret(); 
    }    

 
//方向解釋:終結符表達式 
class DirectionNode extends AbstractNode { 
    private String direction; 
     
    public DirectionNode(String direction) { 
        this.direction = direction; 
    } 
     
    //方向表達式的解釋操作 
    public String interpret() { 
        if (direction.equalsIgnoreCase("up")) { 
            return "向上"; 
        } 
        else if (direction.equalsIgnoreCase("down")) { 
            return "向下"; 
        } 
        else if (direction.equalsIgnoreCase("left")) { 
            return "向左"; 
        } 
        else if (direction.equalsIgnoreCase("right")) { 
            return "向右"; 
        } 
        else { 
            return "無效指令"; 
        } 
    } 

 
//動作解釋:終結符表達式 
class ActionNode extends AbstractNode { 
    private String action; 
     
    public ActionNode(String action) { 
        this.action = action; 
    } 
     
    //動作(移動方式)表達式的解釋操作 
    public String interpret() { 
        if (action.equalsIgnoreCase("move")) { 
            return "移動"; 
        } 
        else if (action.equalsIgnoreCase("run")) { 
            return "快速移動"; 
        } 
        else { 
            return "無效指令"; 
        } 
    } 

 
//距離解釋:終結符表達式 
class DistanceNode extends AbstractNode { 
    private String distance; 
     
    public DistanceNode(String distance) { 
        this.distance = distance; 
    } 
     
//距離表達式的解釋操作 
    public String interpret() { 
        return this.distance; 
    }    

 
//指令處理類:工具類 
class InstructionHandler { 
    private String instruction; 
    private AbstractNode node; 
     
    public void handle(String instruction) { 
        AbstractNode left = null, right = null; 
        AbstractNode direction = null, action = null, distance = null; 
        Stack stack = new Stack(); //聲明一個棧對象用於存儲抽象語法樹 
        String[] words = instruction.split(" "); //以空格分隔指令字符串 
        for (int i = 0; i < words.length; i++) { 
//本實例采用棧的方式來處理指令,如果遇到“and”,則將其後的三個單詞作為三個終結符表達式連成一個簡單句子SentenceNode作為“and”的右表達式,而將從棧頂彈出的表達式作為“and”的左表達式,最後將新的“and”表達式壓入棧中。                   if (words[i].equalsIgnoreCase("and")) { 
                left = (AbstractNode)stack.pop(); //彈出棧頂表達式作為左表達式 
                String word1= words[++i]; 
                direction = new DirectionNode(word1); 
                String word2 = words[++i]; 
                action = new ActionNode(word2); 
                String word3 = words[++i]; 
                distance = new DistanceNode(word3); 
                right = new SentenceNode(direction,action,distance); //右表達式 
                stack.push(new AndNode(left,right)); //將新表達式壓入棧中 
            } 
            //如果是從頭開始進行解釋,則將前三個單詞組成一個簡單句子SentenceNode並將該句子壓入棧中 
            else { 
                String word1 = words[i]; 
                direction = new DirectionNode(word1); 
                String word2 = words[++i]; 
                action = new ActionNode(word2); 
                String word3 = words[++i]; 
                distance = new DistanceNode(word3); 
                left = new SentenceNode(direction,action,distance); 
                stack.push(left); //將新表達式壓入棧中 
            } 
        } 
        this.node = (AbstractNode)stack.pop(); //將全部表達式從棧中彈出 
    } 
     
    public String output() { 
        String result = node.interpret(); //解釋表達式 
        return result; 
    } 

       工具類InstructionHandler用於對輸入指令進行處理,將輸入指令分割為字符串數組,將第1個、第2個和第3個單詞組合成一個句子,並存入棧中;如果發現有單詞“and”,則將“and”後的第1個、第2個和第3個單詞組合成一個新的句子作為“and”的右表達式,並從棧中取出原先所存句子作為左表達式,然後組合成一個And節點存入棧中。依此類推,直到整個指令解析結束。
       編寫如下客戶端測試代碼:
[java] 
class Client { 
    public static void main(String args[]) { 
        String instruction = "up move 5 and down run 10 and left move 5"; 
        InstructionHandler handler = new InstructionHandler(); 
        handler.handle(instruction); 
        String outString; 
        outString = handler.output(); 
        System.out.println(outString); 
    } 

       編譯並運行程序,輸出結果如下:
向上移動5再向下快速移動10再向左移動5

作者:劉偉

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。