Що таке OT?

Тиждень самописних мов розмітки на Хабрахабре. Стаття про AXON нагадала мені про мій проектик
o.t
— object language template. В ньому я поєднав цікаві ідеї з XML, YAML та інших.
Що, ще один?
Велосипеди бувають різні. Мені, наприклад, було цікаво спробувати створити саме мова опису даних і в якійсь мірі мову розмітки.
TL;DR
<note status="saved">
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>don't forget me this weekend!</body>
</note>

note:
status :: saved;
to: "Tove";
from: "Jani";
heading: 'Reminder';
body: `don't forget me this weekend!`;
;

Концепція
Спочатку хотілося щось типу мови програмування всередині DOM, щоб код завжди виконувався в контексті того чи іншого сайту, щоб можна було здійснювати навігацію по DOM керуючими інструкціями мови, змінні та об'єкти рантайм маппит в DOM-вузол контексту і т. д. і т. п. У підсумку перший варіант концепції успішно вилетів з пам'яті.
Другий варіант набагато простіше і взагалі не про програмування як таке. Він радше про шаблони в тому вигляді, в якому вони представлені в технології JSP, коли xhtml перемішується з керуючими елементами. При цьому помічено, що jsp непогано підходить для чистої шаблонізації без програмування. Але там же XML, великий і жахливий.
А що є на заміну крім JSON, YAML і TOML (.ini на стероїдах)? Перший описує примітивні типи, об'єкти та масиви javascript, другий робить те ж саме, але без курли-скобочек, а третій взагалі не про те.
Від XML їх відрізняє лише одне, вони описують об'єкт через його властивості. Передбачається при цьому, що при необхідності користувач додасть об'єкту поле
type
і опише клас об'єкта. У XML об'єкт описується як безпосередньо екземпляр класу і потім при необхідності можуть бути вказані додаткові поля, типу ідентифікатора.
Що ж буде, якщо об'єднати простоту YAML і концепцію об'єктів з XML? Правильно — object language template, експериментальний человекочитаемый мова опису даних, структур і шаблонів.
O. T.
Схематично весь OT можна описати одним рядком
module~class(id): content;
тобто це модульний мова рекурсивних об'єктних шаблонів. Крім цього, присутні додаткові типи даних крім рядків і відсутні асоціативні масиви, які об'єкти типу з JSON, як неконцептуальная сутність.
Крім текстових ідентифікаторів, строкових, булевих, цілих і дійсних констант присутні деякі символи, що дозволяють описувати деревоподібні структури об'єктів (object model). Так само присутній посилальний тип для побудови інших видів структур-графів.
Будь порожній простір між ідентифікаторами, групами ідентифікаторів, символами розмітки і константами ігнорується і використовується для поділу значущих символів, але не включається в зміст об'єкту. Всередині символів-лапок будь порожній простір враховується.
Об'єктна модель
Будь-шаблон являє собою один об'єкт, який є кореневим. Будь-який об'єкт, у т. ч. кореневої, здається як мінімум ідентифікатором класу об'єкта і опціонально ідентифікаторами модуля і унікальним ідентифікатором об'єкта:
module~class(id)

Наприклад, для html-сторінок існує об'єкт класу
body
, який може бути предварен ідентифікатором модуля, з якого взято цей клас (
html~body
). Цей об'єкт наділяється ідентифікатором
index-page
, за яким можна встановити зв'язок з об'єктом через посилання
@index-page
.
body
html~body
html~body(index-page)
@index-page

Об'єкти можуть бути вкладені один в одного, таким чином перший об'єкт буде містити в собі другий об'єкт, встановлюється зв'язок батько-нащадок.
html:
body
;

Внутрішній вміст об'єкта починається після символу
:
. Весь вміст аж до відповідного символу
;
буде вважатися належним об'єкту-батькові. Якщо об'єкт не передбачає вмісту, символи
:;
не зазначаються.
При цьому важливо пам'ятати, що обов'язковим для будь-якого об'єкта є ідентифікатор класу об'єкта, тобто, два і більше однакових ідентифікатора класу в шаблоні будуть відповідати двом і більше екземплярів класу.
html:
body: br br br;
;

Повторне використання

