- 11.8k
- 1
- 27
- 59
Letting the other answers handle other aspects of the review, this answer addresses two issues:
- A simpler way to exit – Just call
exit()
or whatever when you encounter the tokenquit
. If you don't want toexit()
you could call a specific exception, i.e.QuitException
, and catch this at the proper level - Variable number of operands – If first using slice operators to pick out the correct number of operands, and remove them from the stack, we can use unpacking of argument lists to call the operator with the list of operands. Rather neat, actually!
Here is the code changes:
from operator import add, sub, mul
import math
def foo():
return 100.0
TOKENS = {
'+' : (2, add),
'-' : (2, sub),
'*' : (2, mul),
'/' : (2, lambda a, b: a / b),
'^' : (2, lambda a, b: a ** b),
'**' : (2, lambda a, b: a ** b),
'%' : (2, lambda a, b: a % b),
'mod' : (2, lambda a, b: a % b),
'//' : (2, lambda a, b: a // b),
'sqrt': (1, math.sqrt),
'foo' : (0, foo), # function with no parameters
'pi' : (-1, math.pi), # a constant
}
# Keep the else-block, but replace the if-block with:
if token == 'quit':
exit() # Or possibly: raise QuitException :-)
if token in TOKENS:
operands_count, operator = TOKENS[token]
if operands_count >= 0:
operands = stack[:operands_count]
del stack[:operands_count]
answer = operator(*operands)
else:
answer = operator
stack.append(answer)
Using this I was able to parse '4 5 + 1 + 10 * 2 ** sqrt pi * foo quit 2 *'
and got the expected 31415.9265359
as my final output. Tested '20 3 mod '
equals 2
also, just to verify that operand order had not changed.
Have I mentioned that I like the slice operators, and the *operands
in combination with the simplicity of adding function, constants and so on into a list? If not, considered it done!
- 11.8k
- 1
- 27
- 59