Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from functools import reduce
- #'(+ 1 2 (+ 2 3))' -> ['+', 1, 2, ['+', 2, 3]]
- # parsing
- #'(car (quote (+ 42 13)))' -> ['(','car','(','quote','(','+','42','13',')',')',')']
- class LispInterException(ValueError):pass
- def tokenize(line):
- word_holder = ''
- tokens = []
- for i in line:
- if i == '(' or i == ')':
- if word_holder == '':
- tokens.append(i)
- else:
- tokens.append(word_holder)
- word_holder = ''
- tokens.append(i)
- elif i == ' ':
- if word_holder != '':
- tokens.append(word_holder)
- word_holder = ''
- else:
- word_holder += i
- if word_holder != '':
- tokens.append(word_holder)
- return tokens
- #tokens: '(','42','(','13',')','666',')'
- #stack: '(','42',['13']
- def parse(array): #via stack
- stack = []
- for i in array:
- if i != ')':
- if i.isdigit():
- stack.append(int(i))
- else:
- stack.append(i)
- else:
- resulting_list = []
- while stack and stack[-1] != '(':
- resulting_list.append(stack.pop())
- if stack:
- stack.pop()
- else:
- raise LispInterException("Exception: Missing opening skobochka")
- stack.append(resulting_list[::-1])
- return stack.pop()
- # 42
- # ['+',1,2]
- # x,y,z - numbers
- # i,j,k -- indices
- # f,g,h,foo,bar-- functions
- # expr -
- # (+ (* 2 3) 5)
- global_d = {}
- local_d = {}
- def my_eval(expr, global_d, local_d):
- if type(expr) == int:
- return expr
- elif expr == '#t' or expr == '#f':
- return expr
- elif type(expr) == str:
- if expr in local_d:
- return local_d[expr]
- else:
- raise LispInterException("Exception: Variable is not defined")
- elif type(expr) == list and expr[0] == '+': #plus
- print('plusuu')
- return reduce(lambda x,y: x + my_eval(y, global_d, local_d), expr[1:], 0)
- elif type(expr) == list and expr[0] == '-': #minus
- print('minusuu')
- if len(expr) == 2: #Lisp returns -x if it's (- x)
- return my_eval(expr[1], global_d, local_d) * -1
- else:
- return reduce(lambda x,y: x - my_eval(y, global_d, local_d), expr[1:], 0)
- elif type(expr) == list and expr[0] == '*': #multiply
- print('umnojau')
- return reduce(lambda x,y: x * my_eval(y, global_d, local_d), expr[1:], 1)
- elif type(expr) == list and expr[0] == '/': #divide
- print('delu')
- if len(expr) == 1:
- return 'Error: You can\'t call eval for the empty division symbol'
- else:
- return reduce(lambda x,y: x / my_eval(y, global_d, local_d), expr[1:])
- elif type(expr) == list and expr[0] == 'null': #null
- print('null func')
- if my_eval(expr[1], global_d, local_d):
- return '#f'
- else:
- return '#t'
- elif type(expr) == list and expr[0] == '=': #equal
- print('equal func')
- if my_eval(expr[1], global_d, local_d) == my_eval(expr[2], global_d, local_d):
- return '#t'
- else:
- return '#f'
- elif type(expr) == list and expr[0] == '/=': #not equal
- print('not equal func')
- if my_eval(expr[1], global_d, local_d) != my_eval(expr[2], global_d, local_d):
- return '#t'
- else:
- return '#f'
- elif type(expr) == list and expr[0] == '>': #more than
- print('more than func')
- if my_eval(expr[1], global_d, local_d) > my_eval(expr[2], global_d, local_d):
- return '#t'
- else:
- return '#f'
- elif type(expr) == list and expr[0] == '<': #less than
- print('less than func')
- if my_eval(expr[1], global_d, local_d) < my_eval(expr[2], global_d, local_d):
- return '#t'
- else:
- return '#f'
- elif type(expr) == list and expr[0] == '>=': #more or equal than
- print('more or equal than func')
- if my_eval(expr[1], global_d, local_d) >= my_eval(expr[2], global_d, local_d):
- return '#t'
- else:
- return '#f'
- elif type(expr) == list and expr[0] == 'if': #if function
- print('if func')
- if my_eval(expr[1], global_d, local_d) == '#t':
- return my_eval(expr[2], global_d, local_d)
- else:
- return my_eval(expr[3], global_d, local_d)
- elif type(expr) == list and expr[0] == '<=': #less or equal than
- print('less or equal func')
- if my_eval(expr[1], global_d, local_d) <= my_eval(expr[2], global_d, local_d):
- return '#t'
- else:
- return '#f'
- elif type(expr) == list and expr[0] == 'cons': #Try and probably fix after fucntion let will be created
- print('cons func')
- a = my_eval(expr[2], global_d, local_d)
- a.insert(0, my_eval(expr[1], global_d, local_d))
- return a
- elif type(expr) == list and expr[0] == 'list':
- print('list func')
- return [my_eval(i, global_d, local_d) for i in expr[1:]]
- elif type(expr) == list and expr[0] == 'car':
- print('car func')
- return my_eval(expr[1], global_d, local_d)[0]
- elif type(expr) == list and expr[0] == 'cdr':
- print('cdr func')
- return my_eval(expr[1], global_d, local_d)[1:]
- elif type(expr) == list and expr[0] == 'quote':
- print('quote func')
- return expr[1]
- elif type(expr) == list and expr[0] == 'let':
- print('let func')
- local_d_new = local_d.copy()
- for i in expr[1]:
- local_d_new[i[0]] = my_eval(i[1], global_d, local_d)
- return my_eval(expr[2], global_d, local_d_new)
- elif type(expr) == list and expr[0] == 'let*':
- for i in expr[1]:
- local_d = local_d.copy()
- local_d[i[0]] = my_eval(i[1], global_d, local_d)
- return my_eval(expr[2], global_d, local_d)
- elif type(expr) == list and expr[0][0] == 'lambda':
- print('lambda func')
- local_d = local_d.copy()
- actuals = [my_eval(i, global_d, local_d) for i in expr[1:]]
- for i,j in enumerate(expr[0][1]):
- local_d[j] = actuals[i]
- return (my_eval(expr[0][2], global_d, local_d))
- else:
- raise LispInterException('Exception: you gave some bullshit to the eval')
- #print (my_eval(parse(tokenize('(let* ((a 25) (b (+ a 1))) (+ a b))')), global_d, local_d))
- # ((lambda (x) (+ 1 x)) 42)
- # ((lambda (x y) (list y x)) 42 13)
- # evlis
- #Прогнать парсинг с отладочной печатью
- #Написать функцию самостоятельно перегона из стринга в инт, из инта в стринг
- #Доделать всю арифметику, а также car cdr quote cons if
- # REPL = Read Eval Print Loop
- def repl():
- global_d = {}
- while True:
- expr = input("MICRO-LISP: ")
- try:
- print (my_eval(parse(tokenize(expr)), global_d, {}))
- except LispInterException as e:
- print (e)
- repl()
- #Добавить в необходимые места ексепшены (например, не хватает открывающейся скобки)
- #Сделать Define
- #Реализовать специальную конструкцию If, чтобы експрешион ((if (= 1 1) (lambda (x) (+ 1 x)) (lambda (y) (+ 2 x))) 42) выполнялся (прописать myeval...)
- #Реализовать интерпретатор без рекурсии
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement