Как стать автором
Обновить

Есть 14 языков для хранения данных… Или как появился IEML

Уровень сложностиСредний
Время на прочтение4 мин
Количество просмотров2.6K

Предыстория

Велась как-то работа на одним движком для создания GUI, некоторым подобием Qt. Выделялся он тем, что конечный пользователь мог этот интерфейс кастомизировать с помощью конфига до самых мелочей.

Изначально в качества такого конфига был взят YAML, звучало разумно, простой для обывателя формат, справится, если не бабушка, то хотя бы слегка прошаренный геймер.

В процессе интеграции обнаружилось, что нам этого формата не хватает, да и некоторые другие его минусы стали проявляться. В итоге было решено создать свой формат.

Начало

Формат получил название IEML. Он частично вдохновлен YAML, поэтому стоит ожидать его частые упоминания в статье.

К нему был предъявлен ряд требований:

  • По максимуму сохранить визуальную простоту YAML

  • Быть строгим (не допускать отклонений от синтаксиса)

  • Быть явным (не иметь синтаксически пересекающихся типов данных)

  • Быть единообразным

  • Быть по минимуму избыточным

  • Иметь функционал для повышения читабельности и избежания копирования

Формат

Во имя простоты было принято решение сделать формат зависимым от отступов. Некоторые скажут, что такая запись подвержена ошибкам, но это не язык программирования, что быть иметь синтаксическую защиту от ошибок.

В качестве отступов была выбрана исключительно табуляция. Почему именно она - можно почитать здесь, также из этой же статьи можно понять почему выбор пал в сторону полного отказа от пробелов.

Большинство специальных последовательностей включают в себя пробелы, он обязательны, про этом лишние пробелы не пропускаются, в большинстве случаев они будут считаться за сырые данные или ошибку.

Между элементами возможны пустые линии, содержащие табуляцию, пробелы и комментарии.

Были сохранены почти все скалярные типы данных из YAML и добавлен 1 новый:

  • Булевые значения

  • Целые и дробные числа

  • Строки

  • Null

  • Сырые данные

У каждого из этих типов появились свои особенности и отклонения от их традиционного написания.

Все скалярные типы можно переносить на следующую строку, с соблюдением отступа, а все нескалярные можно записывать в одну, если они содержат всего один элемент.

Помимо возможностей и нескалярных типов YAML, образовалось два новых:

  • Списки

  • Словари

  • Якоря

  • Тэги

  • Файлы

Комментарии

Что бы не терять возможности добавления собственного типа для команд или файловых путей (Это мы обсудим позже) было решено обозначать комментарии с помощью #, но снова, что бы не терять возможности добавить тип hex-цвета, обязательным после этого должен идти или ! (Для возможности шебанга).

В итоге комментарии выглядят так:

#!Это комментарий
# Это комментарий
#А это уже ошибка

Булевые значения

Несмотря на практически однозначную распространенность true\false, выбор пал на yes\no.

Это проще для обывателя, это более точно подходит в большинстве контекстов, это короче.

Помимо этого формат обязует парсер позволять прочесть эти значения, как сырые данные, так что Norway Problem полностью решена.

Числа

Любое число должно содержать хотя бы одну цифру в целой части:

1 # 1 
1.0 # 1.0
1. # 1.0
.1 # Ошибка

Любое число содержащее . в мантиссе считается дробным. Да, числа поддерживают экпоненциальную запись, которая записывается с помощью буквы e .

Помимо этого стандарт позволяет записывать числа в любой системе счисления от 1 до 36. Для этого используется символ ' перед которым пишется система (в десятичной системе счисления), а после - число. Например:

2'101

Является числом 101 в двоичной системе.

Строки

Формат позволяет записать строку 3 различными способами:

  • Классический с использованием " и поддержкой экранирования

  • Не экранируемый с использованием >> и его короткая запись в одну строку с >

Оба способа поддерживают перенос на следующую строку, но требуют соблюдения уровня отступа.

Примеры:

"Hello Wolrd!
  " # "Hello World!\n "
