Расширенный INI-формат для хранения данных, разработанный компанией Blizzard Entertainment.
Формат
Формат практически ничем не отличается от INI за исключением некоторых различий. Рассмотрим классический INI. Как видите, здесь всё просто. Имя секции обёрнутое в [] и пара ключ=значение. Формат разбирается построчно и не допускает значений из нескольких строк. По сути значением является всё после первого знака = в строке.
Такой формат позволяет очень быстро читать значения за O(n) довольно простыми алгоритмами.
; Comment
[Section1]
key1=value1
key2=value2
keyN=valueN
[Section2]
key1=value1
key2=value2
keyN=valueN
Комментарии
В формате BNI было решено изменить начинающий символ комментариев на классический двойной слэш // и разрешить использовать их в строке значения.
// Comment
[Section]
key=value // Another comment
Ключи
Формат BNI допускает одинаковые имена ключей или вообще отсутствие оных.
[Section]
key=value
key=value1
=value3
=value4
Значения
Формально значением является всё от первого знака = до конца строки. И если вы будете описывать формальную грамматику, то так и опишите токен для лексера.
Для того чтоб компактно хранить данные Blizzard пришлось немного расширить значения и ввести следующие типы:
string | Захватывает всё до символа ,, конца строки или начала комментария //. Крайние пробелы игнорируются. |
text | Все символы между одинарными ', двойными " и обратными кавычками `. Экранирование не поддерживается. |
comment | Комментарии, которые начинаются с двойного слэша // и захватывают все символы до конца строки. Поддерживаются в конце значений. |
Для примера, возьмём такое значение:
test= Какой-то текст , " Запятая, текст кавычках " , Ещё один текст // Комментарий
При разборе оно будет представлено в виде массива со следующими элементами:
- Какой-то текст
- Запятая, текст кавычках тут должны быть пробелы но разметка их сожрала
- Ещё один текст
Обратите внимания как захватываются крайние пробелы.
Парсинг
Проще всего парсить значения посимвольно с помощью конечного автомата с тремя состояниями - search, string, text.
Устанавливаем автомат в значение search и начинаем искать первый символ который переключит состояние:
- Любой не пробельный символ кроме , включает состояние string, в котором ждём , или конец строки для возврата в состояние search.
- Любой символ кавычек включает состояние text и ожидает именно этот символ кавычек для перехода в состояние search.
При любом пробельном символе в состояниях search, string смотрим следующие два символа на наличие //. Иначе можно неправильно обработать такой слуйчай:
BlizzardLink=http://www.blizzard.com/
VSCode
Поддержка BNI реализована в плагине для VSCode.
*.txt
Blizzard не стали изобретать новое расширение для этого вормата, а использовали .txt, чем создали многие неудобства. Плагин не привязан к расширению файла и вы конечно можете переключать язык каждому файлу отдельно, но это слишком неудобно, когда таких файлов много.
Проще найти настройку files.associations и указать язык bni для шаблона *.txt.