from core.parser.clean_string import cleanString from core.parser.parse_token import parseToken from core.parser.find_prefix import findPrefix from core.primitives.list import ( cons, NIL ) from core.exceptions import ( syntaxError, runtimeError ) from core.tokens import SpecialForm def parseExpression(s: str) -> tuple: s = cleanString(s) if not s: return NIL, s match s[0]: case '"': # string matching = s.find('"', 1) if matching < 0: raise syntaxError(f'the closing " is missing: {s}') return s[1:matching], s[matching + 1:] case '(': # list cache = s # saving initial view for Error illustration s = s[1:] arr: list = [] while s and s[0] != ')': elem, s = parseExpression(s) arr.append(elem) s = cleanString(s) if not s: raise syntaxError(f'the closing ) is missing: {cache}') result = NIL for elem in reversed(arr): result = cons(elem, result) return result, s[1:] case ')': raise syntaxError(f'extra closing bracket: {s}') # TODO debug case "'": try: v, rem = parseExpression(s[1:]) except Exception as e: raise runtimeError(f'invalid quote: {s}') from e if v is None: raise syntaxError(f'quote of nothing: {s}') return cons(SpecialForm.QUOTE, cons(v, NIL)), rem case _: # maybe we can find token first = findPrefix(s) return parseToken(first) if first else NIL, s[len(first):]