首页 > 其他分享 >解释器模式

解释器模式

时间:2022-09-23 21:23:27浏览次数:43  
标签:case note 解释器 string 模式 break vs

理论

解释器模式(interpreter),给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

解释器模式的应用场景:

当有一个语言需要解释执行,并且可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。

解释器模式的优点:

  1. 可以很容易地改变和扩展文法,因为该模式使用类来表示文法规则,可使用继承来改变和扩展该文法。

  2. 也比较容易实现文法,因为定义抽象语法树中各个节点地类地实现大体类似,这些类都易于直接编写。

解释器模式的缺点:

  解释器模式为文法中地每一条规则至少定义了一个类,因此包含许多规则地文法可能难以管理和维护。建议当文法非常复杂时,使用其他技术如语法分析程序或编译器生成器来处理。

实例

实现音乐解释器,定义一套规则:

T表示速度,以毫秒为单位;

O 表示音阶, O1 表示低音阶, O2 表示中音阶, O3 表示高音阶;

P 表示休止符;

C D E F G A B 表示 “Do-Re-Mi-Fa-So-La-Ti”;

音符长度1表示一拍,2表示二拍,0.5表示半拍,0.25表示四分之一拍;

所有字母和数字都要用半角空格分开。

UML类图

代码实现

#include <iostream>
#include <sstream>
#include <vector>
using namespace std;

//演奏内容类
class PlayContext {
public:
    void SetText(string _text) {
        text = _text;
    }
    string GetText() {
        return text;
    }
private:
    string text;
};

//抽象表达式类
class Expression {
public:
    virtual void Excute(string key, string value) = 0;
    void Interpret(PlayContext* context) {
        if (context->GetText().length() == 0)
            return;
        else {
            vector<string> vs;
            stringstream ss(context->GetText());  //使用字符串构造一个stringstream
            //按空格分割字符串
            string buf; 
            while (ss >> buf)
                vs.push_back(buf);
            //解释前两个字符串
            Excute(vs[0], vs[1]);
            //拼接剩下的字符串
            string tmp;
            vs.erase(vs.begin(), vs.begin() + 2);
            for (vector<string>::iterator it = vs.begin(); it != vs.end(); it++) {
                tmp += *it;
                if (it < vs.end() - 1)
                    tmp += " ";
            }
            //更新字符串
            context->SetText(tmp);
        }
    }
};

//音符类
class Note :public Expression {
public:
    void Excute(string key, string value) {
        string note = " ";
        switch (key[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;
        default:
            break;
        }
        cout << note << " ";
    }
};

//音阶类
class Scale :public Expression {
public:
    virtual void Excute(string key, string value) {
        string scale = " ";
        switch (value[0])
        {
        case'1':
            scale = "低音"; break;
        case'2':
            scale = "中音"; break;
        case'3':
            scale = "高音"; break;
        default:
            break;
        }
        cout << scale << " ";
    }
};

//音速类
class Speed : public Expression
{
public:
    void Excute(string key, string value)
    {
        int v = stoi(value);
        if (v < 500)
            cout << "快速 ";
        else if (v > 1000)
            cout << "慢速 ";
        else
            cout << "中速 ";
    }
};

int main()
{
    PlayContext context;
    cout << "上海滩: " << endl;
    context.SetText("T 600 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");
    Expression* expression = NULL;
    while (context.GetText().length() > 0)
    {
        char str = context.GetText()[0];
        switch (str)
        {
        case'O':
            expression = new Scale; break;
        case'T':
            expression = new Speed; break;
        case'C':
        case'D':
        case'E':
        case'F':
        case'G':
        case'A':
        case'B':
        case'P':
            expression = new Note; break;
        default:
            break;
        }
        expression->Interpret(&context);
        delete expression;
    }
    cout << endl;
    return 0;
}

运行结果:

 

标签:case,note,解释器,string,模式,break,vs
From: https://www.cnblogs.com/kyzh-lhl/p/16724229.html

相关文章

  • 前后端开发模式、API接口、接口测试工具postman、restful规范、序列化和反序列化、dja
    目录前后端开发模式一、两种模式1.传统开发模式:前后端混合开发1.1.缺点:2.前后端分离开发模式2.1.特点3.补充老刘的相关博客:二、API接口1.作用2.说明三、接口测试工具postm......
  • 038.IDEA中的Debug模式下各快捷键的使用
                     ......
  • 设计模式_装饰模式
    先看个例子:你买了一辆爱车,现在想给车子增加装饰? 定义汽车行为接口【IBaoMa】,定义方法【startEngine】,【switchOnLights】,【start】。   定义爱车类【LoveCars】,实......
  • 前后端开发模式
    前后端开发模式一、传统的开发模式前后端分离前我们的开发协作模式一般都是这样的:前端写好静态的HTML页面交付给后端开发。静态页面可以本地开发,也无需考虑业务逻辑只......
  • 【设计模式】之策略模式
    场景引入假如你在A城市,要去B城市旅游,交通方式有以下几种选择:驾车火车飞机不难写出这样的代码:voidtransport(stringmethod){if(method=="drive"){......
  • 享元模式
    理论享元模式(Flyweight),运用共享技术有效地支持大量细粒度的对象。内部状态与外部状态:在享元对象内部并且不会随环境变化而改变的共享部分,称为享元对象的内部状态。而随......
  • 设计模式-结构型模式之装饰器
    实现AOP(面向切面编程)的一种便捷方式,额外扩展统一管理装饰器的实现我在语言进阶篇中有提到,这里不再赘述1fromdecoratorimportdecorator234@decorator5......
  • 策略模式演示
    参考:AwardSuper.csusingSystem;usingSystem.Collections.Generic;usingSystem.Text;namespaceStrategyMode{abstractclassAwardSuper{pub......
  • 设计模式-结构型模式之外观
    简化应用程序内部接口,提供一个单一接口以供外部(前端or客户侧)调用1classValley:23defrun(self):4self.pre_declare()5self.declar......
  • 设计模式之(12)——外观模式
    外观模式(facadePattern)又叫门面模式,隐藏了子系统的复杂实现,为子系统中的一组接口提供了一个统一的访问入口,使得子系统容易被访问或使用,说白了就是把复杂的子系统封装成......