I'm designing a new esoteric language, and the interpreter is in Python3. It is going to use Prefix Notation, so as part of the interpreter, I need a function that evaluates a string as prefix notation and returns a number. Here is my code so far:
import re
import math
class Operator:
def __init__(self, arity, function):
self.arity = arity
self.function = function
def __call__(self, *args):
assert(len(args) == self.arity)
return self.function(*args)
operatorTable = { "+": Operator(2, lambda a,b: a+b),
"-": Operator(2, lambda a,b: a-b),
"/": Operator(2, lambda a,b: a/b),
"*": Operator(2, lambda a,b: a*b),
"<": Operator(2, lambda a,b: a<b),
">": Operator(2, lambda a,b: a>b),
"_": Operator(1, lambda a: -a),
"p": Operator(0, lambda: math.pi),
"e": Operator(0, lambda: math.e)
}
def prefixParse(code):
if code[0] in operatorTable:
operator = operatorTable[code[0]]
if operator.arity == 2:
arg1, chomp1 = prefixParse(code[1:])
arg2, chomp2 = prefixParse(code[chomp1 + 1:])
return operator(arg1, arg2), chomp1 + chomp2 + 1
elif operator.arity == 1:
arg, chomp = prefixParse(code[1:])
return operator(arg), chomp + 1
elif operator.arity == 0:
return operator(), 1
match = re.match("^\d+", code)
if match:
return int(match.group(0)), match.end()
if code[0] == ' ':
res = prefixParse(code[1:])
return res[0], res[1] + 1
print(prefixParse("+2*5 10")[0])
I'm interested in hearing any improvements you have to offer, but I'm particularly interested in these design questions:
Is the recursive
prefixParsea good/suitable algorithm for parsing prefix notation, or is there a simpler way to do it?Is it overkill to use the
Operatorclass?Is there a way to "chomp" the string in place rather than handing a bunch of string indices back and forth? That would be nice because then to get an integer result from the parse function, I don't have to do
prefixParse(code)[0]which looks kinda ugly IMO.Is the layout of the multi-line
operatorTableassignment good code formatting?