Resilient parsing!

This commit is contained in:
etc404
2026-04-26 20:50:40 -06:00
parent 7d6b339cc6
commit 00d1ff11d7
4 changed files with 43 additions and 27 deletions
+8
View File
@@ -11,3 +11,11 @@ class Atom:
def append(self, atom: Atom): def append(self, atom: Atom):
self.cdr = atom self.cdr = atom
def __str__(self):
if type(self.car) is Atom:
return "(" + self.car.__str__() + ("" if self.cdr is None else (" " + self.cdr.__str__())) + ")"
elif self.car is None:
return "()"
else:
return self.car + ("" if self.cdr is None else self.cdr.__str__())
+2 -5
View File
@@ -2,8 +2,5 @@ import atom
import reader import reader
class Lisp: class Lisp:
def parse(self, expression): def evaluate(self, expression):
return reader.tokenize(expression) print(expression)
def evaluate(self, expression: str):
return self.parse(expression)
+30 -20
View File
@@ -11,11 +11,13 @@ class Reader:
self.tokens = [] self.tokens = []
self.interpreter = lisp.Lisp() self.interpreter = lisp.Lisp()
def run(self):
while self.peek() != "":
self.interpreter.evaluate(self.read_expression())
self.consume()
def tokenize(self, expression: str): def tokenize(self, expression: str):
self.tokens += re.findall(r"""[\s,]*[;.*]*([()']|"(?:\\.|[^\\"])*"?|[^\s()'",;]*)""", expression) self.tokens += re.findall(r"""[\s,]*[;.*]*([()']|"(?:\\.|[^\\"])*"?|[^\s()'",;]*)""", expression)
while self.peek() != "":
self.read_expression()
self.consume()
def peek(self): def peek(self):
return self.tokens[0] return self.tokens[0]
@@ -25,27 +27,35 @@ class Reader:
self.tokens = self.tokens[1:] self.tokens = self.tokens[1:]
return token return token
def read_expression(self) -> atom.Atom | None: def read_expression(self):
if len(self.tokens) == 0: if len(self.tokens) == 0:
return None return None
if self.peek() == "(": if self.peek() == "(":
self.consume() self.consume()
return self.read_list() atomlist = []
token = self.peek()
while token != ")":
atomlist.append(self.read_expression())
while self.peek() == "":
self.consume()
expression: str = input("... ")
self.tokenize(expression)
token = self.peek()
self.consume()
return atomlist
else: else:
return self.read_atom() return self.read_atom()
def read_list(self): def read_atom(self):
token = self.peek() token = self.consume()
last = atom.Atom(None, None) if token.upper() == "T":
first = last return True
while token != ")": elif token.upper() == "NIL":
last.setval(self.read_expression()) return False
last.append(atom.Atom(None, None)) try:
last = last.cdr return int(token)
token = self.peek() except ValueError:
self.consume() try:
return first return float(token)
except ValueError:
def read_atom(self) -> atom.Atom: return token
print(self.peek())
return atom.Atom(self.consume(), None)
+2 -1
View File
@@ -5,8 +5,9 @@ def main():
interpreter = reader.Reader() interpreter = reader.Reader()
# REPL Loop # REPL Loop
while True: while True:
expression: str = input("> ") expression: str = input(">>> ")
interpreter.tokenize(expression) interpreter.tokenize(expression)
interpreter.run()
if __name__ == "__main__": if __name__ == "__main__":
main() main()