<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    細(xì)心!用心!耐心!

    吾非文人,乃市井一俗人也,讀百卷書,跨江河千里,故申城一游; 一兩滴辛酸,三四年學(xué)業(yè),五六點(diǎn)粗墨,七八筆買賣,九十道人情。

    BlogJava 聯(lián)系 聚合 管理
      1 Posts :: 196 Stories :: 10 Comments :: 0 Trackbacks
    對於一個具有層次節(jié)點(diǎn)關(guān)係的問題來說,如果您要剖析每一個節(jié)點(diǎn),您可以使用Interpreter模式,直譯器模式有些類似演算法中的個別擊破方式,對每一個父節(jié)點(diǎn)我們剖析出其子節(jié)點(diǎn)組合,然而交給子節(jié)點(diǎn)剖析物件繼續(xù)剖析,直到剖析至終端節(jié)點(diǎn)為止。

    舉個例子來說明好了,先說明的是,這個例子是改寫自 Design Patterns於Java語言之實(shí)習(xí)應(yīng)用 第23章的範(fàn)例,我將之更簡化了,以讓大家將焦點(diǎn)能集中在如何使用Interpreter模式,以及如何實(shí)用。

    假設(shè)您要實(shí)作一個Interpreter,這個Interpreter可以直譯您文字檔中的程式,並依您自訂的程式文法來執(zhí)行程式,幾個簡單的程式如下:
    PROGRAM
        PRINT dog SPACE
        PRINT is SPACE
        PRINT an SPACE
        PRINT animai
    END
     
    您的這式程個會印出"dog is an animal"的文字,再來一個例子是:
    PROGRAM
        REPEAT 2
            LINEBREAK
            PRINT dog
            BREAK
        END
    END
     

    這個程式要印出:
    ------------------------------
     dog
    ------------------------------
     dog

    您也可以任意的組合程式,例如:
    PROGRAM
        PRINT begin
        BREAK
        REPEAT 3
            REPEAT 2
                PRINT dog SPACE
                PRINT is SPACE
                PRINT a SPACE
                PRINT animal
                BREAK
            END
        END
    END
     

    這個程式中的幾個關(guān)鍵字是PROGRAM、PRINT、SPACE、BREAK、LINEBREAK、REPEAT、END, PROGRAM是表示程式開始,以END作結(jié),PRINT可以印出一個無空白的字串,SPACE印出一個空白,BREAK是換行,而LINEBREAK是畫一個直線並換行,REPEAT是迴圈指令,可以指定迴圈次數(shù),以END作結(jié)。

    觀察程式,可以制定出以下的文法,如下:
    <program> ::= PROGRAM <command list>
    <command list> ::= <command>* END
    <command> ::= <repeat command> | <primitive command>
    <repeat command> ::= REPEAT <number> <command list>
    <primitive command> ::= PRINT <string>
                             | BREAK | SPACE | LINEBREAK
     

    程式文法制定需要對程式進(jìn)行語句分析與定義,在這邊並不討論這個課題,在程式中,command節(jié)點(diǎn)由primitive或repeat兩個節(jié)點(diǎn)任意組合,一個command list節(jié)點(diǎn)則是零個以上的command節(jié)點(diǎn)組合而成,其中repeat還可以組合command list節(jié)點(diǎn),這是組合模式的應(yīng)用,可以在程式中組合巢狀迴圈。

    在直譯程式時,以讀到PROGRAM作為開始節(jié)點(diǎn),接下來我們剖析程式為command list 節(jié)點(diǎn),並將它們丟給專門剖析command list的物件繼續(xù)剖析,這個物件將之分析,看是不是有repeat command或primitive command節(jié)點(diǎn),如果有就再往下交由專屬物件進(jìn)行剖析,如此層層剝開,並由專屬物件負(fù)責(zé)剖析工作。

    Interpreter模式的基本觀念就如上所示,先來看看如何以程式實(shí)現(xiàn)剖析的過程,下面這個程式會剖析您的程式,並將程式加上對應(yīng)的括號來將同一個區(qū)塊組合起來,以表示它完成剖析之後的結(jié)果:
    • INode.java
    public interface INode { 
    public void parse(Context context);
    }

    • ProgramNode.java
    // <program> ::= PROGRAM <command list> 
    public class ProgramNode implements INode {
    private INode commandListNode;
    public void parse(Context context) {
    context.skipToken("PROGRAM");
    commandListNode = new CommandListNode();
    commandListNode.parse(context);
    }

    public String toString() {
    return "[PROGRAM " + commandListNode + "]";
    }
    }

    • CommandListNode.java
    import java.util.Vector; 

    // <command list> ::= <command>* END
    public class CommandListNode implements INode {
    private Vector list = new Vector();

    public void parse(Context context) {
    while (true) {
    if (context.currentToken() == null) {
    System.err.println("Missing 'END'");
    break;
    } else if (
    context.currentToken().equals("END")) {
    context.skipToken("END");
    break;
    } else {
    INode commandNode = new CommandNode();
    commandNode.parse(context);
    list.add(commandNode);
    }
    }
    }

    public String toString() {
    return "" + list;
    }
    }

    • CommandNode.java
    // <command> ::= <repeat command> | <primitive command> 
    public class CommandNode implements INode {
    private INode node;

    public void parse(Context context) {
    if (context.currentToken().equals("REPEAT")) {
    node = new RepeatCommandNode();
    node.parse(context);
    } else {
    node = new PrimitiveCommandNode();
    node.parse(context);
    }
    }

    public String toString() {
    return node.toString();
    }
    }

    • RepeatCommandNode.java
    public class RepeatCommandNode implements INode { 
    private int number;
    private INode commandListNode;

    public void parse(Context context) {
    context.skipToken("REPEAT");
    number = context.currentNumber();
    context.nextToken();
    commandListNode = new CommandListNode();
    commandListNode.parse(context);
    }

    public String toString() {
    return "[REPEAT " + number + " "
    + commandListNode + "]";
    }
    }

    • PrimitiveCommandNode.java
    // <primitive command> ::= PRINT <string> 
    // | SPACE | BREAK | LINEBREAK
    public class PrimitiveCommandNode implements INode {
    private String name;
    private String text;

    public void parse(Context context) {
    name = context.currentToken();
    context.skipToken(name);
    if (!name.equals("PRINT") && !name.equals("BREAK")
    && !name.equals("LINEBREAK")
    && !name.equals("SPACE")) {
    System.err.println("Undefined Command");
    }

    if (name.equals("PRINT")) {
    text = context.currentToken();
    name += text;
    context.nextToken();
    }
    }

    public String toString() {
    return name;
    }
    }

    • Context.java
    import java.util.*; 

    public class Context {
    private StringTokenizer tokenizer;
    private String currentToken;

    public Context(String text) {
    tokenizer = new StringTokenizer(text);
    nextToken();
    }

    public String nextToken() {
    if (tokenizer.hasMoreTokens()) {
    currentToken = tokenizer.nextToken();
    } else {
    currentToken = null;
    }
    return currentToken;
    }

    public String currentToken() {
    return currentToken;
    }

    public void skipToken(String token) {
    if (!token.equals(currentToken)) {
    System.err.println("Warning: " + token +
    " is expected, but " +
    currentToken + " is found.");
    }
    nextToken();
    }

    public int currentNumber() {
    int number = 0;
    try {
    number = Integer.parseInt(currentToken);
    } catch (NumberFormatException e) {
    System.err.println("Warning: " + e);
    }
    return number;
    }
    }

    • Main.java
    import java.util.*; 
    import java.io.*;

    public class Main {
    public static void main(String[] args) {
    try {
    BufferedReader reader = new
    BufferedReader(new FileReader(args[0]));
    String text;
    while ((text = reader.readLine()) != null) {
    System.out.println("text = \"" +
    text + "\"");
    INode node = new ProgramNode();
    node.parse(new Context(text));
    System.out.println("node = " + node);
    }
    }
    catch (ArrayIndexOutOfBoundsException e) {
    System.err.println(
    "Usage: java Main yourprogram.txt");
    }
    catch (Exception e) {
    e.printStackTrace();
    }
    }
    }

    假設(shè)您的程式是這樣寫的:
    • program.txt
    PROGRAM PRINT xxx END
    PROGRAM REPEAT 4 PRINT xxx END END
    PROGRAM REPEAT 4 PRINT xxx PRINT "yyy" END END

    則執(zhí)行Intrepreter程式之後會是:
     $ java Main program.txt
     text = "PROGRAM PRINT xxx END"
     node = [PROGRAM [PRINTxxx]]

     text = "PROGRAM REPEAT 4 PRINT xxx END END"
     node = [PROGRAM [[REPEAT 4 [PRINTxxx]]]]

     text = "PROGRAM REPEAT 4 PRINT xxx PRINT "yyy" END END"
     node = [PROGRAM [[REPEAT 4 [PRINTxxx, PRINT"yyy"]]]]

    這個範(fàn)例程式基本上已經(jīng)顯示了直譯器模式的工作原理,如何讓程式直譯之後能夠工作,這待會再示範(fàn),先來看一下Intrepreter模式的 UML 類別結(jié)構(gòu)圖:
    Intrepreter

    TerminalExpression就像我們的primitive command,再剖析下去已經(jīng)沒有子節(jié)點(diǎn)了,而NonterminalExpression就像是repeat command,注意到其中也使用了組合模式,就如之前所說的,組合模式讓可以遞迴的組合句子為更複雜的語句。

    您已經(jīng)會剖析句子了,接下來要如何讓這個直譯器真正工作,雖然程式中使用toString()來表示每一個節(jié)點(diǎn)的剖析結(jié)果,但事實(shí)上,這個程式也已經(jīng)說明了如何讓剖析的結(jié)果真正運(yùn)作了,既然已經(jīng)記錄好剖析之後的語句順序了,只要由上而下追蹤剖析結(jié)果,就一定可以執(zhí)行到 primitive command,且順序符合自訂的程式原始碼的需求,這只要將toString()改為execute(),並作一些轉(zhuǎn)發(fā)與重複執(zhí)行的修改就可以了,直接來看程式會比較容易理解:
    • INode.java
    public interface INode {
    public void parse(Context context);
    public void execute();
    }

    • ProgramNode.java
    // <program> ::= PROGRAM <command list>
    public class ProgramNode implements INode {
    private INode commandListNode;

    public void parse(Context context) {
    context.skipToken("PROGRAM");
    commandListNode = new CommandListNode();
    commandListNode.parse(context);
    }

    public void execute() {
    commandListNode.execute();
    }

    public String toString() {
    return "[PROGRAM " + commandListNode + "]";
    }
    }

    • CommandListNode.java
    import java.util.*;    

    // <command list> ::= <command>* END
    public class CommandListNode implements INode {
    private Vector list = new Vector();
    private INode commandNode;

    public void parse(Context context) {
    while (true) {
    if (context.currentToken() == null) {
    System.err.println("Missing 'END'");
    break;
    } else if(context.currentToken().equals("END")) {
    context.skipToken("END");
    break;
    } else {
    commandNode = new CommandNode();
    commandNode.parse(context);
    list.add(commandNode);
    }
    }
    }

    public void execute() {
    Iterator it = list.iterator();
    while (it.hasNext()) {
    ((CommandNode)it.next()).execute();
    }
    }

    public String toString() {
    return "" + list;
    }
    }

    • CommandNode.java
    // <command> ::= <repeat command> | <primitive command>
    public class CommandNode implements INode {
    private INode node;

    public void parse(Context context) {
    if (context.currentToken().equals("REPEAT")) {
    node = new RepeatCommandNode();
    node.parse(context);
    } else {
    node = new PrimitiveCommandNode();
    node.parse(context);
    }
    }

    public void execute() {
    node.execute();
    }

    public String toString() {
    return node.toString();
    }
    }

    • PrimitiveCommandNode.java
    // <primitive command> ::= PRINT <string> 
    // | SPACE | BREAK | LINEBREAK
    public class PrimitiveCommandNode implements INode {
    private String name;
    private String text;

    public void parse(Context context) {
    name = context.currentToken();
    context.skipToken(name);
    if (!name.equals("PRINT") && !name.equals("BREAK")
    && !name.equals("LINEBREAK")
    && !name.equals("SPACE")) {
    System.err.println("Undefined Command");
    }

    if (name.equals("PRINT")) {
    text = context.currentToken();
    context.nextToken();
    }
    }

    public void execute() {
    if(name.equals("PRINT"))
    System.out.print(text);
    else if(name.equals("SPACE"))
    System.out.print(" ");
    else if(name.equals("BREAK"))
    System.out.println();
    else if(name.equals("LINEBREAK"))
    System.out.println(
    "\n------------------------------");
    }

    public String toString() {
    return name;
    }
    }

    • RepeatCommandNode.java
    public class RepeatCommandNode implements INode {
    private int number;
    private INode commandListNode;

    public void parse(Context context) {
    context.skipToken("REPEAT");
    number = context.currentNumber();
    context.nextToken();
    commandListNode = new CommandListNode();
    commandListNode.parse(context);
    }

    public void execute() {
    for(int i = 0; i < number; i++)
    commandListNode.execute();
    }

    public String toString() {
    return "[REPEAT " + number + " " +
    commandListNode + "]";
    }
    }

    • Context.java
    import java.util.*;

    public class Context {
    private StringTokenizer tokenizer;
    private String currentToken;

    public Context(String text) {
    tokenizer = new StringTokenizer(text);
    nextToken();
    }

    public String nextToken() {
    if (tokenizer.hasMoreTokens()) {
    currentToken = tokenizer.nextToken();
    } else {
    currentToken = null;
    }
    return currentToken;
    }

    public String currentToken() {
    return currentToken;
    }

    public void skipToken(String token) {
    if (!token.equals(currentToken)) {
    System.err.println("Warning: " + token +
    " is expected, but " +
    currentToken + " is found.");
    }
    nextToken();
    }

    public int currentNumber() {
    int number = 0;
    try {
    number = Integer.parseInt(currentToken);
    } catch (NumberFormatException e) {
    System.err.println("Warning: " + e);
    }
    return number;
    }
    }

    • Main.java
    import java.util.*;
    import java.io.*;

    public class Main {
    public static void main(String[] args) {
    try {
    BufferedReader reader = new BufferedReader(
    new FileReader(args[0]));
    String text;
    while ((text = reader.readLine()) != null) {
    System.out.println("text = \"" + text
    + "\"");
    INode node = new ProgramNode();
    node.parse(new Context(text));
    node.execute();
    }
    }
    catch (ArrayIndexOutOfBoundsException e) {
    System.err.println(
    "Useage: java Main yourprogram.txt");
    }
    catch (Exception e) {
    e.printStackTrace();
    }
    }
    }

    假設(shè)您的直譯程式稿是這麼撰寫的:
    • program.txt
    PROGRAM REPEAT 4 LINEBREAK PRINT justin SPACE PRINT momor LINEBREAK END END

    則程式執(zhí)行的結(jié)果就是:
      $ java Main program.txt
     text = "PROGRAM REPEAT 4 LINEBREAK PRINT justin SPACE
             PRINT momor LINEBREAK END END"
     ------------------------------
     justin momor
     ------------------------------

     ------------------------------
     justin momor
     ------------------------------

     ------------------------------
     justin momor
     ------------------------------

     ------------------------------
     justin momor
     ------------------------------ 

    Design Patterns於Java語言之實(shí)習(xí)應(yīng)用 第23章的範(fàn)例中,可以讓您依指令稿直譯,畫出任何的圖案,讓範(fàn)例結(jié)合了工廠(Factory)模式、外觀(Facade)模式等等,在這邊建議您看看那個範(fàn)例,看看不同的設(shè)計(jì)模式之間如何組合且相互合作。
    posted on 2007-04-17 10:47 張金鵬 閱讀(318) 評論(0)  編輯  收藏 所屬分類: Behavioral 模式
    主站蜘蛛池模板: 国产亚洲福利在线视频| 亚洲人成无码www久久久| 国产AV无码专区亚洲Av| 污污网站免费观看| 亚洲精品制服丝袜四区| 国产人成免费视频网站| 黄色免费在线网址| 亚洲一区二区三区电影| 国产真人无码作爱免费视频| 亚洲欧洲日产韩国在线| 亚洲av无码天堂一区二区三区| 免费国产黄网站在线观看视频| 亚洲午夜国产精品无码老牛影视| 国产成人无码免费网站| 91亚洲性爱在线视频| 57pao一国产成视频永久免费| 久久精品a亚洲国产v高清不卡| 免费无遮挡无码视频网站| 亚洲毛片基地4455ww| 日韩毛片免费无码无毒视频观看| 一区二区三区精品高清视频免费在线播放 | 中文字幕日本人妻久久久免费| 亚洲国产精品无码专区影院| 成年私人影院免费视频网站| 中国videos性高清免费| 色天使色婷婷在线影院亚洲| 亚洲国产精品一区二区三区久久| 国产片AV片永久免费观看| 91天堂素人精品系列全集亚洲 | 在线观看免费毛片| 日韩精品无码专区免费播放| 免费又黄又爽又猛大片午夜| www.亚洲日本| 久久久久亚洲av无码专区喷水| 亚洲一级Av无码毛片久久精品| 欧洲精品免费一区二区三区| 成年人免费的视频| 免费精品一区二区三区第35 | 亚洲av永久无码精品秋霞电影秋 | 亚洲欧美国产日韩av野草社区| 成人五级毛片免费播放|