Нотация с синтаксическим сахаром

// Основная нотация канонической формы описания синтаксиса языка Денеб.
// Нотация может располагаться в файле с расширением ".nuss" (The notation using syntax sugar).
// Нотация с синтаксическим сахаром является основой свободного синтаксиса языка Денеб.
// Нотация описана в стиле литературного программирования.
// Данный текст нотации можно использовать непосредственно для автоматической обработки.
// Нотация описана рекурсивно на самой себе.

// == Нотация ==
// Словарь является основой нотации.
// Словарь содержит список определений лексем, комментарии и пробелы форматирования.
Словарь := (ОпределениеЛексемы / Комментарий / %Пробел)*;

// == Словарь ==
// Определение лексемы основная деталь словаря.
// Определение лексемы представляет собой последовательность из лексемы и определения.
// Определение заключено в скобки определения ":=" ";".
// Между лексемой, скобками и определением могут находится пробелы.
ОпределениеЛексемы := Лексема %Пробел %НачалоОпределения %Пробел Определение %Пробел %ОкончаниеОпределения;
// Комментарий предназначен для пояснения к исходному тексту нотации.
// Комментарий может быть однострочным и многострочным.
Комментарий := ОднострочныйКомментарий / МногострочныйКомментарий;
// Пробел используется для форматирования нотации.
// Пробел представляет из себя список символов пробела, символов табуляции, символов переноса строки и символов возврата каретки.
Пробел := (СимволПробела / СимволТабуляции / СимволВозвратаКаретки / СимволПереносаСтроки)*;

// == Определение лексемы ==
// Лексема это имя конструкции языка.
// Лексема может начинаться с символа исключенной лексемы, что означает что лексема исключается из результата.
// Лексема содержит не менее одного символа лексемы.
Лексема := ИсключеннаяЛексема- СимволЛексемы+;
// Начало определения ":="
НачалоОпределения := ":=";
// Определение является описанием содержимого лексемы.
// Определение может быть выбором, списком, повторением, лексемой, символами, строкой, регулярным выражением или выражением в скобках.
Определение := Выбор / Список / Повторение / Лексема / Символы / Строка / РегулярноеВыражение / Блок;
// Окончание определения ";"
ОкончаниеОпределения := ";";

// == Комментарий ==
// Однострочный комментарий
ОднострочныйКомментарий := %НачалоОднострочногоКомментария ЛюбыеСимволы!* %ОкончаниеОднострочногоКомментария;
// Многострочный комментарий
МногострочныйКомментарий := %НачалоМногострочногоКомментария ЛюбыеСимволы!* %ОкончаниеМногострочногоКомментария;

// == Пробел ==
СимволПробела := " ";
СимволТабуляции := "№9";
СимволВозвратаКаретки := "№13";
СимволПереносаСтроки := "№10";

// == Лексема ==
// Смволом исключенной лексемы является "%"
ИсключеннаяЛексема := "%";
// Символом лексемы может являтся любой кирилический символ из основного набора Unicode
СимволЛексемы := "№1024;":"№1319;";

// == Определение ==
// Выбор означает в качестве содержимого один из перечисленных вариантов.
// Варианты разделены символом '/'.
// Выбор содержит не менее двух вариантов.
Выбор := (Вариант _ %Пробел %РазделительВыбора %Пробел)2+;
// Список означает в качестве содержимого расположенные по порядку пункты.
// Пункты могут быть разделены пробелом.
// Список содержит не менее двух пунктов.
Список := (Пункт _ %Пробел)2+;
// Повторение означает в качестве содержимого некоторое повторяющееся содержимое.
Повторение := Элемент %Пробел Щедрость- %Пробел Количество;
// Символы означает один из набора символов указывается начальный и конечный символ набора заключенные в кавычки и разделенные двоеточием.
Символы := %НачалоСимвола Литерал %ОкончаниеСимвола %Пробел %РазделительДиапазона %Пробел %НачалоСимвола Литерал %ОкончаниеСимвола;
// Строка последовательность символов заключенная в кавычки
Строка := %НачалоСтроки Литерал+ %ОкончаниеСтроки;
// Регулярное выражение
РегулярноеВыражение := %МеткаРегулярногоВыражения %НачалоСтроки Литерал+ %ОкончаниеСтроки;
// Блок
Блок := %НачалоБлока Определение %ОкончаниеБлока;

