mirror of
https://github.com/Nivanchenko/tokenizer.git
synced 2024-11-19 17:12:17 +02:00
Токенайзер(лексер) на языке OneScript
.github/workflows | ||
src | ||
tasks | ||
tests | ||
.gitignore | ||
packagedef | ||
README.md |
tokenizer
Токенайзер - простой пакет для разбиения строки на токены. Задача, которую он решает - разбиение строки на токены, по определенной спецификации.
Примеры использования
Разбиение простой строки 1,2,3
на токены:
Строка = "1,2,3";
Спека = Новый Массив();
Спека.Добавить(Новый СпецификацияТокенЧисло());
Спека.Добавить(Новый СпецификацияТокенСимвол(",", "Запятая"));
Токенайзер = Новый Токенайзер(Спека);
Токенайзер.Инит(Строка);
Результат = Новый Массив();
Пока Токенайзер.ЕстьЕщеТокены() Цикл
Результат.Добавить(Токенайзер.СледующийТокен());
КонецЦикла;
В результате выполнения этого кода массив Результат
будет содержать пять элементов с типом Токен
.
API
API объекта Токен
следующий:
Значение()
- возвращает значение токена.ТипТокена()
- возвращает тип токена.Начало()
- возвращает позицию токена в тексте.Размер()
- возвращает длину токена в тексте.
API объекта Токенайзер
следующий:
Инит(Строка)
- инициализирует Токенайзер строкой.СледующийТокен()
- возвращает следующий токен.ЕстьЕщеТокены()
- возвращаетИстина
, если есть еще токены.
В конструктор Токенайзер
передается спецификация токенов. Спецификация токенов - это массив объектов, реализующих интерфейс СпецификацияТокена
.
Интерфейс СпецификацияТокена
описывает следующие методы:
Функция Проверить(Знач Строка) Экспорт
Если УдалосьНайтиТокенВСтроке Тогда
Возврат Новый Структура("Значение, Размер", "ЗначениеТокена", ДлинаТокена);
КонецЕсли;
Возврат Неопределено;
КонецФункции
Функция ТипТокена() Экспорт
Возврат "МойКастомныйТипТокена";
КонецФункции
"Типовые" токены
Поставляемые вместе с пакетом спецификации токенов:
СпецификацияТокенСимвол
- спецификация токена, который содержит один символ. В конструктуор передается символ и тип токена.СпецификацияТокенЧисло
- спецификация токена, который содержит целое число.СпецификацияТокенСтрока
- спецификация токена, который содержит строку. В конструктор передается экранирующий внутренние ковычки символ. Поддерживаемые экранируемые символы:\
,""""
.СпецификацияТокенИдентификатор
- спецификация токена, который содержит идентификатор, т.е. строка начинающаяся с буквы и содержит буквы и цифры.СпецификацияТокенПробелы
- спецификация токена, который содержит пробел. В конструктор передается флаг, который указывает, нужно ли пропускать пробелы или нет.СпецификацияТокенРегулярноеВыражение
- спецификация токена, который содержит строку, соответствующую регулярному выражению. В конструктор передается регулярное выражение и тип токена.
Пример токенизации и парсинга журнала регистрации
small.lgp
1CV8LOG(ver 2.0)
758d6f0a-476f-468b-80ac-48773092049c
{20221110000049,N,
{2444a6a24da10,3d},1,1,1,1803214,81,I,"Первое событие",599,
{"U"},"Представление данных",1,1,9,3,0,
{0}
},
{20221110000049,U,
{2444a6a24da10,3d},1,1,1,1803214,81,E,"Второе ""событие""
многострочное ",599,
{"U"},"Представление данных2",1,1,9,3,0,
{2,1,31,2,31}
}
ПарсерСкобки.os
Перем _Токенайзер;
Перем ПрошлиЗаголовок;
Процедура ПриСозданииОбъекта(Токенайзер)
_Токенайзер = Токенайзер;
ПрошлиЗаголовок = Ложь;
КонецПроцедуры
Функция Распарсить() Экспорт
ТекущийМассив = Новый Массив();
Пока _Токенайзер.ЕстьЕщеТокены() Цикл
Токен = _Токенайзер.СледующийТокен();
Если ПрошлиЗаголовок = Ложь И Не Токен.ТипТокена() = "Открыть" Тогда
Продолжить;
КонецЕсли;
ПрошлиЗаголовок = Истина;
Если Токен.ТипТокена() = "Открыть" Тогда
ТекущийМассив.Добавить(Распарсить());
Продолжить;
КонецЕсли;
Если Токен.ТипТокена() = "Идентификатор"
ИЛИ Токен.ТипТокена() = "Число"
ИЛИ Токен.ТипТокена() = "Строка" Тогда
ТекущийМассив.Добавить(Токен.Значение());
КонецЕсли;
Если Токен.ТипТокена() = "Закрыть" Тогда
Возврат ТекущийМассив;
КонецЕсли;
КонецЦикла;
Возврат ТекущийМассив;
КонецФункции
Main.os
Спека = Новый Массив();
Спека.Добавить(Новый СпецификацияТокенПробелы(Истина));
Спека.Добавить(Новый СпецификацияТокенСимвол("{", "Открыть"));
Спека.Добавить(Новый СпецификацияТокенСимвол("}", "Закрыть"));
Спека.Добавить(Новый СпецификацияТокенСимвол(",", "Запятая"));
Спека.Добавить(Новый СпецификацияТокенРегулярноеВыражение(Новый РегулярноеВыражение("(1CV8LOG)|(\(\w+ \d.\d\))"), "Версия"));
Спека.Добавить(Новый СпецификацияТокенРегулярноеВыражение(Новый РегулярноеВыражение("[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$"), "Гуид"));
Спека.Добавить(Новый СпецификацияТокенРегулярноеВыражение(Новый РегулярноеВыражение("[\da-z]+"), "Идентификатор"));
Спека.Добавить(Новый СпецификацияТокенСтрока());
Спека.Добавить(Новый СпецификацияТокенЧисло());
Спека.Добавить(Новый СпецификацияТокенСимвол(Символы.ПС, "ПереносСтроки"));
Токенайзер = Новый Токенайзер(Спека);
ЧтениеТекста = Новый ЧтениеТекста("small.lgp");
Текст = ЧтениеТекста.Прочитать();
ЧтениеТекста.Закрыть();
Токенайзер.Инит(Текст);
Скобарь = Новый ПарсерСкобки(Токенайзер);
Результат = Скобарь.Распарсить();
Результатом парсинга будет массив, содержащий записи ЖР, каждая запись - массив, содержащий поля записи. С поддержкой вложенности массивов.