Skip to content

Commit 87ff284

Browse files
committed
add interpreter
1 parent 4aa96cb commit 87ff284

File tree

12 files changed

+369
-4
lines changed

12 files changed

+369
-4
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242

4343
[命令模式 Command](doc/16-命令.md)
4444

45-
解释器模式 Interpreter
45+
[解释器模式 Interpreter](doc/17-解释器.md)
4646

4747
迭代器模式 Iterator
4848

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.29215.179
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "16_interpreter", "16_interpreter.vcxproj", "{3B612B32-7C16-4052-96F3-8749E7257C16}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|x64 = Debug|x64
11+
Debug|x86 = Debug|x86
12+
Release|x64 = Release|x64
13+
Release|x86 = Release|x86
14+
EndGlobalSection
15+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
16+
{3B612B32-7C16-4052-96F3-8749E7257C16}.Debug|x64.ActiveCfg = Debug|x64
17+
{3B612B32-7C16-4052-96F3-8749E7257C16}.Debug|x64.Build.0 = Debug|x64
18+
{3B612B32-7C16-4052-96F3-8749E7257C16}.Debug|x86.ActiveCfg = Debug|Win32
19+
{3B612B32-7C16-4052-96F3-8749E7257C16}.Debug|x86.Build.0 = Debug|Win32
20+
{3B612B32-7C16-4052-96F3-8749E7257C16}.Release|x64.ActiveCfg = Release|x64
21+
{3B612B32-7C16-4052-96F3-8749E7257C16}.Release|x64.Build.0 = Release|x64
22+
{3B612B32-7C16-4052-96F3-8749E7257C16}.Release|x86.ActiveCfg = Release|Win32
23+
{3B612B32-7C16-4052-96F3-8749E7257C16}.Release|x86.Build.0 = Release|Win32
24+
EndGlobalSection
25+
GlobalSection(SolutionProperties) = preSolution
26+
HideSolutionNode = FALSE
27+
EndGlobalSection
28+
GlobalSection(ExtensibilityGlobals) = postSolution
29+
SolutionGuid = {568A86D6-D74D-4BAB-BBF1-96D21721D8AD}
30+
EndGlobalSection
31+
EndGlobal

