Skip to content

Instantly share code, notes, and snippets.

@jorinvo
Created May 17, 2016 11:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jorinvo/2b9d6fe996694313454a72ecf6f82d75 to your computer and use it in GitHub Desktop.
Save jorinvo/2b9d6fe996694313454a72ecf6f82d75 to your computer and use it in GitHub Desktop.
Experiments writing a LISP interpreter in Python. Thanks https://maryrosecook.com/blog/post/little-lisp-interpreter
class Library:
@staticmethod
def first(x):
return x[0]
@staticmethod
def add(*x):
if type(x[0]) == list:
return sum(x[0])
else:
return sum(x)
@staticmethod
def max(*x):
if type(x[0]) == list:
return max(x[0])
else:
return max(x)
@staticmethod
def square(x):
return x * x
@staticmethod
def map(fn, l):
return [fn(x) for x in l]
@staticmethod
def ifelse(cond, then_val, else_val):
if cond == 1:
return then_val
elif cond == 0:
return else_val
else:
raise Exception('Non-boolean condition: %s' % (cond))
library = {
'first': Library.first,
'+': Library.add,
'max': Library.max,
'square': Library.square,
'map': Library.map,
'if': Library.ifelse
}
from library import library
def tokenize(lisp_str):
return lisp_str.replace('(', ' ( ').replace(')', ' ) ').split()
def parenthesize(tokens, tree=[]):
if not tokens:
return tree.pop()
token = tokens.pop(0)
if token == '(':
return parenthesize(tokens, tree + [parenthesize(tokens)])
elif token == ')':
return tree
else:
return parenthesize(tokens, tree + [categorize(token)])
def categorize(token):
try:
return ('lit', float(token))
except:
return ('id', token)
def interpret(val, context=None):
if not context:
return interpret(val, library)
elif type(val) == list:
l = [interpret(x, context) for x in val]
if callable(l[0]):
return l[0](*l[1:])
else:
return l
elif val[0] == 'id':
try:
return context[val[1]]
except KeyError as key:
raise Exception('Function %s not in context' % (key))
else:
# lit
return val[1]
if __name__ == '__main__':
test_input = '''
(
(+ 1 7)
(+ (2.5 4))
(map square (1 2 3))
1
(first (
(first ((square 3)))
1
(first (4 5))
))
(if 1 10 20)
(if (first (0 1)) 10 20)
)
'''
tokens = tokenize(test_input)
tree = parenthesize(tokens)
print(interpret(tree))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment