Парсер выражений Лиспа

Я создаю очень простой интерпретатор Лиспа. Похож на тот отсюда. Вот что у меня есть для части синтаксического анализа, то есть все, от «текст передан в программу» до «ast построен». Как это выглядит ниже? Что можно улучшить? Самым сложным для меня было рекурсивное read_from_tokens функция.

import re
Symbol = str

def pops(L, d=None):
    "Pop from the left of the list, or return the default."
    return L.pop(0) if L else d

def parse(program):
    "Read a Scheme expression from a string and return tokens in AST."
    program = preprocess(program)
    assert program.count(')') == program.count('('), "Mismatched parens"
    return read_from_tokens(tokenize(program))

def preprocess(s):
    "Replace comments with a single space."
    return re.sub(r';.+', ' ', s)

def tokenize(s):
    "Convert a string into a list of tokens."
    return s.replace('(', ' ( ').replace(')', ' ) ').split()

def atom(token):
    "Return a number (only accepted literal) or a symbol."
    try:
        return int(token) if token.isdigit() else float(token)
    except ValueError:
        return Symbol(token)

def read_from_tokens(tokens):
    "Read one or more expression from a sequence of tokens. Returns a list of lists."
    L = []
    while (token := pops(tokens, ')')) != ')':
        L.append(atom(token) if token!='(' else read_from_tokens(tokens))
    return L

if __name__ == '__main__':
    print (parse("(define (+ 2 2) 10) (* pi (* r r))"))
    print (parse("(define r 10)"))
    print (parse("(* pi (* (+ 1 1) r))"))

0

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *