python开发任意表达式求值全功能示例

2022-07-12 13:49:50
目录
正文完整的源代码

正文

在之前的基础上进一步实现了全功能表达式求值。

    已支持浮点数已支持字符串的处理,前加一个"(类似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表达式求值的资料请关注易采站长站其它相关文章!