题目解析参考(python实现)
C语言版本请出门左转另一位助教博客
题目要求利用中文语法实现简单的中文语法编译,满足以下语法:
- 变量定义:整数 (变量名) 等于 (数字)
- 运算(加法):(变量名) 增加 (数字)
- 运算(减法):(变量名) 减少 (数字)
- 输出:看看 (变量名) or 看看 “(字符串内容)”
- 选择:如果 (判断语句) 则 (操作语句) 否则 (操作语句)
若否则后没有任何操作使用(无)来进行填充(参考样例2)
题目分析
下列语法为伪代码或类c语法:
变量定义:整数 钱包 等于 二 相当于 int wallet=2
运算(加法):钱包 增加 二 相当于 wallet+=2
运算(减法):钱包 减少 一 相当于 wallet-=1
输出:看看 钱包 相当于 print(wallet) 看看 "你好,世界" 相当于 print("你好,世界")
选择:如果 钱包 大于 二 则 看看 钱包 否则 看看 “我好穷” 相当于
if wallet > 2 print(wallet)
else print("我好穷")
对于这类语法可以认为是由关键词和变量的处理组成的。
我们做个简单的归类:
整数
看看
如果
无
对于这个可以用枚举类来做:
class Keyword(Enum):
IF = '如果 '
EMPTY = '空'
INT = '整数 '
LOOK = '看看 '
同理我们定义一下比较运算符,==,>,<,!=:
class Comparison(Enum):
Greater = '大于'
Less = '小于'
Equal = '等于'
Nequal = '不等于'
定义一下运算符
class Action(Enum):
ASSIGN = ' 等于 '
ADD = ' 增加 '
DESC = ' 减少 '
定义一下错误类型:
class Error(Enum):
INDEXERROR = '语法错误'
OVERFLOWERROR = '溢出错误'
ATTRIBUTEERROR = '属性错误'
UNKNOWERROR = '未知错误'
1.为什么用枚举类,用枚举类的好处都有啥?谁说对了分就给他!
Line类
定义一个Line类,来分解语句的关键词,变量,动作,同时要防止变量名出现(如果,看看)这类的关键词。
class Line:
base_num = {'零': 0, '一': 1, '二': 2, '三': 3, '四': 4,
'五': 5, '六': 6, '七': 7, '八': 8, '九': 9, '十': 10}
def __init__(self, s: str):
self.__key = None
self.__action = None
self.__var = None
self.__value = None
self.__judge_sen = None
self.__choice_one = None
self.__choice_two = None
s = self.__set_key(s)
if self.__key == Keyword.IF:
self.__if_deal(s)
else:
self.__set_action(s)
self.__set_value(s)
def __set_key(self, s: str):
```
提取key
```
for v in Keyword:
if s.find(v.value) == 0:
self.__key = v
s = self.__cut(s, v)
break
return s
def __set_action(self, s: str):
```
提取运算符
```
for v in Action:
if s.find(v.value) != -1:
self.__action = v
mat = re.match(r'(.*)'+v.value+r'(.*)', s)
self.__var = mat.group(1)
self.__value = mat.group(2)
if self.__value not in self.base_num.keys():
self.__key = Error.OVERFLOWERROR
break
def __set_value(self, s: str):
```
提取变量和值
```
if self.__action is None and self.__key == Keyword.LOOK:
if s[0] == '“' and s[-1] == '”':
self.__value = s[1:-1]
elif s[0] != '“' and s[-1] != '”':
self.__var = s
else:
self.__key = Error.INDEXERROR
elif self.__action is None and self.__key is None:
self.__key = Error.INDEXERROR
elif self.__key == Keyword.INT and self.__action == None:
self.__action = Action.ASSIGN
self.__var = s
def __cut(self, s: str, key: Keyword):
if key.value == '如果 ':
s = s.lstrip(key.value)
else:
s = s.replace(key.value, '')
return s
def __cut_blank(self, s: str):
s = s.replace(' ', '')
return s
def __if_deal(self, s: str):
```
处理“如果”的逻辑
```
ma = re.match(r'(.*?) 则 (.*) 否则 (.*)', s)
self.__judge_sen = ma.group(1)
self.__choice_one = Line(ma.group(2))
self.__choice_two = Line(ma.group(3))
def get_key(self):
return self.__key
def get_action(self):
return self.__action
def get_var(self):
return self.__var
def get_value(self):
return self.__value
def get_judge_sen(self):
return self.__judge_sen
def get_choice_true(self):
return self.__choice_one
def get_choice_false(self):
return self.__choice_two
2.为什么不用公有属性,而采用私有属性,提供公有方法来访问?谁说对了分就给他!
System类
class System:
print_num = {0: '零', 1: '一', 2: '二', 3: '三', 4: '四',
5: '五', 6: '六', 7: '七', 8: '八', 9: '九', 10: '十'}
def __init__(self):
self.__value = {}
def sinput(self):
```
输入工具
```
s = input('>')
if s == '退出':
return s
li = Line(s)
return li
def sprient(self, s):
```
输出工具
```
if isinstance(s,int) is True:
s = self.print_num[s]
print(s)
def info(self, err: Error):
```
报错工具
```
print("错误:" + err.value)
def run(self):
while(True):
line = self.sinput()
if line == '退出':
return 0
res = self.__run_line(line)
if res != 0:
self.info(res)
break
def __run_line(self, line: Line):
```
语句处理工具
```
if line.get_key() in Error:
return line.get_key()
elif line.get_key() in Keyword:
res = self.__run_key(line)
return res
elif line.get_action() in Action:
res = self.__run_action(line)
return res
else:
return Error.UNKNOWERROR
def __run_key(self, line: Line):
if line.get_key() == Keyword.INT:
if line.get_value() is not None:
self.__value[line.get_var()] = line.base_num[line.get_value()]
else:
self.__value[line.get_var()] = 0
res = 0
elif line.get_key() == Keyword.LOOK:
if line.get_var() is not None and line.get_var() in self.__value.keys():
self.sprient(self.__value[line.get_var()])
elif line.get_value() is not None:
self.sprient(line.get_value())
else:
return Error.ATTRIBUTEERROR
res = 0
elif line.get_key() == Keyword.IF:
res = self.__run_if(line)
return res
def __run_if(self,line:Line):
ma = re.match(r'(.*) (.*) (.*)',line.get_judge_sen())
com = ma.group(2)
va = ma.group(1)
num = ma.group(3)
if va in self.__value.keys():
if num not in self.__value.keys():
va2 = line.base_num[num]
else:
va2 = self.__value[num]
if com == Comparison.Equal.value:
if self.__value[va] == va2:
res = self.__run_line(line.get_choice_true())
else:
res = self.__run_line(line.get_choice_false())
elif com == Comparison.Nequal.value:
if self.__value[va] != va2:
res = self.__run_line(line.get_choice_true())
else:
res = self.__run_line(line.get_choice_false())
elif com == Comparison.Greater.value:
if self.__value[va] > va2:
res = self.__run_line(line.get_choice_true())
else:
res = self.__run_line(line.get_choice_false())
elif com == Comparison.Less.value:
if self.__value[va] < va2:
res = self.__run_line(line.get_choice_true())
else:
res = self.__run_line(line.get_choice_false())
else:
return Error.INDEXERROR
else:
return Error.ATTRIBUTEERROR
return res
def __run_action(self, line: Line):
if line.get_action() == Action.ASSIGN:
if line.get_var() in self.__value.keys():
self.__value[line.get_var()] = line.base_num[line.get_value()]
else:
return Error.ATTRIBUTEERROR
elif line.get_action() == Action.ADD:
if line.get_var() in self.__value.keys():
self.__value[line.get_var()] += line.base_num[line.get_value()]
if self.__value[line.get_var()] > 10:
return Error.OVERFLOWERROR
else:
return Error.ATTRIBUTEERROR
elif line.get_action() == Action.DESC:
if line.get_var() in self.__value.keys():
self.__value[line.get_var()] -= line.base_num[line.get_value()]
if self.__value[line.get_var()] < 0:
return Error.OVERFLOWERROR
else:
return Error.ATTRIBUTEERROR
return 0
完整代码
# coding = utf-8
from enum import Enum
import re
class Keyword(Enum):
IF = '如果 '
EMPTY = '空'
INT = '整数 '
LOOK = '看看 '
class Comparison(Enum):
Greater = '大于'
Less = '小于'
Equal = '等于'
Nequal = '不等于'
class Action(Enum):
ASSIGN = ' 等于 '
ADD = ' 增加 '
DESC = ' 减少 '
class Error(Enum):
INDEXERROR = '语法错误'
OVERFLOWERROR = '溢出错误'
ATTRIBUTEERROR = '属性错误'
UNKNOWERROR = '未知错误'
class Line:
base_num = {'零': 0, '一': 1, '二': 2, '三': 3, '四': 4,
'五': 5, '六': 6, '七': 7, '八': 8, '九': 9, '十': 10}
def __init__(self, s: str):
self.__key = None
self.__action = None
self.__var = None
self.__value = None
self.__judge_sen = None
self.__choice_one = None
self.__choice_two = None
s = self.__set_key(s)
if self.__key == Keyword.IF:
self.__if_deal(s)
else:
self.__set_action(s)
self.__set_value(s)
def __set_key(self, s: str):
for v in Keyword:
if s.find(v.value) == 0:
self.__key = v
s = self.__cut(s, v)
break
return s
def __set_action(self, s: str):
for v in Action:
if s.find(v.value) != -1:
self.__action = v
mat = re.match(r'(.*)'+v.value+r'(.*)', s)
self.__var = mat.group(1)
self.__value = mat.group(2)
if self.__value not in self.base_num.keys():
self.__key = Error.OVERFLOWERROR
break
def __set_value(self, s: str):
if self.__action is None and self.__key == Keyword.LOOK:
if s[0] == '“' and s[-1] == '”':
self.__value = s[1:-1]
elif s[0] != '“' and s[-1] != '”':
self.__var = s
else:
self.__key = Error.INDEXERROR
elif self.__action is None and self.__key is None:
self.__key = Error.INDEXERROR
elif self.__key == Keyword.INT and self.__action == None:
self.__action = Action.ASSIGN
self.__var = s
def __cut(self, s: str, key: Keyword):
if key.value == '如果 ':
s = s.lstrip(key.value)
else:
s = s.replace(key.value, '')
return s
def __cut_blank(self, s: str):
s = s.replace(' ', '')
return s
def __if_deal(self, s: str):
ma = re.match(r'(.*?) 则 (.*) 否则 (.*)', s)
self.__judge_sen = ma.group(1)
self.__choice_one = Line(ma.group(2))
self.__choice_two = Line(ma.group(3))
def get_key(self):
return self.__key
def get_action(self):
return self.__action
def get_var(self):
return self.__var
def get_value(self):
return self.__value
def get_judge_sen(self):
return self.__judge_sen
def get_choice_true(self):
return self.__choice_one
def get_choice_false(self):
return self.__choice_two
class System:
print_num = {0: '零', 1: '一', 2: '二', 3: '三', 4: '四',
5: '五', 6: '六', 7: '七', 8: '八', 9: '九', 10: '十'}
def __init__(self):
self.__value = {}
def sinput(self):
s = input('>')
if s == '退出':
return s
li = Line(s)
return li
def sprient(self, s):
if isinstance(s,int) is True:
s = self.print_num[s]
print(s)
def info(self, err: Error):
print("错误:" + err.value)
def run(self):
while(True):
line = self.sinput()
if line == '退出':
return 0
res = self.__run_line(line)
if res != 0:
self.info(res)
break
def __run_line(self, line: Line):
if line.get_key() in Error:
return line.get_key()
elif line.get_key() in Keyword:
res = self.__run_key(line)
return res
elif line.get_action() in Action:
res = self.__run_action(line)
return res
else:
return Error.UNKNOWERROR
def __run_key(self, line: Line):
if line.get_key() == Keyword.INT:
if line.get_value() is not None:
self.__value[line.get_var()] = line.base_num[line.get_value()]
else:
self.__value[line.get_var()] = 0
res = 0
elif line.get_key() == Keyword.LOOK:
if line.get_var() is not None and line.get_var() in self.__value.keys():
self.sprient(self.__value[line.get_var()])
elif line.get_value() is not None:
self.sprient(line.get_value())
else:
return Error.ATTRIBUTEERROR
res = 0
elif line.get_key() == Keyword.IF:
res = self.__run_if(line)
return res
def __run_if(self,line:Line):
ma = re.match(r'(.*) (.*) (.*)',line.get_judge_sen())
com = ma.group(2)
va = ma.group(1)
num = ma.group(3)
if va in self.__value.keys():
if num not in self.__value.keys():
va2 = line.base_num[num]
else:
va2 = self.__value[num]
if com == Comparison.Equal.value:
if self.__value[va] == va2:
res = self.__run_line(line.get_choice_true())
else:
res = self.__run_line(line.get_choice_false())
elif com == Comparison.Nequal.value:
if self.__value[va] != va2:
res = self.__run_line(line.get_choice_true())
else:
res = self.__run_line(line.get_choice_false())
elif com == Comparison.Greater.value:
if self.__value[va] > va2:
res = self.__run_line(line.get_choice_true())
else:
res = self.__run_line(line.get_choice_false())
elif com == Comparison.Less.value:
if self.__value[va] < va2:
res = self.__run_line(line.get_choice_true())
else:
res = self.__run_line(line.get_choice_false())
else:
return Error.INDEXERROR
else:
return Error.ATTRIBUTEERROR
return res
def __run_action(self, line: Line):
if line.get_action() == Action.ASSIGN:
if line.get_var() in self.__value.keys():
self.__value[line.get_var()] = line.base_num[line.get_value()]
else:
return Error.ATTRIBUTEERROR
elif line.get_action() == Action.ADD:
if line.get_var() in self.__value.keys():
self.__value[line.get_var()] += line.base_num[line.get_value()]
if self.__value[line.get_var()] > 10:
return Error.OVERFLOWERROR
else:
return Error.ATTRIBUTEERROR
elif line.get_action() == Action.DESC:
if line.get_var() in self.__value.keys():
self.__value[line.get_var()] -= line.base_num[line.get_value()]
if self.__value[line.get_var()] < 0:
return Error.OVERFLOWERROR
else:
return Error.ATTRIBUTEERROR
return 0
if __name__ == '__main__':
sys = System()
sys.run()
3.可以讨论一下代码的规范和结构对于团队项目有什么好处?
结
代码的某些实现方法为了理解写的比较刻意,仅供参考,上面加粗的可以讨论,代码后续会放到github上,欢迎进行bug测试,好的想法和纠错,会重点关照哦。