Обзор книги "Language Implementation Patterns" (2010 г.) 📚
(можно посмотреть тут - https://pragprog.com/titles/tpdsl/language-implementation-patterns/)
После прохождения в университете стандартных условно "компиляторских" курсов ("формальные языки и грамматики" и "конструирование компиляторов"), я увидел что они слабо относятся к реальному дело.
Реальные компиляторы написаны не совсем так, как сказано в кондовых теоретических учебниках. Мне как будто не хватало какой-то информации - например, ни одна грамматика не разберет сходу, что означает запись
T(i) в C++, так как для этого нужно знать что такое T и i, а грамматики так не смогут. 😟Книга
Language Implementation Patterns супер информативная и содержит real-life теорию с кодом для реализации языковых тулз.В ней разбираются всякие примеры как: интерпретатор байткода, статический анализатор кода, компилятор C/C++ (урезанный) и многое другое.
В книге есть 31 "паттерн" от простых к сложным, каждый паттерн описывает структуру данных, алгоритм, или типичную архитектуру для языковых тулз.
Паттерны разделены на 4 части: чтение ввода (
I), анализ ввода (II), интерпретация ввода (III), генерация вывода (IV).Самые простые приложения используют только
I, сложные используют I+II+III или I+II+IV.Для примера с моего старого поста (https://t.me/cxx95/40): часть
I объясняет "лексический анализ", часть II "синтаксический анализ", часть IV "кодогенерацию".В книге не изобретаются велосипеды, а сразу дается правильная архитектура или вспомогательная тулза 🙂
Например, вся часть
I может быть покрыта ANTLR - генератором парсеров (а автор книги - разработчик ANTLR), и свой парсер не придется писать.Это экономит много времени, потому что у человекочитаемой грамматики (например в форме БНФ) могут быть супер неочевидные правила разбора, и надо самому вычислять множества FIRST и FOLLOW, а этому посвящается университетский курс... Генератор парсеров все делает за программиста по описанию грамматики.
Казалось бы - разве так много людей часто делают компилятор чего-либо? Но эта книга все равно будет полезна всем, кто делает свой DSL, тулзы для рефакторинга кода, форматирования, статического анализа, метрик.
Какие есть комментарии к книге:
🤔 Надо помнить, что разрабатываемый в книге примерный "компилятор для C++" делается для урезанного языка. В реальном мире анализатор для C++ это не LL(1) или LL(*), а скорее LL(k), где k - размер файла...
🤔 Весь код в книге написан на Java (ANTLR тоже на нем), возможно кому-то не понравится этот язык.
🤔 В одном из паттернов есть крохоборство для "буфера токенов" - прочитанные из файла токены выкидываются из памяти. Но даже в C++, где после препроцессора файлы могут быть в миллионы строк (и в N раз больше токенов) всё хранится в памяти.
🤔 В книге часто рекламируется генератор парсеров ANTLR, но для ряда сложных задач он выглядит трешово и намного более непонятным чем если бы это делалось в коде. Пример - когда "оптимизируем" код в языке для записи операция с векторами:
4 * [0, 5*0, 3] -> [4*0, 4*5*0, 4*3] -> [0, 0, 4*3]предлагается сделать это прямо в конфиге ANTLR:
scalarVectorMult : ^('*' INT ^(VEC (e+=.)+)) -> ^(VEC ^('*' INT $e)+) ;
zeroX : ^('*' a=INT b=INT {$a.int==0}?) -> $a ; // 0*x -> 0
xZero : ^('*' a=INT b=INT {$b.int==0}?) -> $b ; // x*0 -> 0
🤔 В книге совсем не описана генерация в машинный код и сложные оптимизации. Это отдельная наука и большинству людей никогда не пригодятся эти знания. Но надо иметь в виду, что книга грубо говоря показывает как код на С++ переводится в LLVM IR.Буквально на последней странице упоминается LLVM и рекомендуется его использование для компилируемых языков, так как там уже есть все для этого.