網(wǎng)站首頁 編程語言 正文
正文
在之前的基礎(chǔ)上進一步實現(xiàn)了全功能表達式求值。
- 已支持浮點數(shù)
- 已支持字符串的處理,前加一個"(類似lisp語法)
- 支持減號/負號,一符兩用機制
- 支持所有算術(shù)運算符,包括**,//, %
- 支持全部7個比較運算符
- 支持與或非3個邏輯運算符
- 支持自定義數(shù)學(xué)函數(shù)(代碼中預(yù)設(shè)sin函數(shù)作為示范)
- 支持外部提供的變量機制
- 支持外部設(shè)置函數(shù)(代碼中預(yù)設(shè)isvar函數(shù)作為示范)
- 支持列表
- 字典的支持,體現(xiàn)在外部的變量中
- 結(jié)構(gòu)清晰,易于擴展
- 具有實用性及學(xué)習(xí)性
與其說距離DSL只有一步之遙,不如說,DSL機制已經(jīng)實現(xiàn)。因為可以任意擴展函數(shù),而函數(shù)的內(nèi)容
完全可以自行定義。
所以共享給大家,歡迎意見和建議。
完整的源代碼
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
# 這個狀態(tài),特為負號/減號這一特殊符的雙含義號所設(shè)置
this.negState=0
# 內(nèi)建函數(shù)
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('操作數(shù)不足,可能有語法錯誤!')
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('操作數(shù)為空,肯定有哪里錯了。')
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)
原文鏈接:https://blog.csdn.net/xiaorang/article/details/109275883
相關(guān)推薦
- 2022-04-21 Android自定義View實現(xiàn)標(biāo)簽流效果_Android
- 2023-08-01 el-date-picker組件中渲染多余文字
- 2022-08-25 C語言淺析指針的使用_C 語言
- 2022-07-01 使用python實現(xiàn)簡單去水印功能_python
- 2022-09-21 Flask深入了解Jinja2引擎的用法_python
- 2022-12-24 Golang實現(xiàn)組合模式和裝飾模式實例詳解_Golang
- 2022-11-23 .NET?SkiaSharp?生成二維碼驗證碼及指定區(qū)域截取方法實現(xiàn)_實用技巧
- 2022-12-04 C++11中內(nèi)聯(lián)函數(shù)(inline)用法實例_C 語言
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支