Last active
March 21, 2016 22:59
-
-
Save BookOwl/78abe7e3138a0a45d8bb to your computer and use it in GitHub Desktop.
A simple LISP interpreter for https://scratch.mit.edu/discuss/topic/189101/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
from operator import * | |
i=lambda p: p if type(p)!=tuple else{"cons":lambda a,b:(a,b),"car":lambda a:a[0],"cdr":lambda a:a[1],"cadr":lambda a:a[1][0],"+":add,"-":sub,"*":mul,"print":print}[p[0]](*map(i,p[1:])) | |
while 1:i(eval(re.sub("[\n ]+",",",re.sub("[a-z+\-*]+","'\g<0>'",input()).replace("'nil'","''"))or"''")) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
from functools import reduce | |
from operator import mul | |
# Dictionary of defined functions with lots of lambdas | |
FUNCTIONS = {"cons": lambda a, b: (a, b), | |
"car": lambda a: a[0], | |
"cdr": lambda a: a[1], | |
"cadr": lambda a: a[1][0], | |
"+": lambda *args: sum(args), | |
"-": lambda a, b: a - b, | |
"*": lambda *args: reduce(mul, args, 0), | |
"print": lambda arg: print(arg)} | |
def parse(prog): | |
"Parses a S-Expression by converting it into a tuple" | |
# Replace every symbol (but not numbers) with the symbol enclosed in '', | |
# so that when we run eval the symbols turn into strings | |
prog = re.sub("[a-zA-Z+\-*]+", "'\g<0>'", prog) | |
# Replace "nil" with None | |
prog = prog.replace("'nil'", "None") | |
# Replace all the newlines and spaces (Lisp list seperators) | |
# with ", " (Python tuple seperators) | |
prog = re.sub("[\n ]+", ", ", prog) | |
# prog is now valid tuple syntax, so run eval to turn it into one | |
return eval(prog) | |
def interpret(prog): | |
"Recursively interprets the parsed prog" | |
# If we are interpreting a literal (int or None), return it | |
if type(prog) in (int, type(None)): | |
return prog | |
# Else, we have a tuple | |
# Run the function given by the first item in the tuple | |
# with arguments given by recusivly interpreting the rest of the tuple | |
elif prog[0] in FUNCTIONS: | |
return FUNCTIONS[prog[0]](*tuple(map(interpret, prog[1:]))) | |
def run(prog): | |
"A helper function that parses and inteprets prog" | |
return interpret(parse(prog)) | |
if __name__ == "__main__": | |
print("OwlLISP REPL") | |
while True: | |
prog = input("Enter your program: ") | |
ret = run(prog) | |
if ret: | |
print(ret) |
If you want to continue, I'd suggest to make it less code golf-y 📦 (not that you have to)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Next steps: