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

目录
  • 正文
  • 完整的源代码

正文

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

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

(0)

相关推荐

  • Python利用正则表达式从字符串提取数字

    目录 前言 利用正则表达式从字符串提取数字 附python正则表达式抽取文本中的时间日期 总结 前言 正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配. Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式. re 模块使 Python 语言拥有全部的正则表达式功能. 利用正则表达式从字符串提取数字 主要用到下面几个函数 (1)compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象.该对象拥有一系列方法用于正则

  • python数据操作之lambda表达式详情

    目录 1 前言 2 lambda 的特性 3 lambda 的一些用法 3.1 map 函数 3.2 reduce 函数 3.3 sorted 函数 3.4 filter 函数 4 总结 1 前言 在 Java 和 js 中,lambda箭头函数是十分常见的操作,这种表达方式在使用时非常的简便.在python的语法中也有应用场景,lambda是python预留的关键字,带有该关键字的都视为lambda, 其表现形式如下: # lambda 是表达式, arg 是用户输入参数 expression

  • python常用的正则表达式大全

    1.正则表达式 正则表达式是用来匹配与查找字符串的,从网上爬取数据自然或多或少会用到正则表达式,python的正则表达式要先引入re模块,正则表达式以r引导,例如: 其中**r“\d+”**正则表达式表示匹配连续的多个数值,search是re中的函数,从"abc123cd"字符串中搜索连续的数值,得到"123",返回一个匹配对象,结果如上. 2.字符串"\d"匹配0~9之间的一个数值 3.字符"+"重复前面一个匹配字符一次或者

  • python四则运算表达式求值示例详解

    目录 四则运算表达式求值 思路说明 算法步骤 代码 四则运算表达式求值 思路说明 使用双栈来实现——存放数值的栈 nums 与存放运算符的栈 ops. 算法步骤 对原始表达式字符串 exp 进行预处理, 将其转为一个元素对应一个数值或运算符的列表 explist. 遍历 explist , 每个元素依次压入对应的栈中. 每次压入后, 判断当前两栈顶是否可进行乘除运算.栈顶可进行乘除运算的充要条件是, ops 栈顶为<*> ,</> 之一, 且 nums 中的元素比 ops 中的元素

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

    目录 正文 完整的源代码 正文 在之前的基础上进一步实现了全功能表达式求值. 已支持浮点数 已支持字符串的处理,前加一个"(类似lisp语法) 支持减号/负号,一符两用机制 支持所有算术运算符,包括**,//, % 支持全部7个比较运算符 支持与或非3个逻辑运算符 支持自定义数学函数(代码中预设sin函数作为示范) 支持外部提供的变量机制 支持外部设置函数(代码中预设isvar函数作为示范) 支持列表 字典的支持,体现在外部的变量中 结构清晰,易于扩展 具有实用性及学习性 与其说距离DSL只有一

  • java实现任意四则运算表达式求值算法

    本文实例讲述了java实现任意四则运算表达式求值算法.分享给大家供大家参考.具体分析如下: 该程序用于计算任意四则运算表达式.如 4 * ( 10 + 2 ) + 1 的结果应该为 49. 算法说明: 1. 首先定义运算符优先级.我们用一个 Map<String, Map<String, String>> 来保存优先级表.这样我们就可以通过下面的方式来计算两个运算符的优先级了: /** * 查表得到op1和op2的优先级 * @param op1 运算符1 * @param op2

  • JS实现可针对算术表达式求值的计算器功能示例

    本文实例讲述了JS实现可针对算术表达式求值的计算器功能.分享给大家供大家参考,具体如下: HTML部分: <div> <div id="in"> <input name="in" type="text" class="clsin" id="input" value="" readonly="readonly" /> <inpu

  • PHP实现基于栈的后缀表达式求值功能

    本文实例讲述了PHP实现基于栈的后缀表达式求值功能.分享给大家供大家参考,具体如下: 后缀表达式概述 后缀表达式,指的是不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则). 实现代码: <?php class Stack{ public $stack; public $stack_top; public function __construct(){ $this->stack=array(); $this->stack_t

  • 数据结构课程设计-用栈实现表达式求值的方法详解

    1.需求分析设计一个程序,演示用算符优先法对算术表达式求值的过程.利用算符优先关系,实现对算术四则混合运算表达式的求值.(1)输入的形式:表达式,例如2*(3+4)     包含的运算符只能有'+' .'-' .'*' .'/' .'('. ')':(2)输出的形式:运算结果,例如2*(3+4)=14:(3)程序所能达到的功能:对表达式求值并输出 2.系统设计1.栈的抽象数据类型定义:ADT Stack{数据对象:D={ai|ai∈ElemSet,i=1,2,-,n,n≥0}数据关系:R1={<

  • C语言操作符进阶教程(表达式求值隐式类型转换方法)

    目录 结构体 表达式求值 隐式类型转换 意义: 方法 算术转换 操作符属性 结构体 结构体变量的声明需要在主函数之上或者主函数中声明,如果在主函数之下则会报错,而且c语言中的结构体不能直接进行强制转换,只有结构体指针才能进行强制转换. 涉及结构体的操作符这里讲两个:. (结构体访问操作符)-> () 首先写一段代码: int main() { struct Stu s = {"me",19,60}; prinft("%s %d %lf",s.who,s.age

  • Java栈的运用之中缀表达式求值详解

    目录 栈运用题:中缀表达式求值 题目详情 解题思路 实现代码 栈运用题:中缀表达式求值 题目详情 给定一个表达式,其中运算符仅包含 +,-,*,/(加 减 乘 整除),可能包含括号,请你求出表达式的最终值. 注意: 数据保证给定的表达式合法. 题目保证符号 - 只作为减号出现,不会作为负号出现,例如,-1+2,(2+2)*(-(1+1)+2) 之类表达式均不会出现. 题目保证表达式中所有数字均为正整数. 题目保证表达式在中间计算过程以及结果中,均不超过 231−1. 题目中的整除是指向 0 取整

  • Python获取任意xml节点值的方法

    本文实例讲述了Python获取任意xml节点值的方法.分享给大家供大家参考.具体实现方法如下: # -*- coding: utf-8 -*- import xml.dom.minidom ELEMENT_NODE = xml.dom.Node.ELEMENT_NODE class SimpleXmlGetter(object): def __init__(self, data): if type(data) == str: self.root = xml.dom.minidom.parse(d

  • C++利用链栈实现表达式求值

    本文实例为大家分享了C++利用链栈实现表达式求值的具体代码,供大家参考,具体内容如下 #include<iostream.h> typedef int Status; typedef char Cstack; #define OK 1 #define ERROR 0 typedef struct StackNode { Cstack data; struct StackNode *next; }StackNode,*LinkStack; Status InitStack(LinkStack &

随机推荐