第1篇:常量折叠

  • 前言
  • 开始
  • 先看_cal函数
  • 参数
  • 先看前4行
  • 再往后看
  • 再继续看
  • 后面是
  • 最后为
  • 总结一下
  • 继续看part1函数
  • 参数
  • 先看前2行
  • 再往后看
  • 总结一下
  • 作者


前言

我做过一个编程语言:mylang

开始

做编程语言最基础的就是常量折叠部分
那么先看一下mylang中的常量折叠部分

def _cal(t,a,b,inter):
    A = copy.deepcopy(a)
    B = copy.deepcopy(b)
    _a = comp(a)
    _b = comp(b)
    if(_a[0] != 'error'):
        a = _a[0]
    else:
        return _a
    if(_b[0] != 'error'):
        b = _b[0]
    else:
        return _b
    	
    if(isinstance(a,str) and a.startswith('{')):
        a = comp(a)[0]
    if(isinstance(a,str) and a.startswith('{')):
        b = comp(b)[0]
    t = t[1:]
    result = None
    try:
        if(t == '+'):result = a + b
        elif(t == '-'):result = a - b
        elif(t == '/'):
            if(b != 0):
                result = a / b
            else:
                return ['error','ZeroDivisionError:division by zero']
        elif(t == '*'):result = int(a * b)
        elif(t == '<'):result = int(a < b)
        elif(t == '<='):result = int(a <= b)
        elif(t == '='):result = int(a == b)
        elif(t == '>='):result = int(a >= b)
        elif(t == '>'):result = int(a > b)
        elif(t == '&'):result = int(a and b)
        elif(t == '|'):result = int(a or b)
        elif(t == '!'):result = int(not a)
        elif(t == '^'):result = int(a ** b)
        elif(t == '%'):result = int(a % b)
        else:return ['error','OperatorError:undefined operator']
        if(isinstance(result,list)):
            string = str(result)
            string = string.replace('[','{')
            string = string.replace(']','}')
            return [string]
        elif(inter and isinstance(result,mytype.stack)):
            return ['stack' + str(result._stack)]
        elif(inter and isinstance(result,mytype.queue)):
            return ['queue' + str(result._queue)]
        else:
            return [result]
    except:
        return ['error','TypeError: can\'t concatenate {0} to {1} with operater \'{2}\''.format(comp(A,inter=True)[0],comp(B,inter=True)[0],t)]
def part1(string,inter):
    if(string.count('(') != string.count(')')):
        return ['error','EOLError:EOL while scanning']
    string += ' '
    ls = []
    buf = ''
    flag = 0
    qmflag = False
    if(len(string.split(' ')) != 3):
        for i in string:
            if(i == '('):
                flag += 1
            if(i == ')'):
                flag -= 1
            if(i == '"'):
                if(qmflag):
                    qmflag = False
                    flag -= 1
                else:
                    qmflag = True
                    flag += 1
            if((not flag) and i == ' '):
                ls.append(buf.strip())
                buf = ''
            buf += i
        if(len(ls) != 3 and ls[0] != '@!'):
            return ['error','OperatingError:wrong length']
        if(ls[0].strip() != '@!'):
            t,a,b = ls
        else:
            t,a = ls
            b = None
    else:
        t,a,b = string.split(' ')
    if('(' in a):
        a = comp(a[1:-1])
        if(a[0] == 'error'):
            return [a]
    if('(' in b):
        b = comp(b[1:-1])
        if(b[0] == 'error'):
            return b
    if(isinstance(a,list)):
        if(a[0] == 'error'):
            return a
        a = a[0]
    if(isinstance(b,list)):
        if(b[0] == 'error'):
            return b
        b = b[0]
    return _cal(t,a,b,inter)

先看_cal函数

def _cal(t,a,b,inter):
    A = copy.deepcopy(a)
    B = copy.deepcopy(b)
    _a = comp(a)
    _b = comp(b)
    if(_a[0] != 'error'):
        a = _a[0]
    else:
        return _a
    if(_b[0] != 'error'):
        b = _b[0]
    else:
        return _b
    if(isinstance(a,str) and a.startswith('{')):
        a = comp(a)[0]
    if(isinstance(a,str) and a.startswith('{')):
        b = comp(b)[0]
    t = t[1:]
    result = None
    try:
        if(t == '+'):result = a + b
        elif(t == '-'):result = a - b
        elif(t == '/'):
            if(b != 0):
                result = a / b
            else:
                return ['error','ZeroDivisionError:division by zero']
        elif(t == '*'):result = int(a * b)
        elif(t == '<'):result = int(a < b)
        elif(t == '<='):result = int(a <= b)
        elif(t == '='):result = int(a == b)
        elif(t == '>='):result = int(a >= b)
        elif(t == '>'):result = int(a > b)
        elif(t == '&'):result = int(a and b)
        elif(t == '|'):result = int(a or b)
        elif(t == '!'):result = int(not a)
        elif(t == '^'):result = int(a ** b)
        elif(t == '%'):result = int(a % b)
        else:return ['error','OperatorError:undefined operator']
        if(isinstance(result,list)):
            string = str(result)
            string = string.replace('[','{')
            string = string.replace(']','}')
            return [string]
        elif(inter and isinstance(result,mytype.stack)):
            return ['stack' + str(result._stack)]
        elif(inter and isinstance(result,mytype.queue)):
            return ['queue' + str(result._queue)]
        else:
            return [result]
    except:
        return ['error','TypeError: can\'t concatenate {0} to {1} with operater \'{2}\''.format(comp(A,inter=True)[0],comp(B,inter=True)[0],t)]
参数

其中参数t,a,b,inter,其中t是运算符,a是第一个参数,b是第二个参数,inter是表示是否为交互模式的布尔值

先看前4行
A = copy.deepcopy(a)
    B = copy.deepcopy(b)
    _a = comp(a)
    _b = comp(b)

其中A和B是原值的备份,_a和_b是a和b所代表的值

再往后看
if(_a[0] != 'error'):
        a = _a[0]
    else:
        return _a
    if(_b[0] != 'error'):
        b = _b[0]
    else:
        return _b

此处是为了防止a和b所代表的值有误

再继续看
if(isinstance(a,str) and a.startswith('{')):
        a = comp(a)[0]
    if(isinstance(a,str) and a.startswith('{')):
        b = comp(b)[0]

此处特别处理列表

后面是
t = t[1:]
    result = None

其中result是结果,t = t[1:]是为了如下原因:

常量折叠语法: @[t] [a] [b]
传入的t@[t]部分
所以t = t[1:]是为了将@去掉

最后为
try:
        if(t == '+'):result = a + b
        elif(t == '-'):result = a - b
        elif(t == '/'):
            if(b != 0):
                result = a / b
            else:
                return ['error','ZeroDivisionError:division by zero']
        elif(t == '*'):result = int(a * b)
        elif(t == '<'):result = int(a < b)
        elif(t == '<='):result = int(a <= b)
        elif(t == '='):result = int(a == b)
        elif(t == '>='):result = int(a >= b)
        elif(t == '>'):result = int(a > b)
        elif(t == '&'):result = int(a and b)
        elif(t == '|'):result = int(a or b)
        elif(t == '!'):result = int(not a)
        elif(t == '^'):result = int(a ** b)
        elif(t == '%'):result = int(a % b)
        else:return ['error','OperatorError:undefined operator']
        if(isinstance(result,list)):
            string = str(result)
            string = string.replace('[','{')
            string = string.replace(']','}')
            return [string]
        elif(inter and isinstance(result,mytype.stack)):
            return ['stack' + str(result._stack)]
        elif(inter and isinstance(result,mytype.queue)):
            return ['queue' + str(result._queue)]
        else:
            return [result]
    except:
        return ['error','TypeError: can\'t concatenate {0} to {1} with operater \'{2}\''.format(comp(A,inter=True)[0],comp(B,inter=True)[0],t)]

此处就是在进行运算

总结一下


Created with Raphaël 2.2.0 开始 对两个参数进行转化 检查两个参数的正确性 对特殊值进行特判 进行运算 结束 报错 yes no



继续看part1函数

def part1(string,inter):
    if(string.count('(') != string.count(')')):
        return ['error','EOLError:EOL while scanning']
    string += ' '
    ls = []
    buf = ''
    flag = 0
    qmflag = False
    if(len(string.split(' ')) != 3):
        for i in string:
            if(i == '('):
                flag += 1
            if(i == ')'):
                flag -= 1
            if(i == '"'):
                if(qmflag):
                    qmflag = False
                    flag -= 1
                else:
                    qmflag = True
                    flag += 1
            if((not flag) and i == ' '):
                ls.append(buf.strip())
                buf = ''
            buf += i
        if(len(ls) != 3 and ls[0] != '@!'):
            return ['error','OperatingError:wrong length']
        if(ls[0].strip() != '@!'):
            t,a,b = ls
        else:
            t,a = ls
            b = None
    else:
        t,a,b = string.split(' ')
    if('(' in a):
        a = comp(a[1:-1])
        if(a[0] == 'error'):
            return [a]
    if('(' in b):
        b = comp(b[1:-1])
        if(b[0] == 'error'):
            return b
    if(isinstance(a,list)):
        if(a[0] == 'error'):
            return a
        a = a[0]
    if(isinstance(b,list)):
        if(b[0] == 'error'):
            return b
        b = b[0]
    return _cal(t,a,b,inter)
参数

参数中string为表达式,inter是表示是否为交互模式的布尔值

先看前2行
if(string.count('(') != string.count(')')):
        return ['error','EOLError:EOL while scanning']

这是为了判断表达式嵌套是否正确

再往后看
string += ' '
    ls = []
    buf = ''
    flag = 0
    qmflag = False
    if(len(string.split(' ')) != 3):
        for i in string:
            if(i == '('):
                flag += 1
            if(i == ')'):
                flag -= 1
            if(i == '"'):
                if(qmflag):
                    qmflag = False
                    flag -= 1
                else:
                    qmflag = True
                    flag += 1
            if((not flag) and i == ' '):
                ls.append(buf.strip())
                buf = ''
            buf += i
        if(len(ls) != 3 and ls[0] != '@!'):
            return ['error','OperatingError:wrong length']
        if(ls[0].strip() != '@!'):
            t,a,b = ls
        else:
            t,a = ls
            b = None
    else:
        t,a,b = string.split(' ')

这里是为了分开操作符(operator,这里用t(token)表示)和两个参数(a和b)
先看4个变量

ls:分解后的结果
buf:不完整的t/a/b(尚未完全分段的)
flag:嵌套的"()数量
qmflag:记录是否为""内的部分

继续看主体部分

if(len(string.split(' ')) != 3):
		# ......
    else:
        t,a,b = string.split(' ')

此处处理是否有嵌套的表达式
接着看主体部分

for i in string:
            if(i == '('):
                flag += 1
            if(i == ')'):
                flag -= 1
            if(i == '"'):
                if(qmflag):
                    qmflag = False
                    flag -= 1
                else:
                    qmflag = True
                    flag += 1
            if((not flag) and i == ' '):
                ls.append(buf.strip())
                buf = ''
            buf += i

此处为了分开t,a,b三个部分
接着是

if(len(ls) != 3 and ls[0] != '@!'):
            return ['error','OperatingError:wrong length']
        if(ls[0].strip() != '@!'):
            t,a,b = ls
        else:
            t,a = ls
            b = None

此处是将ls分成t,a,b三部分

if('(' in a):
        a = comp(a[1:-1])
        if(a[0] == 'error'):
            return [a]
    if('(' in b):
        b = comp(b[1:-1])
        if(b[0] == 'error'):
            return b
    if(isinstance(a,list)):
        if(a[0] == 'error'):
            return a
        a = a[0]
    if(isinstance(b,list)):
        if(b[0] == 'error'):
            return b
        b = b[0]

转化a和b,避错

return _cal(t,a,b,inter)

这里进行计算

总结一下


Created with Raphaël 2.2.0 开始 检查代码的表达式嵌套 分成operator,a,b三部分 转化a和b a和b的正确性 运行 结束 报错 yes no