https://qr.ae/pN2BWT

Это несложно, но требует огромной работы, чтобы сделать полученный инструмент практичным.

Во-первых, забудьте о синтаксисе — это в основном решённая проблема, почти в любом языке есть 1+ библиотека для создания синтаксических анализаторов. Если вам нравится Python, библиотека PLY предоставляет вам полный набор поддержки любого синтаксиса. Более того, вы можете полностью отказаться от синтаксического анализатора, используя свой хост-язык (язык реализации) для построения деревьев AST или любой другой интерпретируемой структуры данных по вашему выбору.

Далее, избегайте написания классического компилятора, это скучный и очень ограниченный языковой шаблон. Присмотритесь к C++, изначально он был чистым компилятором, но в последнее десятилетие он превратился в свихнутый интерпретатор, работающий поверх движка шаблонов/типов. Именно, он запускает какой-то код во время компиляции, но «язык» для метапрограммирования с его семантикой и синтаксисом сжигает ваш мозг, и у вас всё еще нет инструментов для его отладки.

Не забывайте: любой интерпретатор языка программирования может компилировать самый быстрый машинный код, или код на любом другом языке программирования, который вы хотите использовать (ассемблер, LLVM, C/C ++, Java, ..., все, что вы хотите, включая скрипты сборки и SQL): достаточно писать в текстовые файлы, и компилировать их с помощью любого backend-компилятора.

Итак, давайте в целом.

Недостаток: сложность метода. Да, огромная, но только на более поздних этапах. На начальных этапах вы просто копипастите некоторые части кода на целевом языке в виде обычных строк (в большинстве программных проектов используется несколько языков: код, скрипты сборки/развертывания/обслуживания, JS/HTML, SQL, ...), иногда заменяя крошечные элементы в этих строках используя Python-код, и пишете их в текстовые файлы. Это выглядит просто даже для новичка: только интерполяция строк и запись текстового файла.

Следующий этап развития вас как программиста — это вязание структур данных. Также выглядит как типовой навык любого программиста: манипулирование графом объектов, которые ссылаются друг на друга, иногда циклически. Это не страшно, используется практически в любой зрелой программной системе. У вас даже есть преимущество: объектный граф -- это унифицированная структура данных, любой узел это экземпляр, унаследованный от базового класса Object, и вы можете работать с ними через унифицированный интерфейс. Каждый унаследованный класс имеет собственное поведение, но все они разделяют одну и ту же концепт: дерево (граф) атрибутной грамматики . Каждый объект является контейнером данных (даже Primitive), каждый узел может иметь произвольные атрибуты, привязанные к другим объектным графам, и каждый узел может иметь упорядоченные подграфы:

## @brief базовый класс узла объектного графа
## @ingroup object
class Object:
    ## конструктор
    ## @param[in] V заданное скалярное значение
    def __init__(self, V):
            if isinstance(V, Object): V = V.val
        ## имя символа / скалярное значение (строка, число,..)
            self.val = V
        ## слоты = атрибуты = словарь = environment
            self.slot = {}
        ## вложенные AST = вектор = стек = очередь
            self.nest = []
        ## глобальный storage id
        ## @ingroup persist
            self.gid = self.sync().gid