Advertisement
Guest User

Inter 24.01

a guest
Jan 23rd, 2020
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.75 KB | None | 0 0
  1. from functools import reduce
  2. #'(+ 1 2 (+ 2 3))' -> ['+', 1, 2, ['+', 2, 3]]
  3. # parsing
  4.  
  5.  
  6.  
  7. #'(car (quote (+ 42 13)))' -> ['(','car','(','quote','(','+','42','13',')',')',')']
  8.  
  9. class LispInterException(ValueError):pass
  10.  
  11. def tokenize(line):
  12. word_holder = ''
  13. tokens = []
  14. for i in line:
  15. if i == '(' or i == ')':
  16. if word_holder == '':
  17. tokens.append(i)
  18. else:
  19. tokens.append(word_holder)
  20. word_holder = ''
  21. tokens.append(i)
  22. elif i == ' ':
  23. if word_holder != '':
  24. tokens.append(word_holder)
  25. word_holder = ''
  26. else:
  27. word_holder += i
  28. if word_holder != '':
  29. tokens.append(word_holder)
  30. return tokens
  31.  
  32.  
  33.  
  34.  
  35.  
  36. #tokens: '(','42','(','13',')','666',')'
  37. #stack: '(','42',['13']
  38.  
  39. def parse(array): #via stack
  40. stack = []
  41. for i in array:
  42. if i != ')':
  43. if i.isdigit():
  44. stack.append(int(i))
  45. else:
  46. stack.append(i)
  47. else:
  48. resulting_list = []
  49. while stack and stack[-1] != '(':
  50. resulting_list.append(stack.pop())
  51. if stack:
  52. stack.pop()
  53. else:
  54. raise LispInterException("Exception: Missing opening skobochka")
  55. stack.append(resulting_list[::-1])
  56. return stack.pop()
  57.  
  58.  
  59. # 42
  60. # ['+',1,2]
  61. # x,y,z - numbers
  62. # i,j,k -- indices
  63. # f,g,h,foo,bar-- functions
  64. # expr -
  65.  
  66. # (+ (* 2 3) 5)
  67.  
  68. global_d = {}
  69. local_d = {}
  70.  
  71. def my_eval(expr, global_d, local_d):
  72. if type(expr) == int:
  73. return expr
  74.  
  75. elif expr == '#t' or expr == '#f':
  76. return expr
  77.  
  78. elif type(expr) == str:
  79. if expr in local_d:
  80. return local_d[expr]
  81. else:
  82. raise LispInterException("Exception: Variable is not defined")
  83.  
  84. elif type(expr) == list and expr[0] == '+': #plus
  85. print('plusuu')
  86. return reduce(lambda x,y: x + my_eval(y, global_d, local_d), expr[1:], 0)
  87.  
  88. elif type(expr) == list and expr[0] == '-': #minus
  89. print('minusuu')
  90. if len(expr) == 2: #Lisp returns -x if it's (- x)
  91. return my_eval(expr[1], global_d, local_d) * -1
  92. else:
  93. return reduce(lambda x,y: x - my_eval(y, global_d, local_d), expr[1:], 0)
  94.  
  95. elif type(expr) == list and expr[0] == '*': #multiply
  96. print('umnojau')
  97. return reduce(lambda x,y: x * my_eval(y, global_d, local_d), expr[1:], 1)
  98.  
  99. elif type(expr) == list and expr[0] == '/': #divide
  100. print('delu')
  101. if len(expr) == 1:
  102. return 'Error: You can\'t call eval for the empty division symbol'
  103. else:
  104. return reduce(lambda x,y: x / my_eval(y, global_d, local_d), expr[1:])
  105.  
  106. elif type(expr) == list and expr[0] == 'null': #null
  107. print('null func')
  108. if my_eval(expr[1], global_d, local_d):
  109. return '#f'
  110. else:
  111. return '#t'
  112.  
  113. elif type(expr) == list and expr[0] == '=': #equal
  114. print('equal func')
  115. if my_eval(expr[1], global_d, local_d) == my_eval(expr[2], global_d, local_d):
  116. return '#t'
  117. else:
  118. return '#f'
  119.  
  120. elif type(expr) == list and expr[0] == '/=': #not equal
  121. print('not equal func')
  122. if my_eval(expr[1], global_d, local_d) != my_eval(expr[2], global_d, local_d):
  123. return '#t'
  124. else:
  125. return '#f'
  126.  
  127. elif type(expr) == list and expr[0] == '>': #more than
  128. print('more than func')
  129. if my_eval(expr[1], global_d, local_d) > my_eval(expr[2], global_d, local_d):
  130. return '#t'
  131. else:
  132. return '#f'
  133.  
  134. elif type(expr) == list and expr[0] == '<': #less than
  135. print('less than func')
  136. if my_eval(expr[1], global_d, local_d) < my_eval(expr[2], global_d, local_d):
  137. return '#t'
  138. else:
  139. return '#f'
  140.  
  141. elif type(expr) == list and expr[0] == '>=': #more or equal than
  142. print('more or equal than func')
  143. if my_eval(expr[1], global_d, local_d) >= my_eval(expr[2], global_d, local_d):
  144. return '#t'
  145. else:
  146. return '#f'
  147.  
  148. elif type(expr) == list and expr[0] == 'if': #if function
  149. print('if func')
  150. if my_eval(expr[1], global_d, local_d) == '#t':
  151. return my_eval(expr[2], global_d, local_d)
  152. else:
  153. return my_eval(expr[3], global_d, local_d)
  154.  
  155. elif type(expr) == list and expr[0] == '<=': #less or equal than
  156. print('less or equal func')
  157. if my_eval(expr[1], global_d, local_d) <= my_eval(expr[2], global_d, local_d):
  158. return '#t'
  159. else:
  160. return '#f'
  161.  
  162. elif type(expr) == list and expr[0] == 'cons': #Try and probably fix after fucntion let will be created
  163. print('cons func')
  164. a = my_eval(expr[2], global_d, local_d)
  165. a.insert(0, my_eval(expr[1], global_d, local_d))
  166. return a
  167.  
  168. elif type(expr) == list and expr[0] == 'list':
  169. print('list func')
  170. return [my_eval(i, global_d, local_d) for i in expr[1:]]
  171.  
  172. elif type(expr) == list and expr[0] == 'car':
  173. print('car func')
  174. return my_eval(expr[1], global_d, local_d)[0]
  175.  
  176. elif type(expr) == list and expr[0] == 'cdr':
  177. print('cdr func')
  178. return my_eval(expr[1], global_d, local_d)[1:]
  179.  
  180. elif type(expr) == list and expr[0] == 'quote':
  181. print('quote func')
  182. return expr[1]
  183.  
  184. elif type(expr) == list and expr[0] == 'let':
  185. print('let func')
  186. local_d_new = local_d.copy()
  187. for i in expr[1]:
  188. local_d_new[i[0]] = my_eval(i[1], global_d, local_d)
  189. return my_eval(expr[2], global_d, local_d_new)
  190.  
  191. elif type(expr) == list and expr[0] == 'let*':
  192. for i in expr[1]:
  193. local_d = local_d.copy()
  194. local_d[i[0]] = my_eval(i[1], global_d, local_d)
  195. return my_eval(expr[2], global_d, local_d)
  196.  
  197. elif type(expr) == list and expr[0][0] == 'lambda':
  198. print('lambda func')
  199. local_d = local_d.copy()
  200. actuals = [my_eval(i, global_d, local_d) for i in expr[1:]]
  201. for i,j in enumerate(expr[0][1]):
  202. local_d[j] = actuals[i]
  203. return (my_eval(expr[0][2], global_d, local_d))
  204. else:
  205. raise LispInterException('Exception: you gave some bullshit to the eval')
  206.  
  207.  
  208. #print (my_eval(parse(tokenize('(let* ((a 25) (b (+ a 1))) (+ a b))')), global_d, local_d))
  209.  
  210. # ((lambda (x) (+ 1 x)) 42)
  211. # ((lambda (x y) (list y x)) 42 13)
  212. # evlis
  213.  
  214.  
  215. #Прогнать парсинг с отладочной печатью
  216. #Написать функцию самостоятельно перегона из стринга в инт, из инта в стринг
  217. #Доделать всю арифметику, а также car cdr quote cons if
  218.  
  219. # REPL = Read Eval Print Loop
  220.  
  221. def repl():
  222. global_d = {}
  223. while True:
  224. expr = input("MICRO-LISP: ")
  225. try:
  226. print (my_eval(parse(tokenize(expr)), global_d, {}))
  227. except LispInterException as e:
  228. print (e)
  229.  
  230. repl()
  231.  
  232. #Добавить в необходимые места ексепшены (например, не хватает открывающейся скобки)
  233. #Сделать Define
  234. #Реализовать специальную конструкцию If, чтобы експрешион ((if (= 1 1) (lambda (x) (+ 1 x)) (lambda (y) (+ 2 x))) 42) выполнялся (прописать myeval...)
  235. #Реализовать интерпретатор без рекурсии
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement