




版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025應(yīng)屆大學(xué)實(shí)習(xí)生合同協(xié)議
- 2025簽訂房屋租賃合同后遭遇意外損壞維權(quán)難題待解
- 2025關(guān)于商業(yè)店鋪?zhàn)赓U合同范本
- 2025年設(shè)備租賃合同解析
- 2025工程監(jiān)理與咨詢服務(wù)合同(中英文)
- 2025解除合同協(xié)議書
- 2025股權(quán)轉(zhuǎn)讓委托合同
- 2025技術(shù)轉(zhuǎn)讓合同范本協(xié)議書模板
- 2025企業(yè)合同風(fēng)險防控策略研究
- 2025新房購房定金合同
- 設(shè)計(技術(shù))變更申報審批單
- 2024年事業(yè)單位考試模擬300題(含答案)
- HY/T 0273.2-2023海洋災(zāi)害風(fēng)險評估和區(qū)劃技術(shù)導(dǎo)則第2部分:海浪
- 高空作業(yè)施工方案四篇
- 四川省2024年中考數(shù)學(xué)試卷十七套合卷【附答案】
- (高清稿)DB44∕T 2515-2024 水利工程水文化設(shè)計導(dǎo)則
- Unit 3 They are playing.(教學(xué)設(shè)計)-2023-2024學(xué)年湘魯版英語四年級下冊
- DB3502T 090-2022 居家養(yǎng)老緊急事件應(yīng)急助援規(guī)范
- 倉庫物料儲存、搬運(yùn)操作指導(dǎo)書
- GB/T 23587-2024淀粉制品質(zhì)量通則
- 珠子參免疫調(diào)節(jié)作用及其應(yīng)用
評論
0/150
提交評論