It should return result of lisp-like arithmetic expressions:
run("(+ 3 (* 2 4) 1)") # 12
def run(code):
def func(operator):
from functools import reduce
add = lambda a, b: float(a) + float(b)
mul = lambda a, b: float(a) * float(b)
div = lambda a, b: float(a) / float(b)
deduct = lambda a, b: float(a) - float(b)
d = {
'+': lambda arr: reduce(add, arr),
'*': lambda arr: reduce(mul, arr),
'/': lambda arr: reduce(div, arr),
'-': lambda arr: reduce(deduct, arr)
}
return d[operator]
def lex(token):
if token in ('+', '-', '/', '*', '%'):
return "operator"
elif token == '(':
return "lbracket"
elif token == ')':
return "rbracket"
elif token[0].isalpha():
return "name"
elif token[0] == token[-1] and token[0] in ('"', "'"):
return "string"
else:
try:
float(token)
return "number"
except:
raise ValueError
def getArgs(words):
args = []
arg = []
i = 0
for word in words[2:]:
if word == '(':
i += 1
arg.append(word)
elif word == ')':
i -= 1
arg.append(word)
if i == 0:
args.append(arg)
arg = []
elif i == 0:
arg.append(word)
args.append(arg)
arg = []
else:
arg.append(word)
return args
def expr(words):
args = getArgs(words)
args_ = []
for arg in args:
if len(arg) == 1:
args_.append(arg)
else:
args_.append(expr(arg))
if lex(words[1]) == "operator":
return func(words[1])(list(map(lambda a: (type(a) in (list, tuple) and a[0]) or a, args_)))
lines = code.split("\n")
for line in lines:
word = ''
words = []
chars = tuple(line)
for i in tuple(line):
if i in ('(', ')'):
if word: words.append((word, lex(word)))
words.append((i, lex(i)))
word = ''
elif i == ' ':
if word: words.append((word, lex(word)))
word = ''
else:
word += i
if word: words.append((word, lex(word)))
words_ = list(map(lambda arr: arr[0], words))
return(expr(words_))
Test.assert_equals(run("(+ 1 2)"), 3.0)
Test.assert_equals(run("(* 3 (/ 10 2))"), 15.0)