自定義語言的實(shí)現(xiàn)——解釋器模式_第1頁
自定義語言的實(shí)現(xiàn)——解釋器模式_第2頁
自定義語言的實(shí)現(xiàn)——解釋器模式_第3頁
自定義語言的實(shí)現(xiàn)——解釋器模式_第4頁
自定義語言的實(shí)現(xiàn)——解釋器模式_第5頁
已閱讀5頁,還剩18頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、     自定義語言的實(shí)現(xiàn)解釋器模式有朋友一直在等待我的解釋器模式文稿,現(xiàn)把某個版本發(fā)在博客上,歡迎大家討論!       雖然目前計算機(jī)編程語言有好幾百種,但有時候我們還是希望能用一些簡單的語言來實(shí)現(xiàn)一些特定的操作,我們只要向計算機(jī)輸入一個句子或文件,它就能夠按照預(yù)先定義的文法規(guī)則來對句子或文件進(jìn)行解釋,從而實(shí)現(xiàn)相應(yīng)的功能。例如提供一個簡單的加法/減法解釋器,只要輸入一個加法/減法表達(dá)式,它就能夠計算出表達(dá)式結(jié)果,如圖18-1所示,當(dāng)輸入字符串表達(dá)式為“1 + 2 + 3 4 + 1

2、”時,將輸出計算結(jié)果為3。圖18-1  加法/減法解釋器示意圖       我們知道,像C+、Java和C#等語言無法直接解釋類似“1+ 2 + 3 4 + 1”這 樣的字符串(如果直接作為數(shù)值表達(dá)式時可以解釋),我們必須自己定義一套文法規(guī)則來實(shí)現(xiàn)對這些語句的解釋,即設(shè)計一個自定義語言。在實(shí)際開發(fā)中,這些簡單 的自定義語言可以基于現(xiàn)有的編程語言來設(shè)計,如果所基于的編程語言是面向?qū)ο笳Z言,此時可以使用解釋器模式來實(shí)現(xiàn)自定義語言。18.1 機(jī)器人控制程序       S

3、unny軟件公司欲為某玩具公司開發(fā)一套機(jī)器人控制程序,在該機(jī)器人控制程序中包含一些簡單的英文控制指令,每一個指令對應(yīng)一個表達(dá)式(expression),該表達(dá)式可以是簡單表達(dá)式也可以是復(fù)合表達(dá)式,每一個簡單表達(dá)式由移動方向(direction),移動方式(action)和移動距離(distance)三部分組成,其中移動方向包括上(up)、下(down)、左(left)、右(right);移動方式包括移動(move)和快速移動(run);移動距離為一個正整數(shù)。兩個表達(dá)式之間可以通過與(and)連接,形成復(fù)合(composite)表達(dá)式。     

4、  用戶通過對圖形化的設(shè)置界面進(jìn)行操作可以創(chuàng)建一個機(jī)器人控制指令,機(jī)器人在收到指令后將按照指令的設(shè)置進(jìn)行移動,例如輸入控制指令:up move 5,則“向上移動5個單位”;輸入控制指令:down  run 10 and left move 20,則“向下快速移動10個單位再向左移動20個單位”。       Sunny軟件公司開發(fā)人員決定自定義一個簡單的語言來解釋機(jī)器人控制指令,根據(jù)上述需求描述,用形式化語言來表示該簡單語言的文法規(guī)則如下:expression := direction action distanc

5、e | composite /表達(dá)式composite := expression 'and' expression /復(fù)合表達(dá)式direction := 'up' | 'down' | 'left' | 'right' /移動方向action := 'move' | 'run' /移動方式distance := an integer /移動距離       上述語言一共定義了五條文法規(guī)則,對應(yīng)五個語言單位,這些語言單位可以

6、分為兩類,一類為終結(jié)符(也稱為終結(jié)符表達(dá)式),例如direction、action和distance,它們是語言的最小組成單位,不能再進(jìn)行拆分;另一類為非終結(jié)符(也稱為非終結(jié)符表達(dá)式),例如expression和composite,它們都是一個完整的句子,包含一系列終結(jié)符或非終結(jié)符。       我們根據(jù)上述規(guī)則定義出的語言可以構(gòu)成很多語句,計算機(jī)程序?qū)⒏鶕?jù)這些語句進(jìn)行某種操作。為了實(shí)現(xiàn)對語句的解釋,可以使用解釋器模式,在解釋器模式中每一 個文法規(guī)則都將對應(yīng)一個類,擴(kuò)展、改變文法以及增加新的文法規(guī)則都很方便,下面就讓我們正式進(jìn)入解釋器

7、模式的學(xué)習(xí),看看使用解釋器模式如何來實(shí)現(xiàn)對機(jī)器人 控制指令的處理。18.2 文法規(guī)則和抽象語法樹       解釋器模式描述了如何為簡單的語言定義一個文法,如何在該語言中表示一個句子,以及如何解釋這些句子。在正式分析解釋器模式結(jié)構(gòu)之前,我們先來學(xué)習(xí)如何表示一個語言的文法規(guī)則以及如何構(gòu)造一棵抽象語法樹。       在前面所提到的加法/減法解釋器中,每一個輸入表達(dá)式,例如“1 + 2 + 3 4 + 1”,都包含了三個語言單位,可以使用如下文法規(guī)則來定義:expression

8、:= value | operationoperation := expression '+' expression | expression '-'  expressionvalue := an integer /一個整數(shù)值       該文法規(guī)則包含三條語句,第一條表示表達(dá)式的組成方式,其中value和operation是后面兩個語言單位的定義,每一條語句所定義的字符串如operation和value稱為語言構(gòu)造成分或語言單位,符號“:=”表示“定義為”的意思,其左邊的語言單位通過右邊來進(jìn)

9、行說明和定義,語言單位對應(yīng)終結(jié)符表達(dá)式和非終結(jié)符表達(dá)式。如本規(guī)則中的operation是非終結(jié)符表達(dá)式,它的組成元素仍然可以是表達(dá)式,可以進(jìn)一步分解,而value是終結(jié)符表達(dá)式,它的組成元素是最基本的語言單位,不能再進(jìn)行分解。       在文法規(guī)則定義中可以使用一些符號來表示不同的含義,如使用“|”表示或,使用“”和“”表示組合,使用“*”表示出現(xiàn)0次或多次等,其中使用頻率最高的符號是表示“或”關(guān)系的“|”,如文法規(guī)則“boolValue := 0 | 1”表示終結(jié)符表達(dá)式boolValue的取值可以為0或者1。 

10、0;     除了使用文法規(guī)則來定義一個語言,在解釋器模式中還可以通過一種稱之為抽象語法樹(Abstract Syntax Tree, AST)的圖形方式來直觀地表示語言的構(gòu)成,每一棵抽象語法樹對應(yīng)一個語言實(shí)例,如加法/減法表達(dá)式語言中的語句“1+ 2 + 3 4 + 1”,可以通過如圖18-2所示抽象語法樹來表示:圖18-2  抽象語法樹示意圖       在該抽象語法樹中,可以通過終結(jié)符表達(dá)式value和非終結(jié)符表達(dá)式operation組成復(fù)雜的語句,每個文法規(guī)則的語言實(shí)例都可以表

11、示為一個抽象語法樹,即每一條具體的語句都可以用類似圖18-2所示的抽象語法樹來表示,在圖中終結(jié)符表達(dá)式類的實(shí)例作為樹的葉子節(jié)點(diǎn),而非終結(jié)符表達(dá)式類的實(shí)例作為非葉子節(jié)點(diǎn),它們可以將終結(jié)符表達(dá)式類的實(shí)例以及包含終結(jié)符和非終結(jié)符實(shí)例的子表達(dá)式作為其子節(jié)點(diǎn)。抽象語法樹描述了如何構(gòu)成一個復(fù)雜的句子,通過對抽象語法樹的分析,可以識別出語言中的終結(jié)符類和非終結(jié)符類。18.3 解釋器模式概述       解釋器模式是一種使用頻率相對較低但學(xué)習(xí)難度較大的設(shè)計模式,它用于描述如何使用面向?qū)ο笳Z言構(gòu)成一個簡單的語言解釋器。在某些情況下,為了更好地描述某 一

12、些特定類型的問題,我們可以創(chuàng)建一種新的語言,這種語言擁有自己的表達(dá)式和結(jié)構(gòu),即文法規(guī)則,這些問題的實(shí)例將對應(yīng)為該語言中的句子。此時,可以使用解 釋器模式來設(shè)計這種新的語言。對解釋器模式的學(xué)習(xí)能夠加深我們對面向?qū)ο笏枷氲睦斫猓⑶艺莆站幊陶Z言中文法規(guī)則的解釋過程。       解釋器模式定義如下:解釋器模式(Interpreter Pattern):定義一個語言的文法,并且建立一個解釋器來解釋該語言中的句子,這里的“語言”是指使用規(guī)定格式和語法的代碼。解釋器模式是一種類行為型模式。    

13、0;  由于表達(dá)式可分為終結(jié)符表達(dá)式和非終結(jié)符表達(dá)式,因此解釋器模式的結(jié)構(gòu)與組合模式的結(jié)構(gòu)有些類似,但在解釋器模式中包含更多的組成元素,它的結(jié)構(gòu)如圖18-3所示:圖18-3  解釋器模式結(jié)構(gòu)圖       在解釋器模式結(jié)構(gòu)圖中包含如下幾個角色:       AbstractExpression(抽象表達(dá)式):在抽象表達(dá)式中聲明了抽象的解釋操作,它是所有終結(jié)符表達(dá)式和非終結(jié)符表達(dá)式的公共父類。     

14、60; TerminalExpression(終結(jié)符表達(dá)式):終結(jié)符表達(dá)式是抽象表達(dá)式的子類,它實(shí)現(xiàn)了與文法中的終結(jié)符相關(guān)聯(lián)的解釋操作,在句子中的每一個終結(jié)符都是該類的一個實(shí)例。通常在一個解釋器模式中只有少數(shù)幾個終結(jié)符表達(dá)式類,它們的實(shí)例可以通過非終結(jié)符表達(dá)式組成較為復(fù)雜的句子。       NonterminalExpression(非終結(jié)符表達(dá)式):非終結(jié)符表達(dá)式也是抽象表達(dá)式的子類,它實(shí)現(xiàn)了文法中非終結(jié)符的解釋操作,由于在非終結(jié)符表達(dá)式中可以包含終結(jié)符表達(dá)式,也可以繼續(xù)包含非終結(jié)符表達(dá)式,因此其解釋操作一般通過遞歸的方式來完成。

15、       Context(環(huán)境類):環(huán)境類又稱為上下文類,它用于存儲解釋器之外的一些全局信息,通常它臨時存儲了需要解釋的語句。       在解釋器模式中,每一種終結(jié)符和非終結(jié)符都有一個具體類與之對應(yīng),正因為使用類來表示每一條文法規(guī)則,所以系統(tǒng)將具有較好的靈活性和可擴(kuò)展性。對于所有的終結(jié)符和非終結(jié)符,我們首先需要抽象出一個公共父類,即抽象表達(dá)式類,其典型代碼如下所示:abstract class AbstractExpression    &

16、#160;   public  abstract void interpret(Context ctx);       終結(jié)符表達(dá)式和非終結(jié)符表達(dá)式類都是抽象表達(dá)式類的子類,對于終結(jié)符表達(dá)式,其代碼很簡單,主要是對終結(jié)符元素的處理,其典型代碼如下所示:class TerminalExpression extends  AbstractExpression        public  void interpret(Contex

17、t ctx)               /終結(jié)符表達(dá)式的解釋操作              對于非終結(jié)符表達(dá)式,其代碼相對比較復(fù)雜,因為可以通過非終結(jié)符將表達(dá)式組合成更加復(fù)雜的結(jié)構(gòu),對于包含兩個操作元素的非終結(jié)符表達(dá)式類,其典型代碼如下:class NonterminalExpression extends  AbstractExpre

18、ssion        private  AbstractExpression left;       private  AbstractExpression right;              public  NonterminalExpression(AbstractExpression left,AbstractEx

19、pression right)               this.left=left;              this.right=right;                 &#

20、160;   public void interpret(Context ctx)               /遞歸調(diào)用每一個組成部分的interpret()方法              /在遞歸調(diào)用時指定組成部分的連接方式,即非終結(jié)符的功能      

21、             除了上述用于表示表達(dá)式的類以外,通常在解釋器模式中還提供了一個環(huán)境類Context,用于存儲一些全局信息,通常在Context中包含了一個HashMap或ArrayList等類型的集合對象(也可以直接由HashMap等集合類充當(dāng)環(huán)境類),存儲一系列公共信息,如變量名與值的映射關(guān)系(key/value)等,用于在進(jìn)行具體的解釋操作時從中獲取相關(guān)信息。其典型代碼片段如下:class Context      private