// == Однострочный комментарий ==
// Начало однострочного комментария
НачалоОднострочногоКомментария := "//";
// Любые символы
ЛюбыеСимволы := "№0":"№65535";
// Окончание однострочного комментария
ОкончаниеОднострочногоКомментария := СимволВозвратаКаретки СимволПереносаСтроки / СимволПереносаСтроки СимволВозвратаКаретки / СимволВозвратаКаретки / СимволПереносаСтроки;

// == Многострочный комментарий ==
// Начало многострочного комментария
НачалоМногострочногоКомментария := "/*";
// Окончание многострочного комментария
ОкончаниеМногострочногоКомментария := "*/";

// == Выбор ==
// Вариант
Вариант := Список / Повторение / Лексема / Символы / Строка / РегулярноеВыражение / Блок;
// Разделитель выбора
РазделительВыбора := "/";

// == Список ==
Пункт := Выбор / Повторение / Лексема / Символы / Строка / РегулярноеВыражение / Блок;

// == Повторение ==
// Элемент
Элемент := Лексема / Блок / БлокПовторения;
// Щедрость
Щедрость := "!";
// Количество
Количество := ЛюбоеКоличество / СписокДиапазонов / БолееОдного / НеБолееОдного / Число / Диапазон / ОграничениеСверху / ОграничениеСнизу;

// == Символы ==
// Начало символа
НачалоСимвола := Кавычка; "№34;";
// Литерал
Литерал := КодСимвола / ЛюбыеСимволы;
// Окончание символа
ОкончаниеСимвола := Кавычка;
// Разделитель диапазона
РазделительДиапазона := ":" / ".."

// == Строка ==
// Начало строки
НачалоСтроки = Кавычка;
// Окончание строки
ОкончаниеСтроки = Кавычка;

// == Регулярное выражение ==
// Метка регулярного выражения
МеткаРегулярногоВыражения := "№";

// == Блок ==
// Начало блока
НачалоБлока := "(";
// Окончание блока
ОкончаниеБлока := ")";

// == Элемент ==
// Блок повторения
БлокПовторения := %НачалоБлока Определение %Клей Определение %ОкончаниеБлока;

// == Количество ==
// Любое количество
ЛюбоеКоличество := "*";
// Более одного
БолееОдного := СимволОграниченияСнизу;
// Не более одного
НеБолееОдного := СимволОграниченияСверху / ДополнительныйСимволОграниченияСверху;
// Число
Число := Цифра+;
// Список диапазонов
СписокДиапазонов := (Число / Диапазон / ОграничениеСверху / ОграничениеСнизу _ %Пробел %РазделительДиапазонов %Пробел)2+;
// Диапазон
Диапазон := Число %Пробел %РазделительДиапазона %Пробел Число;
// Ограничение сверху
ОграничениеСверху := Число %Пробел СимволОграниченияСверху;
// Ограничение снизу
ОграничениеСнизу := Число %Пробел СимволОграниченияСнизу;

// == Начало символа ==
// Кавычка
Кавычка := "№34;";

// == Литерал ==
// Код символа
КодСимвола := %НачалоКодаСимвола Число %ОкончаниеКодаСимвола;

// == Блок повторения ==
// Клей
Клей := "_";

// == Более одного ==
// Символ ограничения снизу
СимволОграниченияСнизу = "+";

// == Не более одного ==
// Символ ограничения сверху
СимволОграниченияСверху := "-";
// Дополнительный символ ограничения сверху
ДополнительныйСимволОграниченияСверху := "?";

// == Число ==
// Цифра
Цифра := "0":"9";

// == Список диапазонов ==
РазделительДиапазонов := ",";

// == Код символа ==
// Начало кода символа
НачалоКодаСимвола := "№";
// Окончание кода символа
ОкончаниеКодаСимвола := ";";