Resilient parsing!
This commit is contained in:
@@ -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,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)
|
|
||||||
@@ -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)
|
|
||||||
@@ -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()
|
||||||
Reference in New Issue
Block a user