22、HashMap map = new HashMap();     public void assign(String key, String value)          /往環(huán)境類中設(shè)值     public String  lookup(String key)          /獲取存儲在環(huán)境類中的值   &#

23、160;        當(dāng)系統(tǒng)無須提供全局公共信息時可以省略環(huán)境類,可根據(jù)實(shí)際情況決定是否需要環(huán)境類。思考繪制加法/減法解釋器的類圖并編寫核心實(shí)現(xiàn)代碼。18.4 完整解決方案      為了能夠解釋機(jī)器人控制指令,Sunny軟件公司開發(fā)人員使用解釋器模式來設(shè)計和實(shí)現(xiàn)機(jī)器人控制程序。針對五條文法規(guī)則,分別提供五個類來實(shí)現(xiàn),其中終結(jié)符表達(dá)式direction、action和distance對應(yīng)DirectionNode類、ActionNode類和DistanceNode類,非終結(jié)符表達(dá)式e

24、xpression和composite對應(yīng)SentenceNode類和AndNode類。      我們可以通過抽象語法樹來表示具體解釋過程,例如機(jī)器人控制指令“down run 10 and left move 20”對應(yīng)的抽象語法樹如圖18-4所示:圖18-4   機(jī)器人控制程序抽象語法樹實(shí)例      機(jī)器人控制程序?qū)嵗窘Y(jié)構(gòu)如圖18-5所示:圖18-5   機(jī)器人控制程序結(jié)構(gòu)圖      在圖18

25、-5中,AbstractNode充當(dāng)抽象表達(dá)式角色,DirectionNode、ActionNode和DistanceNode充當(dāng)終結(jié)符表達(dá)式角色,AndNode和SentenceNode充當(dāng)非終結(jié)符表達(dá)式角色。完整代碼如下所示:javaview plaincopy1. /注:本實(shí)例對機(jī)器人控制指令的輸出結(jié)果進(jìn)行模擬,將英文指令翻譯為中文指令,實(shí)際情況是調(diào)用不同的控制程序進(jìn)行機(jī)器人的控制,包括對移動方向、方式和距離的控制等  2. import java.util.*;  3.   4. /抽象表達(dá)式  

26、5. abstract class AbstractNode   6.     public abstract String interpret();  7.   8.   9. /And解釋:非終結(jié)符表達(dá)式  10. class AndNode extends AbstractNode   11.    &

27、#160;private AbstractNode left; /And的左表達(dá)式  12.     private AbstractNode right; /And的右表達(dá)式  13.   14.     public AndNode(AbstractNode left, AbstractNode right)   15. &

28、#160;       this.left = left;  16.         this.right = right;  17.       18.       19.     /And表達(dá)式解釋操作&#

29、160; 20.     public String interpret()   21.         return erpret() + "再" + erpret();  22.       23.   24.

30、  25. /簡單句子解釋:非終結(jié)符表達(dá)式  26. class SentenceNode extends AbstractNode   27.     private AbstractNode direction;  28.     private AbstractNode action;  29.    

31、 private AbstractNode distance;  30.   31.     public SentenceNode(AbstractNode direction,AbstractNode action,AbstractNode distance)   32.         this.direction =&#

32、160;direction;  33.         this.action = action;  34.         this.distance = distance;  35.       36.       

33、37.     /簡單句子的解釋操作  38.     public String interpret()   39.         return erpret() + erpret() + erpret();  40. 

34、60;        41.   42.   43. /方向解釋:終結(jié)符表達(dá)式  44. class DirectionNode extends AbstractNode   45.     private String direction;  46.      

35、60;47.     public DirectionNode(String direction)   48.         this.direction = direction;  49.       50.       51.    

