Advertisement
Guest User

Python Lisp

a guest
May 9th, 2025
17
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.86 KB | None | 0 0
  1. import math, operator as op
  2. import re
  3.  
  4. Symbol = str
  5. List = list
  6. Number = (int, float)
  7.  
  8. class String(str): pass
  9.  
  10. def tokenize(s):
  11. "Convert a string into a list of tokens, including strings in quotes."
  12. pattern = r'''\s*(?:(;.*) # comments
  13. |("(?:\\.|[^\\"])*") # strings
  14. |([()]|[^\s()"']+)) # parentheses or symbols
  15. '''
  16. tokens = []
  17. for part in re.findall(pattern, s, re.VERBOSE):
  18. if part[0]: continue # skip comments
  19. tokens.append(part[1] or part[2])
  20. return tokens
  21.  
  22. def parse(tokens):
  23. if not tokens: raise SyntaxError('unexpected EOF')
  24. token = tokens.pop(0)
  25. if token == '(':
  26. L = []
  27. while tokens[0] != ')': L.append(parse(tokens))
  28. tokens.pop(0)
  29. return L
  30. elif token == ')':
  31. raise SyntaxError('unexpected )')
  32. else:
  33. return atom(token)
  34.  
  35. def atom(token):
  36. if token.startswith('"') and token.endswith('"'):
  37. return String(token[1:-1]) # хранить как отдельный тип
  38. try: return int(token)
  39. except ValueError:
  40. try: return float(token)
  41. except ValueError:
  42. return Symbol(token)
  43.  
  44. def standard_env():
  45. env = {}
  46. env.update(vars(math))
  47. env.update({
  48. '+':op.add, '-':op.sub, '*':op.mul, '/':op.truediv,
  49. '>':op.gt, '<':op.lt, '>=':op.ge, '<=':op.le, '=':op.eq,
  50. 'abs': abs, 'append': lambda x, y: x + [y],
  51. 'begin': lambda *x: x[-1],
  52. 'car': lambda x: x[0], 'cdr': lambda x: x[1:],
  53. 'cons': lambda x, y: [x] + y,
  54. 'eq?': op.is_, 'equal?': op.eq,
  55. 'length': len, 'list': lambda *x: list(x),
  56. 'list?': lambda x: isinstance(x, list),
  57. 'map': lambda f, l: list(map(f, l)),
  58. 'max': max, 'min': min, 'not': op.not_,
  59. 'null?': lambda x: x == [],
  60. 'number?': lambda x: isinstance(x, Number),
  61. 'print': print,
  62. 'mod': op.mod,
  63. })
  64. return env
  65.  
  66. global_env = standard_env()
  67.  
  68. class Env(dict):
  69. def __init__(self, parms=(), args=(), outer=None):
  70. super().__init__(zip(parms, args))
  71. self.outer = outer
  72. def find(self, var):
  73. # return self if var in self else self.outer.find(var)
  74. if var in self:
  75. return self[var]
  76. elif isinstance(self.outer, Env):
  77. return self.outer.find(var)
  78. else:
  79. return self.outer[var]
  80.  
  81. def eval(x, env=global_env):
  82. if isinstance(x, String):
  83. return str(x)
  84. elif isinstance(x, Symbol):
  85. try:
  86. # return env[x]
  87. if isinstance(env, Env):
  88. return env.find(x)
  89.  
  90. return env[x]
  91. except KeyError:
  92. raise NameError(f"Неизвестный символ {x}")
  93.  
  94. elif not isinstance(x, List): return x
  95. op, *args = x
  96. if op == 'quote': return args[0]
  97. elif op == 'if':
  98. (test, conseq, alt) = args
  99. return eval(conseq if eval(test, env) else alt, env)
  100. elif op == 'define':
  101. (symbol, exp) = args
  102. env[symbol] = eval(exp, env)
  103. elif op == 'lambda':
  104. (parms, body) = args
  105. return lambda *args: eval(body, Env(parms, args, env))
  106. else:
  107. proc = eval(op, env)
  108. vals = [eval(arg, env) for arg in args]
  109. return proc(*vals)
  110.  
  111. def repl(code):
  112. return eval(parse(tokenize(code)))
  113.  
  114. repl('(print "Hello, world!")')
  115.  
  116. code = """
  117. (begin
  118. (define fizzbuzz
  119. (lambda (n)
  120. (if (= (mod n 15) 0) "FizzBuzz"
  121. (if (= (mod n 3) 0) "Fizz"
  122. (if (= (mod n 5) 0) "Buzz"
  123. n)))))
  124. (map fizzbuzz (list 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))
  125. """
  126. print(repl(code))
  127.  
  128. code = """
  129. (begin
  130. (define fact
  131. (lambda (n)
  132. (if (= n 0) 1
  133. (* n (fact (- n 1))))))
  134. (fact 5))
  135. """
  136. print(repl(code))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement