Формальное описание синтаксиса атрибута Citeck Records
Терминология
Контекст - область, которая выделена с помощью скобок или кавычек
{},[],(),"",''или не выделена ничем (корневая область или корневой контекст);Алиас - псевдоним для атрибута. Пример: в конструкции
someAlias:namesomeAlias является алиасом и возможный результат вычисления -someAlias:"Договор №2";Экранирование символа - добавление перед символом знака
\. Необходимо в тех случаях, когда спец-символ должен быть обработан как обычный символ;Спец-символ - символ, который в определенном контексте имеет специальное значение.
Скаляр - конечный атрибут, который не может содержать вложенных атрибутов. Может быть одним из
?id,?str,?disp,?num,?assoc,?localId,?bool,?json.
Примечание
Экранирование спец-символов необходимо только в текущем контексте и не требуется во вложенных контекстах.
Описание
Общий вид атрибута:
path0[].path1{INNER}|proc0(arg0,arg1)|proc1(arg0,arg1) (1)
path0[].path1 - путь из атрибутов. Элементы пути объединяются через точку. Если точка является частью имени атрибута, то её следует экранировать.
Все атрибуты в пути кроме последнего имеют ровно один внутренний атрибут без пост-процессоров и алиаса. Последний атрибут в пути может иметь любое количество вложенных атрибутов, но не имеет алиаса.
Все атрибуты в пути кроме первого не имеют пост-процессоров. Первый атрибут в пути может иметь любое количество пост-процессоров, которые указываются в конце после {INNER}.
Любой элемент пути из атрибутов может иметь окончание [], которое при наличии означает, что атрибут множественный.
{INNER} содержит вложенные атрибуты с алиасами, которые разделены через запятую. Алиас не обязателен. Если он отсутствует, то для результата используется первое имя в пути атрибутов.
Пример значения {INNER}:
{alias0:attribute0,alias1:attribute1,attribute2}
В aliasN спец-символами являются , и :. Вместо attributeN допускается синтаксис (1), но c экранированием запятых , и если отсутствует алиас, то следует экранировать : (см. Примечание 1). Если алиас равен первому элементу в пути атрибутов, то это равнозначно отсутствию алиаса.
Вместо {INNER} при наличии только одного вложенного атрибута без алиаса и процессоров допускается запись без фигурных скобок. В таком случае если вложенный атрибут не является скаляром, то перед ним добавляется точка. Перед скаляром ничего не добавляется т.к. он уже содержит разделительный символ ?.
Примеры:
name?str == name{?str}
name.title?str == name{title{?str}}
Если атрибут заканчивается на скаляр ?disp (att0?disp или att0{?disp}), то допускается опустить окончание ?disp в атрибуте т.к. это скаляр по умолчанию.
Пример:
name?disp == name
При описании атрибута допускается использование пост-процессоров, которые вызываются с результатом вычисления атрибута:
proc0(arg0,arg1)
procN - имя пост-процессора;
argN - аргументы, которые отделяются друг от друга запятыми. Допускаются значения аналогичные формату json - https://www.json.org/json-en.html , но с возможностью использовать для строк одинарные кавычки вместо двойных;
Пост-процессоры объединяются через символ | и выполняются слева направо аналогично unix pipeline. Пост-процессоры могут быть частью любого атрибута на любом уровне вложенности.
Для пост-процессора с типом «or» доступен дополнительный синтаксис с использованием !. Возможные варианты значения после !:
Значение в двойных или одинарных кавычках означает константную строку; (
some!'constant' == some|or('constant'))При отсутствии значения парсер подбирает нужный аргумент в зависимости от скаляра перед знаком
!:
?bool! ->
false?json! ->
{};?num! ->
0;иначе ->
"".
null означает пустое значение; (
some!null == some|or(null))true или false - булево значение; (
some!true == some|or(true))Если первый символ число - числовое значение; (
some!123 == some|or(123))Если ни один из вышестоящих вариантов не подошел, то считается, что указано имя атрибута, который нужно вернуть в случае если результат вычисления атрибута до
!оказался null; (some!other == some|or('a:other'))
Между частями атрибута (алиас, путь, вложенные атрибуты, пост-процессоры, аргументы) допускается использование любого количества пробельных символов (\n, \t, \r, ).
Модель атрибута:
SchemaAtt {
alias: String,
name: String,
multiple: Boolean,
inner: List<SchemaAtt>,
processors: List<AttProcDef>
}
Модель пост-процессора:
AttProcDef {
type: String,
arguments: List<DataValue>
}
DataValue - любой json тип - https://www.json.org/json-en.html