EBNF для описания грамматик #
EBNF — это формальный язык для описания грамматик формальных языков
- EBNF расшифровывается как Extended Backus-Naur Form, или «расширенная нотация Бэкуса-Наура».
- EBNF поддерживает контекстно-свободные грамматики и регулярные грамматики — этого достаточно для описания лексики и синтаксиса всех языков программирования
- EBNF лаконичен в сравнении с другими нотациями
Символы в нотации EBNF #
EBNF имеет несколько диалектов — мы используем диалект из стандарта ISO (ISO/IEC 14977).
Стандарт ISO для EBNF определяет такие символы:
| Символ EBNF | Запись | Описание |
|---|---|---|
| definition | = | Правило, то есть определение нетерминального символа через ряд других символов |
| concatenation | , | Конкатенация символов |
| termination | ; | Конец правила |
| alternation | | | Альтернативные варианты правила |
| optional | [ … ] | Опциональная часть правила (0 или 1 раз) |
| repetition | { … } | Повторяющаяся часть правила (0, 1 или много раз) |
| grouping | ( … ) | Атомарная группа символов |
| terminal string | " … " | Терминальный символ (строка или символ Unicode) |
| comment | (* … *) | Комментарий, не входит в определение |
| exception | - | Исключение ряда символов из числа допустимых |
Пример: EBNF для SQL #
В примере показаны числа (в десятичной записи) и идентификаторы (кроме экранированных двойными кавычками).
(* Идентификатор в SQL *)
identifier = identifier_start, { identifier_extend } ;
identifier_start = letter | "_" ;
identifier_extend = letter | digit | "_" ;
(* Литерал числа в SQL: целое число либо десятичная дробь *)
signed_numeric_literal = [ sign ], unsigned_numeric_literal ;
sign = "+" | "-" ;
unsigned_numeric_literal = unsigned_integer, [ ".", unsigned_integer ] ;
unsigned_integer = digit, { digit } ;
letter = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K"
| "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V"
| "W" | "X" | "Y" | "Z" | "a" | "b" | "c" | "d" | "e" | "f" | "g"
| "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r"
| "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" ;
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
Применение ИИ #
Для генерации черновой версии EBNF грамматики рекомендуется использовать ИИ-модели в режиме чата.
Рекомендуемый подход:
- Составьте свой промпт и запустите его в подходящей ИИ-модели
- Вдумчиво и аккуратно перепишите правила грамматики
- Перепроверьте конспект — нет ли забытых вещей («слепых зон»), фактических ошибок или несущественных деталей?
Пример промпта для создания грамматики выражений:
Ты разработчик и разбираешься в порождающих грамматиках, компиляторах, синтаксическом и лексическом разборе.
Напиши EBNF грамматику для подмножества SQL:
1. Используй EBNF в диалекте стандарта ISO
2. Поддерживай только инструкцию SELECT без FROM, но с произвольными числовыми выражениями с арифметическими операторами, скобками, вызовами встроенных функций
Нюанс: ИИ плохо распознаёт дублирование информации #
Типовая ошибка — созданная ИИ-моделью грамматика содержит правила для описания лексики, хотя лексика уже описана в другом markdown-документе вашего репозитория.
- Последствия: лексические правила, описанные вместе с грамматикой, в лучшем случае дублируют информацию (нарушают принцип DRY), а в худшем случае — противоречат написанному в другом документе
- Решение: переместить EBNF правила для лексем в документ с описанием лексики языка и проверить на соответствие тексту документа