"Как написать компилятор за 15 минут", Андрей Гершун,...
Transcript of "Как написать компилятор за 15 минут", Андрей Гершун,...
![Page 1: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/1.jpg)
Как написать компилятор за 15 минут?
Андрей Гершун AlaSQL
![Page 2: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/2.jpg)
Зачем еще языки кроме JavaScript?
2
Benjamin Lee Whorf Автор гипотезы
лингвистической относительности (категории языка определяют
категории мышления)
![Page 3: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/3.jpg)
3
![Page 4: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/4.jpg)
Содержание
• Знакомьтесь – МАТRIX! • Инструменты • Орфография • Грамматика • Семантика • Пишем интерпретатор • Венец творения – компилятор!
4
![Page 5: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/5.jpg)
Как происходит процесс понимания и выполнения? • Лексер • Парсер • Run-‐cme library • Интерпретатор или • Компилятор
5 C3P0
интерпретатор
![Page 6: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/6.jpg)
Знакомьтесь, MATRIX!
6
![Page 7: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/7.jpg)
MATRIX
• Язык работы с матрицами • Вдохновлен MATLAB, OCTANE, R и Q c = a * b'
7
![Page 8: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/8.jpg)
Пример программы на MATRIX
A = 1 2 3 B = 4|5|6 PRINT A*B
• Если все правильно, то мы должны увидеть: 32
8
![Page 9: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/9.jpg)
Примитивы
1 // число
1 2 3 4 // вектор-‐строка
1 | 2 | 3 // вектор-‐столбец
1 2 | 3 4 // матрица 2x2
9
![Page 10: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/10.jpg)
Операции МАТRIX
1 2 + 3 4 // => 4 6 – сложение
2 * 5 6 // => 10 12 – умножение
1 2' // => 1|2 -‐транспонирование
(1 2 + 3 4)*2 // => 8 12 -‐ скобки
size(1 2|3 4) // => 2 2 -‐ функция размера
10
![Page 11: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/11.jpg)
Zach Carter Автор Jison
Воспользуемся генератором парсеров: • Jison Альтернативы: • PEG.js • ALTNR/4
11
![Page 12: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/12.jpg)
Структура файла с грамматикой (matrix0.jison)
%{ /* А. Вспомогательный код */ %} %lex %options case-‐insensitive %% /* Б. Лексемы */ /lex
12
![Page 13: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/13.jpg)
Структура файла (продолжение)
%ebnf %start main /* В. Приоритеты правил */ %% /* Г. Грамматические правила */
13
![Page 14: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/14.jpg)
Слова языка
• Комментарии // • Пробелы • Число • Названия переменных и функций • Знаки: + * ‘ = ( ) • Ключевое слово: PRINT • Конец файла: <<EOF>>
14
![Page 15: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/15.jpg)
Как работает лексер?
a = 1 2 3'
15
![Page 16: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/16.jpg)
Описываем лексемы
регулярка return 'лексема'
16
![Page 17: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/17.jpg)
Бритва Оккама: Отсекаем все ненужное: комментарии и пробелы // Комментарии \/\/.*$ return // Пробелы, переносы строк \s return
17 William of Okkam
![Page 18: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/18.jpg)
Ключевые слова
'PRINT' return 'PRINT' 'GO TO' return 'GOTO' Синонимы 'GOTO' return 'GOTO'
18
![Page 19: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/19.jpg)
Числа и литералы (после ключевых слов!)
/* Числа */ [0-‐9]+(\.[0-‐9]*)? return 'NUMBER' /* Литералы: названия переменных и функций */ [A-‐Za-‐z_][A-‐Za-‐z_0-‐9]* return 'LITERAL'
19
![Page 20: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/20.jpg)
Немного магии (служебные лексемы)
/* Конец файла */ <<EOF>> return 'EOF' /* В конце отлавливаем нераспознанные символы */ . return 'INVALID'
20
![Page 21: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/21.jpg)
Кофе-‐брейк 1: Что выдает на выходе лексер?
• Проверим лексику: > jison matrix1.jison
• Отладим с помощью jison-‐debugger a = 1 2 3'
21
![Page 22: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/22.jpg)
Теперь грамматика! правило : набор лексем 1 | набор лексем 2 | набор лексем 3 ;
22
John Backus
Peter Naur
![Page 23: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/23.jpg)
Описываем операторы main : Statement* EOF ;
Statement : Print | Set ;
Set : LITERAL EQ Expression ;
Print : PRINT Expression ;
a = 1 2 3
PRINT A*b'
23
![Page 24: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/24.jpg)
Выражения
Expression : Matrix | LITERAL | LPAR Expression RPAR | Expression PLUS Expression | Expression STAR Expression | Expression SHTRIH ;
24
![Page 25: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/25.jpg)
Матрицы Matrix : Columns ;
Row : NUMBER | Row NUMBER ;
Columns : Row | Columns PALKA Row ;
• Пример 1 2 3
25
![Page 26: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/26.jpg)
Приоритеты операций
%left PLUS // 1 + 2 + 3 %left STAR // 1 + 2 * 3 %right STRIH // 1 2 * 3 4'
26
![Page 27: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/27.jpg)
Кофе-‐брейк 2:дерево разбора a = 1 2 3'
27
![Page 28: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/28.jpg)
Пора уже что-‐то делать!
Компилируем грамматику > jison matrix2.jison
Выполняем проверку грамматики > node matrix2.js program.mat
Если все правильно, то ничего не будет!
28
![Page 29: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/29.jpg)
Пишем интерпретатор!
29 C3P0
интерпретатор
![Page 30: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/30.jpg)
Подготовимся интерпретировать (run-‐cme library MATRIX)
• Операторы – MATRIX.print()
• Операции – MATRIX.add() – MATRIX.mulcply() – MATRIX.transpose()
30
![Page 31: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/31.jpg)
Добавляем семантику: подставляем лексемы
Правило : Expression PLUS Expression { // $$ -‐ возвращаемая переменная // $1, $2… -‐ лексемы $$ = $1 + $3; } ;
31
![Page 32: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/32.jpg)
Начнем с печати! Print : PRINT Expression { MATRIX.print($2); } ;
32
![Page 33: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/33.jpg)
Присваивание переменной
Set : LITERAL EQ Expression { MATRIX.mem[$1] = $3; } ;
// Когда будем забирать значение, // просто возьмем: MATRIX.mem.a
33
![Page 34: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/34.jpg)
Матрица
Внутреннее представление – массив массивов, например, матрица: 1 2 3 | 4 5 6 Представляется как: [[1,2,3],[4,5,6]]
34
![Page 35: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/35.jpg)
Строки и столбцы матрицы /* 1 2 3 */ Row
: NUMBER { $$ = [parseFloat($1)]; } | Row NUMBER { $$ = $1; $$.push(parseFloat($2)); } ;
/* 1 2 | 3 4 */ Columns
: Row { $$ = [$1]; } | Columns PALKA Row { $$ = $1; $$.push($3); } ;
35
![Page 36: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/36.jpg)
И все -‐ интерпретатор готов!
36
![Page 37: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/37.jpg)
Кофе-‐брейк 3: Настоящий запуск!
> jison matrix3.jison > node matrix3 program.mat Voila! … наша матрица!
37
![Page 38: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/38.jpg)
38
Розеттский камень Жан-‐Франсуа Шампольон (транслятор)
![Page 39: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/39.jpg)
Интерпретатор
Возвращает значение: Expression PLUS Expression { $$ = MATRIX.add($1,$3); }
39
![Page 40: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/40.jpg)
А компилятор…
Возвращает строку кода на JavaScript: Expression PLUS Expression { $$ = 'MATRIX.add('+$1+','+$3+')'; }
40
![Page 41: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/41.jpg)
Главная функция интерпретатора
Ничего не возвращает main : Statement* EOF;
41
![Page 42: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/42.jpg)
Главная функция компилятора Возвращает откомпилированную функцию на JavaScript: main : Statement* EOF { return new Function(
'var MATRIX = this;’ +$1.join(';')) .bind(MATRIX); } ;
42
![Page 43: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/43.jpg)
Праздничный ужин! Компилируем грамматику > jison matrix4.jison // Запуск из JavaScript var parser = require('./matrix4.js'); var f = parser.parse('print 1 2+100'); f(); //вернет 101 102
43
![Page 44: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/44.jpg)
В браузере
<script src="matrix4.js"></script> <script> var f = parse.parse('print 1 2+100'); f();
</script>
44
![Page 45: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/45.jpg)
Итак, для интерпретатора/компилятора нужно:
• Определить лексемы • Определить правила • Разработать runcme библиотеку • Определить семантику (как будут интерпретироваться или компилироваться правила)
45
![Page 46: "Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24](https://reader031.fdocument.pub/reader031/viewer/2022032100/55ccdc3dbb61ebdb518b4641/html5/thumbnails/46.jpg)
Хотите написать свой ES6?
• Парсеры JavaScript – Esprima – Acorn – UglifyJS – SpiderMonkey
• Линтеры – используют парсеры
• CoffeeScript – использует Jison 46