PythonPyFn示例:具有两个或多个参数的parse函数
我正在用它来写一个简单的计算器。在阅读了这个示例之后(并没有完全理解它!),我决定稍微修改它以满足我的需要 以下是我的代码(大部分代码取自):PythonPyFn示例:具有两个或多个参数的parse函数,python,pyparsing,Python,Pyparsing,我正在用它来写一个简单的计算器。在阅读了这个示例之后(并没有完全理解它!),我决定稍微修改它以满足我的需要 以下是我的代码(大部分代码取自): def夏季(p1、p2): 返回p1+p2 类NumericStringParser(对象): ''' 大部分代码来自fourFn.py解析示例 ''' def推送优先(自身、strg、loc、toks): self.exprStack.append(toks[0]) def pushUMinus(自身、strg、loc、toks): 如果toks和to
def夏季(p1、p2):
返回p1+p2
类NumericStringParser(对象):
'''
大部分代码来自fourFn.py解析示例
'''
def推送优先(自身、strg、loc、toks):
self.exprStack.append(toks[0])
def pushUMinus(自身、strg、loc、toks):
如果toks和toks[0]='-':
self.exprStack.append('一元-'))
定义初始化(自):
"""
expop::“^”
multop::“*”|“/”
addop::“+”|“-”
整数::['+'|'-']'0'..'9'+
原子::π| E | real | fn'('expr')'|'('expr')'
因子::原子[expop因子]*
术语::因子[多顶因子]*
expr::term[addop term]*
"""
点=文字(“.”)
e=无案例横向(“e”)
fnumber=组合(单词(“+-”+nums,nums)+
可选(点+可选(字(nums)))+
可选(e+字(“+-”+nums,nums)))
ident=Word(字母,字母+nums+“$”)
加号=文字(“+”)
减号=文字(“-”)
mult=文字(“*”)
div=文字(“/”)
lpar=Literal(“”.suppress()
rpar=Literal(“”)。suppress()
逗号=文字(',')。抑制()
addop=正|负
multop=mult | div
expop=Literal(“^”)
pi=无案例横向(“pi”)
expr=Forward()
atom=((可选(“-+”之一)+
(
pi | e | fnumber | ident+lpar+expr+rpar | ident+lpar+expr+逗号+expr+rpar)(
自我介绍(第一)
|可选(一个(“-+”))+组(lpar+expr+rpar)
).setParseAction(self.pushumius)
#通过将指数定义为“原子[^factor]…”而不是
#“atom[^atom]…”,我们得到的是从右到左的指数,而不是从左到右的指数
#也就是说,2^3^2=2^(3^2),而不是(2^3)^2。
因子=正向()
因素
def summer(p1, p2):
return p1 + p2
class NumericStringParser(object):
'''
Most of this code comes from the fourFn.py pyparsing example
'''
def pushFirst(self, strg, loc, toks):
self.exprStack.append(toks[0])
def pushUMinus(self, strg, loc, toks):
if toks and toks[0] == '-':
self.exprStack.append('unary -')
def __init__(self):
"""
expop :: '^'
multop :: '*' | '/'
addop :: '+' | '-'
integer :: ['+' | '-'] '0'..'9'+
atom :: PI | E | real | fn '(' expr ')' | '(' expr ')'
factor :: atom [ expop factor ]*
term :: factor [ multop factor ]*
expr :: term [ addop term ]*
"""
point = Literal(".")
e = CaselessLiteral("E")
fnumber = Combine(Word("+-" + nums, nums) +
Optional(point + Optional(Word(nums))) +
Optional(e + Word("+-" + nums, nums)))
ident = Word(alphas, alphas + nums + "_$")
plus = Literal("+")
minus = Literal("-")
mult = Literal("*")
div = Literal("/")
lpar = Literal("(").suppress()
rpar = Literal(")").suppress()
comma = Literal(',').suppress()
addop = plus | minus
multop = mult | div
expop = Literal("^")
pi = CaselessLiteral("PI")
expr = Forward()
atom = ((Optional(oneOf("- +")) +
(
pi | e | fnumber | ident + lpar + expr + rpar | ident + lpar + expr + comma + expr + rpar).setParseAction(
self.pushFirst))
| Optional(oneOf("- +")) + Group(lpar + expr + rpar)
).setParseAction(self.pushUMinus)
# by defining exponentiation as "atom [ ^ factor ]..." instead of
# "atom [ ^ atom ]...", we get right-to-left exponents, instead of left-to-right
# that is, 2^3^2 = 2^(3^2), not (2^3)^2.
factor = Forward()
factor << atom + ZeroOrMore((expop + factor).setParseAction(self.pushFirst))
term = factor + ZeroOrMore((multop + factor).setParseAction(self.pushFirst))
expr << term + ZeroOrMore((addop + term).setParseAction(self.pushFirst))
# addop_term = ( addop + term ).setParseAction( self.pushFirst )
# general_term = term + ZeroOrMore( addop_term ) | OneOrMore( addop_term)
# expr << general_term
self.bnf = expr
# map operator symbols to corresponding arithmetic operations
epsilon = 1e-12
self.opn = {"+": operator.add,
"-": operator.sub,
"*": operator.mul,
"/": operator.truediv,
"^": operator.pow}
self.fn = {"sin": math.sin,
"cos": math.cos,
"tan": math.tan,
"abs": abs,
"trunc": lambda a: int(a),
"round": round,
"sgn": lambda a: abs(a) > epsilon and cmp(a, 0) or 0}
self.fn2 = {"sum": summer}
def evaluateStack(self, s):
op = s.pop()
if op == 'unary -':
res = self.evaluateStack(s)
return -res
if op in "+-*/^":
op2 = self.evaluateStack(s)
op1 = self.evaluateStack(s)
res = self.opn[op](op1, op2)
return res
elif op == "PI":
return math.pi # 3.1415926535
elif op == "E":
return math.e # 2.718281828
elif op in self.fn:
return self.fn[op](self.evaluateStack(s))
elif op in self.fn2:
op2 = self.evaluateStack(s)
op1 = self.evaluateStack(s)
return self.fn2[op](op1, op2)
elif op[0].isalpha():
return 0
else:
return float(op)
def eval(self, num_string, parseAll=True):
self.exprStack = []
results = self.bnf.parseString(num_string, parseAll)
val = self.evaluateStack(self.exprStack[:])
return val
n = NumericStringParser()
print(n.eval('(4.0*sum(3,3))^1'))