mirror of
https://github.com/Nivanchenko/tokenizer.git
synced 2024-12-16 10:19:30 +02:00
167 lines
8.7 KiB
Markdown
167 lines
8.7 KiB
Markdown
## tokenizer
|
|
|
|
Токенайзер - простой пакет для разбиения строки на токены. Задача, которую он решает - разбиение строки на токены, по определенной спецификации.
|
|
|
|
### Примеры использования
|
|
|
|
Разбиение простой строки `1,2,3` на токены:
|
|
|
|
```bsl
|
|
Строка = "1,2,3";
|
|
|
|
Спека = Новый Массив();
|
|
Спека.Добавить(Новый СпецификацияТокенЧисло());
|
|
Спека.Добавить(Новый СпецификацияТокенСимвол(",", "Запятая"));
|
|
|
|
Токенайзер = Новый Токенайзер(Спека);
|
|
|
|
Токенайзер.Инит(Строка);
|
|
|
|
Результат = Новый Массив();
|
|
|
|
Пока Токенайзер.ЕстьЕщеТокены() Цикл
|
|
Результат.Добавить(Токенайзер.СледующийТокен());
|
|
КонецЦикла;
|
|
```
|
|
|
|
В результате выполнения этого кода массив `Результат` будет содержать пять элементов с типом `Токен`.
|
|
|
|
### API
|
|
|
|
#### API объекта `Токен` следующий:
|
|
|
|
1. `Значение()` - возвращает значение токена.
|
|
2. `ТипТокена()` - возвращает тип токена.
|
|
3. `Начало()` - возвращает позицию токена в тексте.
|
|
4. `Размер()` - возвращает длину токена в тексте.
|
|
|
|
#### API объекта `Токенайзер` следующий:
|
|
|
|
1. `Инит(Строка)` - инициализирует Токенайзер строкой.
|
|
2. `СледующийТокен()` - возвращает следующий токен.
|
|
3. `ЕстьЕщеТокены()` - возвращает `Истина`, если есть еще токены.
|
|
|
|
В конструктор `Токенайзер` передается спецификация токенов. Спецификация токенов - это массив объектов, реализующих интерфейс `СпецификацияТокена`.
|
|
|
|
Интерфейс `СпецификацияТокена` описывает следующие методы:
|
|
|
|
```bsl
|
|
Функция Проверить(Знач Строка) Экспорт
|
|
|
|
Если УдалосьНайтиТокенВСтроке Тогда
|
|
|
|
Возврат Новый Структура("Значение, Размер", "ЗначениеТокена", ДлинаТокена);
|
|
|
|
КонецЕсли;
|
|
|
|
Возврат Неопределено;
|
|
|
|
КонецФункции
|
|
|
|
Функция ТипТокена() Экспорт
|
|
Возврат "МойКастомныйТипТокена";
|
|
КонецФункции
|
|
```
|
|
|
|
### "Типовые" токены
|
|
Поставляемые вместе с пакетом спецификации токенов:
|
|
|
|
1. `СпецификацияТокенСимвол` - спецификация токена, который содержит один символ. В конструктуор передается символ и тип токена.
|
|
2. `СпецификацияТокенЧисло` - спецификация токена, который содержит целое число.
|
|
3. `СпецификацияТокенСтрока` - спецификация токена, который содержит строку. В конструктор передается экранирующий внутренние ковычки символ. Поддерживаемые экранируемые символы: `\`, `""""`.
|
|
4. `СпецификацияТокенИдентификатор` - спецификация токена, который содержит идентификатор, т.е. строка начинающаяся с буквы и содержит буквы и цифры.
|
|
5. `СпецификацияТокенПробелы` - спецификация токена, который содержит пробел. В конструктор передается флаг, который указывает, нужно ли пропускать пробелы или нет.
|
|
6. `СпецификацияТокенРегулярноеВыражение` - спецификация токена, который содержит строку, соответствующую регулярному выражению. В конструктор передается регулярное выражение и тип токена.
|
|
|
|
### Пример токенизации и парсинга журнала регистрации
|
|
|
|
`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`
|
|
```bsl
|
|
Перем _Токенайзер;
|
|
Перем ПрошлиЗаголовок;
|
|
|
|
Процедура ПриСозданииОбъекта(Токенайзер)
|
|
_Токенайзер = Токенайзер;
|
|
ПрошлиЗаголовок = Ложь;
|
|
КонецПроцедуры
|
|
|
|
Функция Распарсить() Экспорт
|
|
ТекущийМассив = Новый Массив();
|
|
|
|
Пока _Токенайзер.ЕстьЕщеТокены() Цикл
|
|
|
|
Токен = _Токенайзер.СледующийТокен();
|
|
|
|
Если ПрошлиЗаголовок = Ложь И Не Токен.ТипТокена() = "Открыть" Тогда
|
|
Продолжить;
|
|
КонецЕсли;
|
|
|
|
ПрошлиЗаголовок = Истина;
|
|
|
|
Если Токен.ТипТокена() = "Открыть" Тогда
|
|
ТекущийМассив.Добавить(Распарсить());
|
|
Продолжить;
|
|
КонецЕсли;
|
|
|
|
Если Токен.ТипТокена() = "Идентификатор"
|
|
ИЛИ Токен.ТипТокена() = "Число"
|
|
ИЛИ Токен.ТипТокена() = "Строка" Тогда
|
|
ТекущийМассив.Добавить(Токен.Значение());
|
|
КонецЕсли;
|
|
|
|
Если Токен.ТипТокена() = "Закрыть" Тогда
|
|
Возврат ТекущийМассив;
|
|
КонецЕсли;
|
|
|
|
КонецЦикла;
|
|
|
|
Возврат ТекущийМассив;
|
|
|
|
КонецФункции
|
|
```
|
|
|
|
`Main.os`
|
|
```bsl
|
|
Спека = Новый Массив();
|
|
Спека.Добавить(Новый СпецификацияТокенПробелы(Истина));
|
|
Спека.Добавить(Новый СпецификацияТокенСимвол("{", "Открыть"));
|
|
Спека.Добавить(Новый СпецификацияТокенСимвол("}", "Закрыть"));
|
|
Спека.Добавить(Новый СпецификацияТокенСимвол(",", "Запятая"));
|
|
Спека.Добавить(Новый СпецификацияТокенРегулярноеВыражение(Новый РегулярноеВыражение("(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");
|
|
Текст = ЧтениеТекста.Прочитать();
|
|
ЧтениеТекста.Закрыть();
|
|
|
|
Токенайзер.Инит(Текст);
|
|
|
|
Скобарь = Новый ПарсерСкобки(Токенайзер);
|
|
Результат = Скобарь.Распарсить();
|
|
```
|
|
|
|
Результатом парсинга будет массив, содержащий записи ЖР, каждая запись - массив, содержащий поля записи. С поддержкой вложенности массивов.
|