第一次个人编程作业(个人实现)

题目解析参考(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测试,好的想法和纠错,会重点关照哦。

posted @ 2020-02-17 16:52  水喵桑  阅读(129)  评论(1编辑  收藏