return value # or x.pop(), or del x[-1]
def topOpnd(self):
return self.opnd[-1] # top operand (end of list)
def open(self):
self.optr.append('(') # treat '(' like an operator
def close(self): # on ')' pop downto highest '('
self.shiftOptr(')') # ok if empty: stays empty
self.optr[-2:] = [] # pop, or added again by optr
def closeall(self):
while self.optr: # force rest on 'eval'
self.reduce() # last may be a var name
try:
self.opnd[0] = self.runstring(self.opnd[0])
except:
self.opnd[0] = 'ERROR' # pop else added again next:
afterMe = {'*': ['+', '-', '(', '='], # class member
'/': ['+', '-', '(', '='], # optrs to not pop for key
'+': ['(', '='], # if prior optr is this: push
'-': ['(', '='], # else: pop/eval prior optr
')': ['(', '='], # all left-associative as is
'=': ['('] }
def shiftOpnd(self, newopnd): # push opnd at optr, ')', eval
self.opnd.append(newopnd)
def shiftOptr(self, newoptr): # apply ops with <= priority
while (self.optr and
self.optr[-1] not in self.afterMe[newoptr]):
self.reduce()
self.optr.append(newoptr) # push this op above result
optrs assume next opnd erases
def reduce(self):
trace(self.optr, self.opnd)
try: # collapse the top expr
operator = self.optr[-1] # pop top optr (at end)
[left, right] = self.opnd[-2:] # pop top 2 opnds (at end)
self.optr[-1:] = [] # delete slice in-place
self.opnd[-2:] = []
result = self.runstring(left + operator + right)
if result == None:
result = left # assignment? key var name
self.opnd.append(result) # push result string back
except:
self.opnd.append('ERROR') # stack/number/name error
def runstring(self, code):
try: # 3.0: not x
/repr
result = str(eval(code, self.names, self.names)) # try expr: string
self.hist.append(code + ' => ' + result) # add to hist log
except:
1474 | Chapter 19: Text and Language