Недавно я подумал о том, как я могу объединить язык программирования LISP и Python, и попытался написать синтаксис LISP, как компилятор в Python. Что -то, что может преобразовать следующий код LISP:
(repeat 2 (write-ln (+ 10 20)))
к этому дереву:
word: "repeat" int: 2 word: "write-ln" symbol: + int: 10 int: 20
А затем напишите исполнителю для выполнения дерева.
Но я понял, что мне не нужно писать синтаксис -синтаксис Lisp. Вместо этого я могу использовать типы Python Builtins напрямую.
Например:
('repeat', ('print', ('add', 10, 20)))
А потом результатом моих мыслей было то, что я написал это простое Python Buldins Типы компилятора
Анкет ( pbtc
для сокращения)
#!/usr/bin/python3 # filename: main.py import itertools import sys def add(*args): result = args[0] if len(args) != 0 else None for arg in args[1:]: result += arg return result def sub(*args): result = args[0] if len(args) != 0 else None for arg in args[1:]: result -= arg return result def mul(*args): result = args[0] if len(args) != 0 else None for arg in args[1:]: result *= arg return result def div(*args): result = args[0] if len(args) != 0 else None for arg in args[1:]: result /= arg return result def true_div(*args): result = args[0] if len(args) != 0 else None for arg in args[1:]: result //= arg return result def join(sep, args): return sep.join(args) tuple_compilers = { 'add': add, 'sub': sub, 'mul': mul, 'div': div, 'tdiv': true_div, 'print': lambda *args: print(*args), 'join': join, 'repeat': itertools.repeat, } def compile_tuple(tree, memory, compile): if len(tree) == 0: raise ValueError('invalid tuple length: {}'.format(len(tree))) if not isinstance(tree[0], str): raise ValueError('invalid tuple instruction: {}'.format(tree[0])) if tree[0] not in tuple_compilers: raise ValueError('unknown tuple instruction: {}'.format(tree[0])) args = [] for node in tree[1:]: args.append(compile(node, memory)) return tuple_compilers[tree[0]](*args) compilers = { tuple: compile_tuple, (list, dict, str, int, float, bytes): lambda tree, memory, compile: tree, } def compile_tree(tree, compilers, memory = None): self = lambda tree, memory: compile_tree(tree, compilers, memory) for _type, compile in compilers.items(): if isinstance(tree, _type): return compile(tree, memory, self) raise TypeError(type(tree).__name__) with open(sys.argv[1]) as infile: globals_dict = {} exec('grammar = ' + infile.read()) compile_tree(grammar, compilers)
Это не безопасно, это медленно, но работает.
Тестирование:
# filename: lispy ('print', ('join', ' ', ('repeat', ('join', ' ', ['hi', 'bye']), 10)) )
$./main.py Lispy :
hi bye hi bye hi bye hi bye hi bye hi bye hi bye hi bye hi bye hi bye
Это весело…
Возможно, позже я написал более полную версию этого и опубликовал ее где -то, как открытый исходный код.
Оригинал: “https://dev.to/mak12776/write-lisp-in-python-42ph”