解釋器模式(interpreter),給定一個語言,定義它的文法的一種表示,並定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。ios
解釋器模式須要解決的問題,若是一個特定類型的問題發生的頻率足夠高,那麼可能就值得將該問題的各個實例表述爲一個簡單語言中的句子。這樣就能夠構建一個解釋器,該解釋器經過解釋這些句子來解決該問題。express
#include <iostream> #include <list> using namespace std; class Context; //AbstractExpression(抽象表達式),聲明一個抽象的解釋操做,這個接口爲抽象語法樹中全部的結點所共享 class AbstractExpression { public: virtual void Interpret(Context *context)=0; }; //TerminalExpression(終結符表達式),實現與文法中的終結符相關聯的解釋操做。實現抽象表達式中所要求的接口, //主要是一個interpret()方法。文法中每個終結符都有一個具體終結表達式與之相對應。 class TerminalExpression:public AbstractExpression { public: void Interpret(Context *context) { cout << "終端解釋器" << endl; } }; //NonterminalExpression(非終結符表達式),爲文法中的非終結符實現解釋操做。對文法中每一條規則R一、R2......Rn //都須要一個具體的非終結符表達式類。經過實現抽象表達式的interpret()方法實現解釋操做。解釋操做以遞歸方式調用 //上面所提到的表明R一、R2......Rn中各個符號的實例變量 class NonterminalExpression:public AbstractExpression { public: void Interpret(Context *context) { cout << "非終端解釋器" << endl; } }; //Context,包含解釋器以外的一些全局信息 class Context { private: string m_input; string m_output; public: void SetInput(string input) { this->m_input=input; } string GetInput() { return m_input; } void SetOutput(string output) { this->m_output=output; } string GetOutput() { return m_output; } }; //客戶端代碼,構建表示該文法定義的語言中一個特定的句子的抽象語法樹。調用解釋操做 int main() { Context *context=new Context(); list<AbstractExpression*> alist; alist.push_back(new TerminalExpression()); alist.push_back(new NonterminalExpression()); alist.push_back(new TerminalExpression()); alist.push_back(new TerminalExpression()); list<AbstractExpression*>::iterator iter=alist.begin(); for(;iter!=alist.end();iter++) (*iter)->Interpret(context); return 0; }
當有一個語言須要解釋執行,而且可將該語言中的句子表示爲一個抽象語法樹時,可以使用解釋器模式。用瞭解釋器模式,就意味着能夠很容易地改變和擴展文法,由於該模式使用類來表示文法規則,你可使用繼承來改變或擴展該文法。也比較容易實現文法,由於定義抽象語法樹中各個節點的類的實現大致相似,這些類都易於直接編寫。解釋器模式也有不足,解釋器模式爲文法中的每一條規則至少定義了一個類,所以包含許多規則的文法可能難以管理和維護。建議當文法很是複雜時,使用其餘的技術如語法分析程序或編譯器生成器來處理。this
#include <iostream> #include <list> #include <string> #include <string.h> #include <cstdlib> using namespace std; //演奏內容類 class PlayContext { private: string m_text; public: void SetText(string text) { this->m_text=text; } string GetText() { return m_text; } }; //表達式類 class Expression { public: void Interpret(PlayContext *context) { if(context->GetText().length()==0) return; else { string playKey=context->GetText().substr(0,1); context->SetText(context->GetText().substr(2)); int nPos=context->GetText().find(" "); string strPlayValue=context->GetText().substr(0,nPos); int nPlayValue=atoi(strPlayValue.c_str()); nPos=context->GetText().find(" "); context->SetText(context->GetText().substr(nPos+1)); Execute(playKey,nPlayValue); } } virtual void Execute(string strKey,const int nValue)=0; }; //音符類 class Note:public Expression { public: void Execute(string strKey,const int nValue) { char szKey[2]; strncpy(szKey,strKey.c_str(),strKey.length()); string note=""; switch(szKey[0]) { case 'C': note="1"; break; case 'D': note="2"; break; case 'E': note="3"; break; case 'F': note="4"; break; case 'G': note="5"; break; case 'A': note="6"; break; case 'B': note="7"; break; } cout << note << " "; } }; //音階類 class Scale:public Expression { public: void Execute(string key,const int value) { string strScale; switch(value) { case 1: strScale="低音"; break; case 2: strScale="中音"; break; case 3: strScale="高音"; break; } cout << strScale << " "; } }; //音速類 class Speed:public Expression { public: void Execute(string key,const int value) { string speed; if(value<500) speed="快速"; else if(value>=1000) speed="慢速"; else speed="中速"; cout << speed << " "; } }; int main() { PlayContext *context=new PlayContext(); cout << "上海灘:"; context->SetText("T 500 O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 G 0.5 A 0.5 O 3 C 1 O 2 A 0.5 G 1 C 0.5 E 0.5 D 3 "); Expression *expression=NULL; while(!context->GetText().empty()) { string str=context->GetText().substr(0,1); char szKey[2]; strncpy(szKey,str.c_str(),str.length()); switch(szKey[0]) { case 'T': expression=new Speed(); break; case 'O': expression=new Scale(); break; case 'C': case 'D': case 'E': case 'F': case 'G': case 'A': case 'B': expression = new Note(); break; default: break; } if(NULL!=expression) expression->Interpret(context); } return 0; }