82 lines
2.3 KiB
Python
82 lines
2.3 KiB
Python
import re
|
|
import lisp
|
|
from lisp import prettyprint
|
|
|
|
|
|
class Reader:
|
|
tokens: list[str]
|
|
|
|
def __init__(self, outputfile: str):
|
|
self.tokens = []
|
|
self.interpreter = lisp.Lisp()
|
|
self.outputfile = outputfile
|
|
|
|
def run(self):
|
|
if len(self.tokens) == 0:
|
|
return
|
|
try:
|
|
with open(self.outputfile, "a") as file:
|
|
while self.peek() != "":
|
|
result = prettyprint(self.interpreter.evaluate(self.read_expression()))
|
|
print(">> " + result)
|
|
file.write(result+"\n")
|
|
except Exception as e:
|
|
print("ERROR: " + str(e))
|
|
self.tokens = []
|
|
return
|
|
self.flush()
|
|
|
|
def tokenize(self, expression: str):
|
|
self.tokens += re.findall(r"""(?:;.*|[\s,]*)([()']|"(?:\\.|[^\\"])*"?|[^\s()'",;]*)""", expression)
|
|
|
|
def peek(self):
|
|
return self.tokens[0]
|
|
|
|
def flush(self):
|
|
while len(self.tokens) > 0:
|
|
if self.peek() == "":
|
|
self.consume()
|
|
|
|
def consume(self):
|
|
token = self.tokens[0]
|
|
self.tokens = self.tokens[1:]
|
|
return token
|
|
|
|
def read_expression(self):
|
|
if len(self.tokens) == 0:
|
|
return None
|
|
if self.peek() == "(":
|
|
self.consume()
|
|
atomlist = []
|
|
token = self.peek()
|
|
while token != ")":
|
|
atomlist.append(self.read_expression())
|
|
while self.peek() == "":
|
|
self.flush()
|
|
expression: str = input("... ").upper()
|
|
self.tokenize(expression)
|
|
token = self.peek()
|
|
self.consume()
|
|
return atomlist
|
|
elif self.peek() == "'":
|
|
# Expand the quote macro!
|
|
self.consume()
|
|
return ["QUOTE", self.read_expression()]
|
|
elif self.peek() == ")":
|
|
raise SyntaxError("Unexpected ')'")
|
|
else:
|
|
return self.read_atom()
|
|
|
|
def read_atom(self):
|
|
token = self.consume()
|
|
if token.upper() == "T":
|
|
return True
|
|
elif token.upper() == "NIL":
|
|
return False
|
|
try:
|
|
return int(token)
|
|
except ValueError:
|
|
try:
|
|
return float(token)
|
|
except ValueError:
|
|
return token |