目录
正文
在之前的基础上进一步实现了全功能表达式求值。
- 已支持浮点数
- 已支持字符串的处理,前加一个"(类似lisp语法)
- 支持减号/负号,一符两用机制
- 支持所有算术运算符,包括**,//, %
- 支持全部7个比较运算符
- 支持与或非3个逻辑运算符
- 支持自定义数学函数(代码中预设sin函数作为示范)
- 支持外部提供的变量机制
- 支持外部设置函数(代码中预设isvar函数作为示范)
- 支持列表
- 字典的支持,体现在外部的变量中
- 结构清晰,易于扩展
- 具有实用性及学习性
与其说距离DSL只有一步之遥,不如说,DSL机制已经实现。因为可以任意扩展函数,而函数的内容
完全可以自行定义。
所以共享给大家,欢迎意见和建议。
完整的源代码
import math opDict={} def addoptr(ch, outLev, inLev, func, parmNum=2): obj= {\'name\':ch, \'out\':outLev, \'in\':inLev, \'func\':func, \'parmNum\':parmNum} opDict[ch]= obj def makeList(x): if isinstance(x[-2], list): x[-2].append(x[-1]) return x[-2].copy() else: ret= [] ret.append(x[-2]) ret.append(x[-1]) return ret addoptr(\'#\', 1, 1, None) addoptr(\'(\', 90, 2, None) addoptr(\')\', 2, None, None) addoptr(\'[\', 90, 2, None) addoptr(\']\', 2, 2, None) addoptr(\',\', 8, 9, makeList) addoptr(\'&\', 13, 14, lambda x: x[-1] and x[-2]) addoptr(\'and\', 13, 14, lambda x: x[-1] and x[-2]) addoptr(\'|\', 11, 12, lambda x: x[-1] or x[-2]) addoptr(\'or\', 11, 12, lambda x: x[-1] or x[-2]) addoptr(\'~\', 16, 17, lambda x: not x[-1],1) addoptr(\'not\', 16, 17, lambda x: not x[-1],1) addoptr(\'=\', 22, 23, lambda x: x[-1]==x[-2]) addoptr(\'>\', 22, 23, lambda x: x[-2]>x[-1]) addoptr(\'<\', 22, 23, lambda x: x[-2]<x[-1]) addoptr(\'>=\', 22, 23, lambda x: x[-2]>=x[-1]) addoptr(\'<=\', 22, 23, lambda x: x[-2]<=x[-1]) addoptr(\'!=\', 22, 23, lambda x: x[-2]!=x[-1]) addoptr(\'<>\', 22, 23, lambda x: x[-2]!=x[-1]) addoptr(\'in\', 22, 23, lambda x: x[-2] in x[-1]) addoptr(\'+\', 31, 32, lambda x: x[-2]+x[-1]) addoptr(\'-\', 31, 32, lambda x: x[-2]-x[-1]) addoptr(\'*\', 41, 42, lambda x: x[-2]*x[-1]) addoptr(\'/\', 41, 42, lambda x: x[-2]/x[-1]) addoptr(\'//\', 41, 42, lambda x: x[-2]//x[-1]) addoptr(\'%\', 41, 42, lambda x: x[-2]%x[-1]) addoptr(\'neg\', 51, 52, lambda x: -x[-1],1) addoptr(\'**\', 55, 56, lambda x: x[-2]**x[-1]) addoptr(\'sin\', 61, 62, lambda x: math.sin(x[-1]),1) alphabet= [chr(ord(\'a\')+x) for x in range(26)]+[chr(ord(\'A\')+x) for x in range(26)] # print(opChar) # print(opSep) # print(alphabet) def isfloat(str1): try: number = float(str1) except ValueError: return False return True class exprEngine: def __init__(this, isVar=None, getValue=None): this.opndStack=[] this.optrStack=[] this.isVar= isVar this.getValue= getValue # 这个状态,特为负号/减号这一特殊符的双含义号所设置 this.negState=0 # 内建函数 if isVar: addoptr(\'isvar\', 61, 62, lambda x: isVar(x[-1]),1) # 处理识别 this.oplen= len(max(opDict, key=lambda x:len(x))) this.opChar=[] for i in range(this.oplen): tmp=[x[0:i+1] for x in opDict if len(x)>=i+1] this.opChar.append(tmp) this.opSep= [x[0] for x in opDict if x[0] not in alphabet]+[\' \', \'\\t\'] print(this.oplen) print(this.opChar) print(this.opSep) def readWord(this, cond): cond= cond.strip() if cond==\'\': return \'\', \'#\' if cond[0] in this.opChar[0]: l1=this.oplen for i in range(this.oplen): if cond[:i+1] not in this.opChar[i]: l1= i break print(l1) if cond[:l1] in this.opChar[l1-1]: return cond[:l1], \'optr\' part= \'\' for ch in cond: if ch in this.opSep: break part+=ch return part, \'opnd\' def pushoptr(this, optr): # 对负号/减号的特殊处理 if optr==\'-\' and this.negState==0: # 这种情况,实际的含义是负号 optr= \'neg\' op= opDict[optr].copy() if len(this.optrStack)==0: this.optrStack.append(op) return opTop= this.optrStack[-1] if op[\'out\']> opTop[\'in\']: this.optrStack.append(op) elif op[\'out\']< opTop[\'in\']: this.popoptr() # 这里递归 this.pushoptr(optr) elif op[\'out\']== opTop[\'in\']: # 消括号对,简单弹出 this.optrStack.pop() this.negState=0 def popoptr(this): opTop= this.optrStack[-1] a= opTop[\'parmNum\'] if len(this.opndStack)<a: raise Exception(\'操作数不足,可能有语法错误!\') ret= opTop[\'func\'](this.opndStack[-a:]) this.opndStack= this.opndStack[:-a] this.opndStack.append(ret) this.optrStack.pop() def pushopnd(this, opnd): if opnd[0]==\'\"\': # 肯定是字符串 this.opndStack.append(opnd[1:]) elif this.isVar and this.isVar(opnd): this.opndStack.append(this.getValue(opnd)) else: if opnd.isdigit(): this.opndStack.append(int(opnd)) elif isfloat(opnd): this.opndStack.append(float(opnd)) else: this.opndStack.append(opnd) this.negState=1 def popopnd(this): if len(this.opndStack)==1: return this.opndStack[0] else: print(this.opndStack) print(this.optrStack) raise Exception(\'可能存在语法错误。\') def eval(this, cond): this.optrStack=[] this.opndStack=[] this.pushoptr(\'#\') while True: aword,kind= this.readWord(cond) print(aword, cond) cond= cond[len(aword):].strip() if kind==\'#\': this.pushoptr(\'#\') break elif kind==\'optr\': this.pushoptr(aword) else: if aword==\'\': raise Exception(\'操作数为空,肯定有哪里错了。\') this.pushopnd(aword) print(this.optrStack) print(this.opndStack) return this.popopnd() if __name__==\'__main__\': # print(opDict) a= exprEngine() # a.addInfo(\'水位\', \'低\') # b= a.eval(\'3 + 5 *2 = 13 and (3+5)*2=16 & 7-2 in [3,5,7] & 12>=15 or a in [a, b,c]\') # b= a.eval(\'sin(-1)<1 and 3+-5=-2\') # print(b) # b= a.eval(\'7*-3\') b= a.eval(\'3**3=27 and 19%5=4 and 21//6=3\') print(b)
以上就是python开发任意表达式求值全功能示例的详细内容,更多关于python表达式求值的资料请关注其它相关文章!
© 版权声明
THE END
暂无评论内容