An open API service indexing awesome lists of open source software.

https://github.com/nivanchenko/tokenizer

Токенайзер(лексер) на языке OneScript
https://github.com/nivanchenko/tokenizer

onescript oscript

Last synced: about 20 hours ago
JSON representation

Токенайзер(лексер) на языке OneScript

Awesome Lists containing this project

README

          

## 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");
Текст = ЧтениеТекста.Прочитать();
ЧтениеТекста.Закрыть();

Токенайзер.Инит(Текст);

Скобарь = Новый ПарсерСкобки(Токенайзер);
Результат = Скобарь.Распарсить();
```

Результатом парсинга будет массив, содержащий записи ЖР, каждая запись - массив, содержащий поля записи. С поддержкой вложенности массивов.