code/16_interpreter/client.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include "expression_type.h"
2+
3+
int main() {
4+
Context ctx;
5+
ctx.input("1 + 1")->interpret()->showOutput();
6+
ctx.input("9 - 5")->interpret()->showOutput();
7+
ctx.input("1 + 1 - 1")->interpret()->showOutput();
8+
}
9+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#include "expression_type.h"
2+
3+
4+
Context::Context() :m_input(""), m_result("") {
5+
6+
}
7+
8+
Context* Context::input(string input) {
9+
m_input = input;
10+
return this;
11+
}
12+
13+
Context* Context::interpret() {
14+
vector<string> list;
15+
splitString(m_input, list, " ");
16+
AbstractNode* nodes[4];
17+
for (int i = 0; i < list.size() - 2; i += 2) {
18+
nodes[0] = new ValueNode(stoi(list.at(i)));
19+
nodes[1] = new OperationNode(list.at(i + 1));
20+
nodes[2] = new ValueNode(stoi(list.at(i + 2)));
21+
nodes[3] = new SimpleExpression(nodes[0], nodes[1], nodes[2]);
22+
list[i + 2] = nodes[3]->interpret();
23+
}
24+
this->m_result = list.back();
25+
return this;
26+
}
27+
28+
string Context::output() {
29+
return m_result;
30+
}
31+
32+
void Context::showOutput() {
33+
cout << "Expression:" << this->m_input << " = " << output() << endl;
34+
}
35+
36+
void Context::splitString(const string& s, vector<string>& v, const string& c)
37+
{
38+
string::size_type pos1, pos2;
39+
pos2 = s.find(c);
40+
pos1 = 0;
41+
while (string::npos != pos2)
42+
{
43+
v.push_back(s.substr(pos1, pos2 - pos1));
44+
45+
pos1 = pos2 + c.size();
46+
pos2 = s.find(c, pos1);
47+
}
48+
if (pos1 != s.length())
49+
v.push_back(s.substr(pos1));
50+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#pragma once
2+
#include <string>
3+
#include <iostream>
4+
#include <vector>
5+
using namespace std;
6+
7+
class AbstractNode {
8+
public:
9+
virtual string interpret() = 0;
10+
};
11+
12+
class ValueNode : public AbstractNode {
13+
public:
14+
ValueNode() :m_val(0) {}
15+
ValueNode(int val) :m_val(val) {}
16+
string interpret() {
17+
return std::to_string(m_val);
18+
}
19+
20+
private:
21+
int m_val;
22+
};
23+
24+
class OperationNode : public AbstractNode {
25+
public:
26+
OperationNode() :m_oper("+") {}
27+
OperationNode(string val) :m_oper(val) {}
28+
string interpret() {
29+
return m_oper;
30+
}
31+
32+
private:
33+
string m_oper;
34+
};
35+
36+
class SimpleExpression :public AbstractNode {
37+
public:
38+
SimpleExpression() :m_leftNode(nullptr), m_operNode(nullptr), m_rightNode(nullptr) {}
39+
SimpleExpression(AbstractNode* left, AbstractNode* operNode, AbstractNode* right) :
40+
m_leftNode(left), m_operNode(operNode), m_rightNode(right) {}
41+
string interpret() {
42+
if (m_operNode && m_leftNode && m_rightNode) {
43+
string operation = m_operNode->interpret();
44+
string valL = m_leftNode->interpret();
45+
string valR = m_rightNode->interpret();
46+
if (operation == "+") {
47+
return std::to_string(stoi(valL) + stoi(valR));
48+
}
49+
else if (operation == "-") {
50+
return std::to_string((stoi(valL) - stoi(valR)));
51+
}
52+
}
53+
return "0";
54+
}
55+
private:
56+
AbstractNode* m_leftNode, * m_rightNode, * m_operNode;
57+
};
58+
59+
class Context {
60+
public:
61+
Context();
62+
Context* input(string expression);
63+
Context* interpret();
64+
string output();
65+
void showOutput();
66+
private:
67+
void splitString(const string& s, vector<string>& v, const string& c);
68+
string m_input;
69+
string m_result;
70+
};

code/16_interpreter/result.png

2.97 KB
Loading

doc/06-原型.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# 原型
22

3-
使用原型实例指定待创建对象的类型,并且通过复制这个原型阿里创建型的对象
3+
使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象
44

55
## UML
66

doc/16-命令.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,4 +181,6 @@ int main() {
181181
invoker->invoke();
182182
return 0;
183183
}
184-
```
184+
```
185+
186+
![result](../code/15_command/result.png)

doc/17-解释器.md

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# 解释器
2+
3+
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子
4+
5+
## UML
6+
7+
* AbstractExpression(抽象表达式): 声明了抽象的解释操作interpret(),是所有终结符表达式和非终结符表达式的基类
8+
* TerminalExpression(终结符表达式): 终结符是文法规则的组成元素中最基本的语言单位,不能再分解
9+
* NonterminalExpression(非终结符表达式): 实现了文法规则中非终结符的解释操作,因为非终结符表达式同样可以包含终结符表达式,所以终结符表达式可以是非终结符表达式的成员
10+
* Context(环境类): 即上下文类,用于存储解释器之外的一些全局信息
11+
12+
![figure16_interpreter](img/figure16_interpreter.png)
13+
14+
## 优缺点
15+
16+
* 优点
17+
* 易于改变和扩展文法,在解释器中使用类表示语言的文法规则,可以通过继承等机制类改变或扩展文法
18+
* 每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言
19+
* 如果要增加新的解释表达式,只需增加一个新的终结符表达式或非终结符表达式类,无需修改原有代码,符合开闭原则
20+
21+
* 缺点
22+
* 对于复杂文法难以维护
23+
* 执行效率低,因为解释器模式中有大量循环和递归调用
24+
25+
26+
## 使用场景
27+
28+
* 一些重复出现的问题可以用一种简单的语言进行表达
29+
* 一个语言的文法较为简单
30+
* 不考虑执行效率的问题时可以使用解释器模式
31+
32+
33+
## 用例
34+
35+
10进制的加减简单表达式:
36+
37+
* 1 + 1
38+
* 9 - 5
39+
* 1 + 1 - 1
40+
41+
42+
[code](../code/16_interpreter)
43+
44+
```c++
45+
// expression_type.h
46+
#pragma once
47+
#include <string>
48+
#include <iostream>
49+
#include <vector>
50+
using namespace std;
51+
52+
class AbstractNode {
53+
public:
54+
virtual string interpret() = 0;
55+
};
56+
57+
class ValueNode : public AbstractNode {
58+
public:
59+
ValueNode() :m_val(0) {}
60+
ValueNode(int val) :m_val(val) {}
61+
string interpret() {
62+
return std::to_string(m_val);
63+
}
64+
65+
private:
66+
int m_val;
67+
};
68+
69+
class OperationNode : public AbstractNode {
70+
public:
71+
OperationNode() :m_oper("+") {}
72+
OperationNode(string val) :m_oper(val) {}
73+
string interpret() {
74+
return m_oper;
75+
}
76+
77+
private:
78+
string m_oper;
79+
};
80+
81+
class SimpleExpression :public AbstractNode {
82+
public:
83+
SimpleExpression() :m_leftNode(nullptr), m_operNode(nullptr), m_rightNode(nullptr) {}
84+
SimpleExpression(AbstractNode* left, AbstractNode* operNode, AbstractNode* right) :
85+
m_leftNode(left), m_operNode(operNode), m_rightNode(right) {}
86+
string interpret() {
87+
if (m_operNode && m_leftNode && m_rightNode) {
88+
string operation = m_operNode->interpret();
89+
string valL = m_leftNode->interpret();
90+
string valR = m_rightNode->interpret();
91+
if (operation == "+") {
92+
return std::to_string(stoi(valL) + stoi(valR));
93+
}
94+
else if (operation == "-") {
95+
return std::to_string((stoi(valL) - stoi(valR)));
96+
}
97+
}
98+
return "0";
99+
}
100+
private:
101+
AbstractNode* m_leftNode, * m_rightNode, * m_operNode;
102+
};
103+
104+
class Context {
105+
public:
106+
Context();
107+
Context* input(string expression);
108+
Context* interpret();
109+
string output();
110+
void showOutput();
111+
private:
112+
void splitString(const string& s, vector<string>& v, const string& c);
113+
string m_input;
114+
string m_result;
115+
};
116+
```
117+
118+
```c++
119+
// expression_type.cpp
120+
#include "expression_type.h"
121+
122+
123+
Context::Context() :m_input(""), m_result("") {
124+
125+
}
126+
127+
Context* Context::input(string input) {
128+
m_input = input;
129+
return this;
130+
}
131+
132+
Context* Context::interpret() {
133+
vector<string> list;
134+
splitString(m_input, list, " ");
135+
AbstractNode* nodes[4];
136+
for (int i = 0; i < list.size() - 2; i += 2) {
137+
nodes[0] = new ValueNode(stoi(list.at(i)));
138+
nodes[1] = new OperationNode(list.at(i + 1));
139+
nodes[2] = new ValueNode(stoi(list.at(i + 2)));
140+
nodes[3] = new SimpleExpression(nodes[0], nodes[1], nodes[2]);
141+
list[i + 2] = nodes[3]->interpret();
142+
}
143+
this->m_result = list.back();
144+
return this;
145+
}
146+
147+
string Context::output() {
148+
return m_result;
149+
}
150+
151+
void Context::showOutput() {
152+
cout << "Expression:" << this->m_input << " = " << output() << endl;
153+
}
154+
155+
void Context::splitString(const string& s, vector<string>& v, const string& c)
156+
{
157+
string::size_type pos1, pos2;
158+
pos2 = s.find(c);
159+
pos1 = 0;
160+
while (string::npos != pos2)
161+
{
162+
v.push_back(s.substr(pos1, pos2 - pos1));
163+
164+
pos1 = pos2 + c.size();
165+
pos2 = s.find(c, pos1);
166+
}
167+
if (pos1 != s.length())
168+
v.push_back(s.substr(pos1));
169+
}
170+
```
171+
172+
```c++
173+
// client.cpp
174+
#include "expression_type.h"
175+
176+
int main() {
177+
Context ctx;
178+
ctx.input("1 + 1")->interpret()->showOutput();
179+
ctx.input("9 - 5")->interpret()->showOutput();
180+
ctx.input("1 + 1 - 1")->interpret()->showOutput();
181+
}
182+
```
183+
184+
![result](../code/16_interpreter/result.png)

doc/img/figure16_interpreter.png

11.8 KB
Loading

0 commit comments

Comments
 (0)