zoukankan      html  css  js  c++  java
  • 第二十七章-解释器模式

    解释器模式(Interpreter): 给定一个语言,定义它的文法中的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
    如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。

    图片

    解释器模式的好处

    通常当有一个语言需要解释执行,并且你可以将该预言中的句子表示为一个抽象语法树时,可使用解释器模式。
    用了解释器模式,就意味着可以很容易地改变和扩展文法,因为该模式使用类来表示文法规则,你可以使用继承来改变或扩展该文法。也比较容易实现文法,因为定义抽象语法树中各个节点的类的实现大体类似,这些类都易于直接编写。
    但解释器模式也有不足,解释器模式为文法中的每一条规则至少定义了一个类,因此包含许多规则的文法可能难以管理和维护。建议当文法非常复杂时,使用其他的技术如语法分析程序或编译器生成器来处理。

    音乐解释器

    图片

    图片

    #include <iostream>
    #include<vector>
    #include<string>
    #include<ctime>
    #include<unordered_map>
    
    using namespace std;
    
    class PlayContext
    {
    private:
    	string text;
    public:
    	string getText() { return text; }
    	void setText(string text_t) { text = text_t; }
    };
    
    class Expression
    {
    public:
    	virtual void Interpret(PlayContext* context)
    	{
    		if (context->getText().size() == 0)
    			return;
    		else
    		{
    			string playKey = context->getText().substr(0, 1);
    			context->setText(context->getText().substr(2));
    			int i = 0, j = 0;
    			string tmp = context->getText();
    			while (j<tmp.size() && tmp[j] != ' ')
    				j++;
    			double playValue = stod(tmp.substr(i, j - i + 1));
    			if(j < tmp.size())
    				context->setText(tmp.substr(j + 1));
    			else
    				context->setText("");
    			Excute(playKey[0], playValue);
    		}
    	}
    
    	virtual void Excute(char key, double value) = 0;
    };
    
    class Note :public Expression
    {
    public:
    	void Excute(char key, double value)
    	{
    		string note;
    		switch (key)
    		{
    		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 Excute(char key, double value)
    	{
    		string scale;
    		switch (int(value))
    		{
    		case 1:
    			scale = "低音";
    			break;
    		case 2:
    			scale = "中音";
    			break;
    		case 3:
    			scale = "高音";
    			break;
    		}
    		cout << scale << " ";
    	}
    };
    
    class Speed :public Expression
    {
    public:
    	void Excute(char key, double value)
    	{
    		string speed;
    		if (value < 500)
    			speed = "快速";
    		else if (value >= 1000)
    			speed = "慢速";
    		else
    			speed = "中速";
    		cout << speed << " ";
    	}
    };
    
    
    int main()
    {
    	PlayContext* context = new PlayContext();
    
    	cout << "上海滩:" << endl;
    
    	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 = nullptr;
     	while (context->getText().size())
    	{
    		string str = context->getText().substr(0, 1);
    		switch (str[0])
    		{
    		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;
    		}
    		expression->Interpret(context);
    	}
    	
    	
    
    	
    
    	system("pause");
    	return 0;
    }
    
  • 相关阅读:
    浏览网页的过程
    端口转发和端口映射
    代码审计入门之BlueCMS v1.6 sp1
    php伪协议总结
    phar反序列化
    iOS开发之GCD使用总结
    深入理解Android NDK日志符号化
    Android 开源项目源码解析之DynamicLoadApk 源码解析
    Gilt如何将微服务部署到AWS环境,介绍ION-Roller
    100分程序员的8个习惯
  • 原文地址:https://www.cnblogs.com/wfcg165/p/12060286.html
Copyright © 2011-2022 走看看