Не могу не похвастаться, что все заработало как надо. Еще интерфейс на Qt запилю, и тогда вообще будет сказка

Спасибо вам огромное, дорогой
py.user.next!
#! /usr/bin/env python
# ------loads from MATH module, you can change this list------
FUNCTIONS = ['sin', 'cos', 'tan', 'sqrt', 'log']
# ------------------------------------------------------------
# Expression:
# Term
# Expression + Term
# Expression - Term
# Term:
# Primary
# Term * Primary
# Term / Primary
# Term % Primary
# Primary:
# Number
# ( Expression )
# function ( Expression )
# - Primary
# + Primary
# Number:
# floating-point-literal
class Buffer(list):
def get(self):
if self:
return self.pop(0)
def putback(self, val):
self.insert(0, val)
def expression(buf):
left = term(buf)
t = buf.get()
while True:
if t == '+':
left += term(buf)
t = buf.get()
elif t == '-':
left -= term(buf)
t = buf.get()
else:
buf.putback(t)
return left
def term(buf):
left = primary(buf)
t = buf.get()
while True:
if t == '*':
left *= primary(buf)
t = buf.get()
elif t == '/':
d = primary(buf)
if d == 0.:
raise ValueError('divide by zero')
left /= d
t = buf.get()
elif t == '%':
d = primary(buf)
if d == 0.:
raise ValueError('divide by zero')
left %= d
t = buf.get()
else:
buf.putback(t)
return left
import math
def primary(buf):
t = buf.get()
if isint(t):
return int(t)
elif isfloat(t):
return float(t)
elif t == '-':
return - primary(buf)
elif t == '+':
return primary(buf)
elif t == '(':
d = expression(buf)
t = buf.get()
if t != ')':
raise ValueError("')' expected")
return d
elif t in FUNCTIONS:
return getattr(math, str(t))(primary(buf))
else:
raise ValueError('primary expected')
def isint(string):
try:
int(string)
return True
except ValueError:
return False
def isfloat(string):
try:
float(string)
return True
except ValueError:
return False
NUMBERS = '0123456789'
PERIOD = '.'
SYMBOLS = '()+-*/%'
NUMBERS_WITH_PERIOD = PERIOD + NUMBERS
FUNCTIONS_str = ''.join(FUNCTIONS)
def p(s):
res = []
s = ''.join(s.split())
state = 'normal'
slen = len(s)
eword = ''
i = 0
while i < slen:
c = s[i]
if state == 'normal':
if c in NUMBERS_WITH_PERIOD:
state = 'number'
num = ''
was_period = False
elif c in SYMBOLS:
state = 'symbol'
elif c in FUNCTIONS_str:
state = 'function'
func = ''
else:
state = 'error'
i -= 1
elif state == 'number':
if c in NUMBERS:
num += c
elif c == PERIOD:
if was_period:
eword = c
state = 'error'
i -= 1
else:
num += c
was_period = True
if c not in NUMBERS_WITH_PERIOD:
res.append(num)
num = ''
state = 'normal'
i -= 1
if i + 1 == slen:
res.append(num)
elif state == 'symbol':
if c in SYMBOLS:
res.append(c)
else:
state = 'normal'
i -= 1
elif state == 'function':
if c in FUNCTIONS_str:
func += c
if c not in FUNCTIONS_str:
if func in FUNCTIONS:
res.append(func)
state = 'normal'
else:
eword = func
state = 'error'
i -= 1
if i + 1 == slen:
if func in FUNCTIONS:
res.append(func)
else:
eword = func
state = 'error'
i -= 1
elif state == 'error':
raise ValueError("wrong word '{}'".format(eword))
i += 1
return res
def calc(expr):
return expression(Buffer(p(expr)))
if __name__ == "__main__":
from time import time
from math import *
exprs = ['(3+2+1+9/2-98*5+7%2)-2+4/2+(((321)-43)-1)/2.',
'-2-1',
'(+2-1)/.100',
'.311-2/4.5',
'10%3',
'sqrt(12)',
'sqrt(4)-1+cos(33)',
'log(20)']
for e in exprs:
t1 = time()
e1 = eval(e)
t1 -= time()
t2 = time()
e2 = calc(e)
t2 -= time()
print "eval({0}):\t{1}\t{2:10f}\ncalc({0}):\t{3}\t{4:10f}\n".format(e, e1, t1, e2, t2)