直接進入主題,解釋器UML圖express
從UML圖能夠看出ide
核心是AbstractExpression類,做爲解釋器的抽象層他的核心方法是Interpret(Content)單元測試
好的,如今咱們能夠去思考了,怎麼寫解釋器呢?測試
我通常從這個方面開始思考的this
僞代碼spa
step1: 核心方法的入參是Content類,那麼咱們先創造一個Content類吧。3d
step2: 寫一個接口或者抽象類Expression 抽象方法Interpret(Content)。指針
step3: 實現抽象類Expression 抽象方法Interpret(Content)。code
那咱們嘗試寫了一個10之內數字的加法和減法吧blog
建立一個Content類
public class Content { //輸入 private char[] inputs; //結果 private int result=0; //指針標記 private int mark=0; //數字隊列 private ArrayBlockingQueue<Integer> numQueque = new ArrayBlockingQueue<Integer>(20); //符號隊列 private ArrayBlockingQueue<Character> optQueque = new ArrayBlockingQueue<Character>(20); public Content(char[] inputs) { this.inputs = inputs; }
這裏我用兩個隊列來分開保存指令(我分爲數字指令和操做指令)爲了以後的計算器可以方便取值操做
不過這樣的話,初始化Content類就不是很方便了,因此我又寫了一個GammarParser類來初始化和檢測語法。
public class GammarParse { private String numError="數字錯誤:"; private String optError="符號錯誤:"; public Content parseToContent(String str) throws ParseException, InterruptedException{ Content content = new Content(str.toCharArray()); pushConentOptAndNumQueque(content); return content; } /** * 將輸入壓入content的Queque * @param content * @throws ParseException * @throws InterruptedException */ public void pushConentOptAndNumQueque(Content content) throws ParseException, InterruptedException{ for (char c : content.getInputs()) { if(content.getMark()%2==0){//標誌位是雙數則爲數字 try { content.getNumQueque().put(Integer.parseInt(String.valueOf(c))); } catch (Exception e) { throw new ParseException(numError+c); } }else { grammarCheck(c); content.getOptQueque().put(c); } content.setMark(content.getMark()+1); } } /** * 符號檢查器 * @param c * @throws ParseException */ private void grammarCheck(char c) throws ParseException{ if(!(c=='+'||c=='-')){ throw new ParseException(optError+c); } } }
寫一個接口或者抽象類Expression 抽象方法Interpret(Content)。
public interface Interperter { void interperter(Content content); }
實現抽象類Expression 抽象方法Interpret(Content)的類CalcInterperter。
public class CalcInterperter implements Interperter{ @Override public void interperter(Content content) { content.setResult(content.getNumQueque().poll());//第一個數字隊列直接賦值給result while(!content.getNumQueque().isEmpty()){ switch (content.getOptQueque().poll()) { case '+': content.setResult(content.getResult()+content.getNumQueque().poll()); break; case '-': content.setResult(content.getResult()-content.getNumQueque().poll()); break; default: break; } } } }
這裏我判斷數字隊列不爲空則將數字出隊同時與符號隊列出隊的元素進行計算。
好了,簡單的1-10內的加減法計算器作完了。讓咱們來跑一下單元測試吧
public class Client { @Test public void test() throws ParseException, InterruptedException{ List<String> expresses = new ArrayList<String>(); expresses.add( "1+2"); expresses.add( "1+2+3"); expresses.add( "1+2+5"); expresses.add( "1+2-3"); expresses.add( "1+2-9"); expresses.add( "1+2-8+2"); GammarParse paser = new GammarParse(); CalcInterperter calc = new CalcInterperter(); for (String exp : expresses) { Content content = paser.parseToContent(exp); calc.interperter(content); System.out.println(exp+" = "+ content.getResult()); } } }
1+2 = 3 1+2+3 = 6 1+2+5 = 8 1+2-3 = 0 1+2-9 = -6 1+2-8+2 = -3