1
0
mirror of https://github.com/Nivanchenko/tokenizer.git synced 2024-12-16 10:19:30 +02:00
tokenizer/README.md
Nikita Ivanchenko 741bc23e8d
Update README.md
2024-07-06 19:35:15 +03:00

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");
Текст = ЧтениеТекста.Прочитать();
ЧтениеТекста.Закрыть();
Токенайзер.Инит(Текст);
Скобарь = Новый ПарсерСкобки(Токенайзер);
Результат = Скобарь.Распарсить();
```
Результатом парсинга будет массив, содержащий записи ЖР, каждая запись - массив, содержащий поля записи. С поддержкой вложенности массивов.