>> # Здесь можно писать комментарии.
Hello World! # А вот это уже не комментарий, что бы строка кончилась должен быть понижен уровень отступа.

Null

Записывается с помощью null, тут все обыденно.

Сырые данные

Всегда являются однострочными. Записываются, если не удалось разобрать данные, как какую-либо другую часть языка, при этом все еще должен быть соблюден ряд условий, таких как не использование большинства спецсимволов языка.

Нужны, что бы вводить новые типы данных, например, hex-цвета, которые уже упоминались ранее:

#FFFF00

Списки

Требуют перед каждым элементом - . Например:

- null
- -10

Помимо этого присутствует короткая запись с помощью [] и с элементами через , , но список вложенных типов ограничен. (Нельзя использовать многострочные типы или типы поглощающую строку документа до конца)

[null, -10]

Словари

Ключом всегда является строка, если требуется какой-либо иной словарь необходимо использовать список.

Ключ и значение разделяются : .

first: null
second: -1

Тэги

Тэг это небольшая строчка дополнительной полезной информации, которая не занимает много места.

Тэг всегда начинается с = и заканчивается : , пишется перед значением, которому присваивает тэг.

- = tag: null
- 
	first: = other tag: -15

Якоря

YAML развил эту концепцию не до конца.

Обозначаются они также с помощью & для взятия и * для получения, но в отличии от YAML они способны находиться в любом порядке и поэтому затенение в одном файле недопустимо.

- *anchor # Здесь тоже находится "Hello"
- &anchor > Hello

И это еще не все.

Файлы

Формат предоставляет механизм по включению файлов. Это позволяет бить большие файлы на меньшие, тем самым делая чтение проще.

Но что еще важнее, эти файлы интегрированы с якорями, каждый файл создает область видимости для якорей, все якоря из родительских файлов видны в дочерних, но не наоборот.

И что еще важнее это позволяет шаблонизировать данные, включая файлы несколько раз с разными якорями. Поэтому при включении файлов имеется специальный синтаксис для передачи якорей исключительно внутрь файла.

Что бы включить файл необходимо написать < , затем путь к файлу, но без расширения, расширения файлов фиксированы, поэтому необходимость их указывать отпала. Если нужно передать якоря, то сразу после включения файла на соответствующем уровне отступа пишется словарь, в котором имена ключей являются именами якорей, а значения - содержимым якорей.

Обычное включение файла:

< path/file-name

Включение файла с передачей якорей:

< path/file-name
first-anchor: null
second-anchor: -15

Сравнение

IEML

YAML

JSON5

TOML

Числа в различных системах исчисления

+

+

+

-

Числа в любых системах исчисления

+

-

-

-

Null

+

+

-

-

Неэкранируемые строки

+

-

-

+

Тэги

+

+

-

-

Якоря

+

+

-

-

Файлы

+

-

-

-

Полноценная графовая структура документа

+

-

-

-

Единообразность

+

-

+

-

Явность

+

-

+

+

Высокая скорость работы

-

-

+

-

Легковесность

-

-

+

-

Тип Дата и время

-

+

-

+

Реализации

На данный момент существует всего одна реализация на C++, но уже пишется реализация для Rust. В будущем планируется добавить реализацию для PHP. Но остальные языки - надежда лишь на энтузиастов из комьюнити.

Итог

Возможно формат вышел не идеальным, но по моему личному мнению - добротным, применимым, но не везде. Буду рад критике в комментариях.

Теги:
Хабы:
Всего голосов 5: ↑3 и ↓2+1
Комментарии27

Публикации

Истории

Ближайшие события

One day offer от ВСК
Дата16 – 17 мая
Время09:00 – 18:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн
Антиконференция X5 Future Night
Дата30 мая
Время11:00 – 23:00
Место
Онлайн
Конференция «IT IS CONF 2024»
Дата20 июня
Время09:00 – 19:00
Место
Екатеринбург
Summer Merge
Дата28 – 30 июня
Время11:00
Место
Ульяновская область