36、 /方向表達(dá)式的解釋操作  52.     public String interpret()   53.         if (direction.equalsIgnoreCase("up")   54.            

37、; return "向上"  55.           56.         else if (direction.equalsIgnoreCase("down")   57.          

38、   return "向下"  58.           59.         else if (direction.equalsIgnoreCase("left")   60.        &

39、#160;    return "向左"  61.           62.         else if (direction.equalsIgnoreCase("right")   63.      &

40、#160;      return "向右"  64.           65.         else   66.             return&

41、#160;"無效指令"  67.           68.       69.   70.   71. /動作解釋:終結(jié)符表達(dá)式  72. class ActionNode extends AbstractNode   73.     p

42、rivate String action;  74.       75.     public ActionNode(String action)   76.         this.action = action;  77.      

43、 78.       79.     /動作(移動方式)表達(dá)式的解釋操作  80.     public String interpret()   81.         if (action.equalsIgnoreCase("move")  &#

44、160;82.             return "移動"  83.           84.         else if (action.equalsIgnoreCase("run") &

45、#160; 85.             return "快速移動"  86.           87.         else   88.      &

46、#160;      return "無效指令"  89.           90.       91.   92.   93. /距離解釋:終結(jié)符表達(dá)式  94. class DistanceNode extends AbstractN

47、ode   95.     private String distance;  96.       97.     public DistanceNode(String distance)   98.         this.distance =&

48、#160;distance;  99.       100.       101. /距離表達(dá)式的解釋操作  102.     public String interpret()   103.         return this.distance;

49、0; 104.          105.   106.   107. /指令處理類:工具類  108. class InstructionHandler   109.     private String instruction;  110.     private 

50、AbstractNode node;  111.       112.     public void handle(String instruction)   113.         AbstractNode left = null, right = null;&#

51、160; 114.         AbstractNode direction = null, action = null, distance = null;  115.         Stack stack = new Stack(); /聲明一個棧對象用于存儲抽

52、象語法樹  116.         String words = instruction.split(" "); /以空格分隔指令字符串  117.         for (int i = 0; i < words.length; i+)&

53、#160;  118. / 本實(shí)例采用棧的方式來處理指令,如果遇到“and”,則將其后的三個單詞作為三個終結(jié)符表達(dá)式連成一個簡單句子SentenceNode作為“and”的 右表達(dá)式,而將從棧頂彈出的表達(dá)式作為“and”的左表達(dá)式,最后將新的“and”表達(dá)式壓入棧 中。                   if (wordsi.equalsIgnoreCase("an

54、d")   119.                 left = (AbstractNode)stack.pop(); /彈出棧頂表達(dá)式作為左表達(dá)式  120.                

55、60;String word1= words+i;  121.                 direction = new DirectionNode(word1);  122.               

56、;  String word2 = words+i;  123.                 action = new ActionNode(word2);  124.             &

57、#160;   String word3 = words+i;  125.                 distance = new DistanceNode(word3);  126.           

58、;      right = new SentenceNode(direction,action,distance); /右表達(dá)式  127.                 stack.push(new AndNode(left,right); /將新表達(dá)式壓入棧中  128.

59、               129.             /如果是從頭開始進(jìn)行解釋,則將前三個單詞組成一個簡單句子SentenceNode并將該句子壓入棧中  130.             

60、else   131.                 String word1 = wordsi;  132.                 direction = new&#

61、160;DirectionNode(word1);  133.                 String word2 = words+i;  134.                 action 

62、;= new ActionNode(word2);  135.                 String word3 = words+i;  136.                 d

63、istance = new DistanceNode(word3);  137.                 left = new SentenceNode(direction,action,distance);  138.          &

64、#160;      stack.push(left); /將新表達(dá)式壓入棧中  139.               140.           141.         this.no

65、de = (AbstractNode)stack.pop(); /將全部表達(dá)式從棧中彈出  142.       143.       144.     public String output()   145.         String res

66、ult = erpret(); /解釋表達(dá)式  146.         return result;  147.       148.          工具類InstructionHandler用于對輸入指令進(jìn)行處理,將輸入指令分割為字符串?dāng)?shù)組,將第1個、第2個和第3個單詞組合成

67、一個句子,并存入棧中;如果發(fā)現(xiàn)有單詞“and”,則將“and”后的第1個、第2個和第3個單詞組合成一個新的句子作為“and”的右表達(dá)式,并從棧中取出原先所存句子作為左表達(dá)式,然后組合成一個And節(jié)點(diǎn)存入棧中。依此類推,直到整個指令解析結(jié)束。       編寫如下客戶端測試代碼:javaview plaincopy1. class Client   2.     public static void main(String

68、60;args)   3.         String instruction = "up move 5 and down run 10 and left move 5"  4.         InstructionHandler

69、60;handler = new InstructionHandler();  5.         handler.handle(instruction);  6.         String outString;  7.         outStrin

70、g = handler.output();  8.         System.out.println(outString);  9.       10.          編譯并運(yùn)行程序,輸出結(jié)果如下:向上移動5再向下快速移動10再向左移動518.5 再談Context的作用   &#

71、160;   在解釋器模式中,環(huán)境類Context用于存儲解釋器之外的一些全局信息,它通常作為參數(shù)被傳遞到所有表達(dá)式的解釋方法interpret()中,可以在Context對象中存儲和訪問表達(dá)式解釋器的狀態(tài),向表達(dá)式解釋器提供一些全局的、公共的數(shù)據(jù),此外還可以在Context中增加一些所有表達(dá)式解釋器都共有的功能,減輕解釋器的職責(zé)。       在上面的機(jī)器人控制程序?qū)嵗?,我們省略了環(huán)境類角色,下面再通過一個簡單實(shí)例來說明環(huán)境類的用途:       Su

72、nny軟件公司開發(fā)了一套簡單的基于字符界面的格式化指令,可以根據(jù)輸入的指令在字符界面中輸出一些格式化內(nèi)容,例如輸入“LOOP 2 PRINT楊過 SPACE SPACE PRINT 小龍女 BREAK END PRINT郭靖 SPACE SPACE PRINT 黃蓉”,將輸出如下結(jié)果:楊過     小龍女楊過     小龍女郭靖     黃蓉       其中關(guān)鍵詞LOOP表示“循環(huán)”,

73、后面的數(shù)字表示循環(huán)次數(shù);PRINT表示“打印”,后面的字符串表示打印的內(nèi)容;SPACE表示“空格”;BREAK表示“換行”;END表示“循環(huán)結(jié)束”。每一個關(guān)鍵詞對應(yīng)一條命令,計算機(jī)程序?qū)⒏鶕?jù)關(guān)鍵詞執(zhí)行相應(yīng)的處理操作。       現(xiàn)使用解釋器模式設(shè)計并實(shí)現(xiàn)該格式化指令的解釋,對指令進(jìn)行分析并調(diào)用相應(yīng)的操作執(zhí)行指令中每一條命令。       Sunny軟件公司開發(fā)人員通過分析,根據(jù)該格式化指令中句子的組成,定義了如下文法規(guī)則:expression := command* /表達(dá)

74、式,一個表達(dá)式包含多條命令command := loop | primitive /語句命令loop := 'loopnumber' expression  'end' /循環(huán)命令,其中number為自然數(shù)primitive := 'printstring'  | 'space' | 'break' /基本命令,其中string為字符串       根據(jù)以上文法規(guī)則,通過進(jìn)一步分析,繪制如圖18-6所示結(jié)構(gòu)圖:圖18-6 &#

75、160;  格式化指令結(jié)構(gòu)圖       在圖18-6中,Context充當(dāng)環(huán)境角色,Node充當(dāng)抽象表達(dá)式角色,ExpressionNode、CommandNode和LoopCommandNode充當(dāng)非終結(jié)符表達(dá)式角色,PrimitiveCommandNode充當(dāng)終結(jié)符表達(dá)式角色。完整代碼如下所示:javaview plaincopy1. import java.util.*;  2.   3. /環(huán)境類:用于存儲和操作需要解釋的語句,在本實(shí)例中每一個需要解釋的單詞可以稱為

76、一個動作標(biāo)記(Action Token)或命令  4. class Context   5.     private StringTokenizer tokenizer; /StringTokenizer類,用于將字符串分解為更小的字符串標(biāo)記(Token),默認(rèn)情況下以空格作為分隔符  6.     private String currentToken; /當(dāng)前字符

77、串標(biāo)記  7.       8.     public Context(String text)   9.         tokenizer = new StringTokenizer(text); /通過傳入的指令字符串創(chuàng)建StringTokenizer對象  10.  &#

78、160;      nextToken();  11.       12.       13.     /返回下一個標(biāo)記  14.     public String nextToken()   15.     

79、;    if (tokenizer.hasMoreTokens()   16.             currentToken = tokenizer.nextToken();  17.           18.    &#

80、160;    else   19.             currentToken = null;  20.           21.         return curr

81、entToken;  22.       23.       24.     /返回當(dāng)前的標(biāo)記  25.     public String currentToken()   26.         return cur

82、rentToken;  27.       28.       29.     /跳過一個標(biāo)記  30.     public void skipToken(String token)   31.         if&

83、#160;(!token.equals(currentToken)   32.             System.err.println("錯誤提示:" + currentToken + "解釋錯誤!");  33.           

84、0;   34.         nextToken();  35.       36.       37.     /如果當(dāng)前的標(biāo)記是一個數(shù)字,則返回對應(yīng)的數(shù)值  38.     public int currentNumber

85、()   39.         int number = 0;  40.         try  41.             number = Integer.parseInt(current

86、Token); /將字符串轉(zhuǎn)換為整數(shù)  42.           43.         catch(NumberFormatException e)   44.             System.err.println(&

87、quot;錯誤提示:" + e);  45.           46.         return number;  47.       48.   49.   50. /抽象節(jié)點(diǎn)類:抽象表達(dá)式  51. abstr

88、act class Node   52.     public abstract void interpret(Context text); /聲明一個方法用于解釋語句  53.     public abstract void execute(); /聲明一個方法用于執(zhí)行標(biāo)記對應(yīng)的命令  54.   55. 

89、0; 56. /表達(dá)式節(jié)點(diǎn)類:非終結(jié)符表達(dá)式  57. class ExpressionNode extends Node   58.     private ArrayList<Node> list = new ArrayList<Node>(); /定義一個集合用于存儲多條命令  59.       

90、60.     public void interpret(Context context)   61.         /循環(huán)處理Context中的標(biāo)記  62.         while (true)  63.       

91、      /如果已經(jīng)沒有任何標(biāo)記,則退出解釋  64.             if (context.currentToken() = null)   65.               

92、0; break;  66.               67.             /如果標(biāo)記為END,則不解釋END并結(jié)束本次解釋過程,可以繼續(xù)之后的解釋  68.          

93、0;  else if (context.currentToken().equals("END")   69.                 context.skipToken("END");  70.         

94、0;       break;  71.               72.             /如果為其他標(biāo)記,則解釋標(biāo)記并將其加入命令集合  73.       

95、;      else   74.                 Node commandNode = new CommandNode();  75.            &#

96、160;    commandNerpret(context);  76.                 list.add(commandNode);  77.               78. 

97、60;         79.       80.       81.     /循環(huán)執(zhí)行命令集合中的每一條命令  82.     public void execute()   83.     &#

98、160;   Iterator iterator = list.iterator();  84.         while (iterator.hasNext()  85.             (Node)iterator.next().execute();  8

99、6.           87.       88.   89.   90. /語句命令節(jié)點(diǎn)類:非終結(jié)符表達(dá)式  91. class CommandNode extends Node   92.     private Node node; 

100、0;93.       94.     public void interpret(Context context)   95.         /處理LOOP循環(huán)命令  96.         if (context.currentToken().

101、equals("LOOP")   97.             node = new LoopCommandNode();  98.             erpret(context);  99.  

102、0;        100.         /處理其他基本命令  101.         else   102.             node = new

103、0;PrimitiveCommandNode();  103.             erpret(context);  104.           105.       106.       107

104、.     public void execute()   108.         node.execute();  109.       110.   111.   112. /循環(huán)命令節(jié)點(diǎn)類:非終結(jié)符表達(dá)式  113. class LoopCommandNode 

105、extends Node   114.     private int number; /循環(huán)次數(shù)  115.     private Node commandNode; /循環(huán)語句中的表達(dá)式  116.       117.     /解釋循環(huán)命令  118

106、.     public void interpret(Context context)   119.         context.skipToken("LOOP");  120.         number = context.currentNumber(); 

107、 121.         context.nextToken();  122.         commandNode = new ExpressionNode(); /循環(huán)語句中的表達(dá)式  123.         commandNerpret(con

108、text);  124.       125.       126.     public void execute()   127.         for (int i=0;i<number;i+)  128.   &#

109、160;         commandNode.execute();  129.       130.   131.   132. /基本命令節(jié)點(diǎn)類:終結(jié)符表達(dá)式  133. class PrimitiveCommandNode extends Node   134.    &

110、#160;private String name;  135.     private String text;  136.       137.     /解釋基本命令  138.     public void interpret(Context context)  

111、; 139.         name = context.currentToken();  140.         context.skipToken(name);  141.         if (!name.equals("PRINT") 

112、&& !name.equals("BREAK") && !name.equals ("SPACE")  142.             System.err.println("非法命令!");  143.         &#

113、160; 144.         if (name.equals("PRINT")  145.             text = context.currentToken();  146.             context.nextToken();  147.           148.       149.       150.     public void execute()  151.  

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論