Для об'єктів, вміст яких може бути описано у кількох місцях шаблону, можливо вказати такий режим опису вмісту, при якому створення нового екземпляра класу не буде проводитися, і весь вміст буде належати одному примірнику даного класу в рамках батьківського об'єкта. Це досягається використанням символу
::
відкриває вміст.
xml:
attr ::
id: "my-xml";
;
attr ::
xmlns: "urn:oberon:ot";
;
;

В режимі повторного використання враховуються не тільки клас але й інші параметри об'єкта, його модуль і ідентифікатор.
вміст
Крім об'єктів-нащадків, батьківський об'єкт можуть бути включені різні константи і посилання на об'єкти. При цьому для розділення окремих елементів вмісту використовується порожній простір.
html:
head:
title: "Привіт, Світ!";
;
body:
p: 2 "+" 2 "=" 4.0;
concat: "Привіт":':':"World":"!";
;
;

Текстове вміст вказується в лапках різних типів:
'
,
"
, і `, при цьому можливе зазначення окремих символів тексту в одинарних лапках
'
та за допомогою шістнадцяткового коду (наприклад
0DU
) з модифікатором
U
на кінці. Текст може містити переноси рядків і будь-які інші символи unicode. Є можливість конкатенації рядків і символів за допомогою символу
:
розташованого між двома і більше частинами рядків. Результуючий рядок буде представлена в об'єктній моделі як один рядок.
Модульність
Модульність у найпростішому вигляді дозволяє візуально розділяти однойменні класи об'єктів різної природи. Наприклад,
html~body
та
human~body
. Модульність в об'єктній моделі припускає також наявність підтримки контекстом деяких модулів, розширена функціональність яких дозволяє розширити можливості роботи з шаблоном у рантайме.

Стандартні модулі і класи

Стандартні модулі надають додаткові можливості рантайма для об'єктної моделі.
core
Модуль
core
є вбудованим модулем, а так само базовим модулем. Для початку використання модуля
core
необхідно створити екземпляр класу
core~template
як кореневий об'єкт шаблону. Тим самим вміст кореневого елемента зможе звертатися до класів модуля
core
. В інших випадках функціональність модуля
core
вимкнено.
core~template:
(* вміст *)
;

Модуль
core
містить клас
import
, який дозволяє описувати залежності шаблону від сторонніх шаблонів (стандартних, користувача, віртуальних і т. д.).
core~template:
import: context;
;

Всередині об'єкта типу
core~template
діє неявне вказівку модуля для відомих класів, таких як
import
і для імпортованих класів діє таке ж правило, тому немає необхідності (але залишається можливість) вказувати модуль
core
та інші імпортовані модулі кожен раз.
Наприклад:
core~template:
import: html;
html: body: p: "Привіт, Світ!";;;
;

Класи
html
,
body
та
p
належать модуля
html
та їх приналежність контролюється рантаймом, але при цьому вказувати їх модуль явно не потрібно.
Шаблонизация і користувальницькі дані

context

Модуль
core
містить клас
context
, який є ідентифікатором модуля
context
.
Модуль
context
надає доступ до даних контексту існування об'єктної моделі. Звернення до об'єктів моделі через спеціальні класи модуля
context
дозволить розміщувати у вмісті шаблону дані з рантайма.
Наприклад, клас
context~$
дозволяє звернутися до даних контексту ідентифікатора або ієрархічним набору ідентифікаторів.
core~template:
import: context;
$(hello-world-text)`, `$(user-names/hello-world-user)`!`
;

Таким чином, в залежності від даних, розміщених в контексті яким-небудь чином і доступних за заданим ідентифікаторів, після обробки тексту шаблону і побудови об'єктної моделі ми отримаємо підсумковий об'єкт з заданими значеннями.
core~template:
import: context;
`Привіт` `, ` `Дружок` `!`
;

Реалізація
Перший прототип парсера був написаний на golang, поруч були реалізовані деякі шаблонні модулі,
core
звичайно, і ще модуль зберігання бінарної інформації у вигляді zbase32-рядки, відмінний формат, заслуговує окремої згадки дизайн-документ цього формату, як ретельно люди аналізували ситуацію з форматами baseXXX.
Надалі, був реалізований неповний прототип парсера OT для javascript, який став основою для мови опису структурних атомів в мові… а втім, це вже інша історія.
Посилання
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.