Написание простого DSL компилятора на Delphi (1. Язык)
Перевод поста Writing a Simple DSL Compiler with Delphi (1. The Language)open in new window.
Эта статья представляет собой неформальное описание простого языка (далее я называю его "Язык") для которого я пишу компилятор. Если вы только начинаете читать эту серию, то я бы рекомендовал вам начать с этого постаopen in new window.
Давайте начнём с простого примера который вычисляет i-тое число Фибоначчи
fib(i) {
if i < 3 {
return 1
} else {
return fib(i-2) + fib(i-1)
}
}
2
3
4
5
6
7
Код довольно прост. Первые два числа в последовательности Фибоначчи это единицы, а последующие являются суммой двух предыдущих числе в последовательности.
Следующие правила описывают язык (более или менее):
- Язык относится к категории C-подобных языков.
- Пробелы игнорируются.
- Только один тип данных — целое число (
integer
) - Только три оператора:
+
,-
, и<
. a < b
возвращает1
если a меньше чемb
, и0
в противоположном случае.- Только два оператора if и return.
- Оператор if выполняет блок then если условное выражение не равно 0 и выполняет блок else в противном случае. Блок else обязателен.
- Оператор return только устанавливает результат функции и не прерывает поток управления.
- Нет оператора присваивания.
- Каждая функция возвращает
integer
. - Параметры всегда передаются по значению.
- Функции без оператора return возвращают 0.
- Функции могут вызывать другие функции (или себя рекурсивно).
Как вы можете видеть, Язык ужасно ограничен, но в нем достаточно функционала для простых примеров. Язык также является функциональным, в терминах computer science. Мы будем использовать это в наших интересах намного позже в этой серии.
Немного более формальное (но всё ещё очень неформальное) описание синтаксиса:
/// program = {function}
///
/// function = identifier "(" [ identifier { "," identifier } ] ")" block
///
/// block = "{" statement {";" statement} [";"] "}"
///
/// statement = if
/// | return
///
/// if = "if" expression block "else" block
///
/// return = "return" expression
///
/// expression = term
/// | term operator term
///
/// term = numeric_constant
/// | function_call
/// | identifier
///
/// operator = "+" | "-" | "<"
///
/// function_call = identifier "(" [expression { "," expression } ] ")"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23