1
0
mirror of https://github.com/Nivanchenko/tokenizer.git synced 2024-11-19 17:12:17 +02:00
Токенайзер(лексер) на языке OneScript
Go to file
Nikita Ivanchenko 741bc23e8d
Update README.md
2024-07-06 19:35:15 +03:00
.github/workflows Откатил на пуштокен 2024-07-06 19:20:39 +03:00
src ренейминг 2024-07-06 18:25:37 +03:00
tasks поправил имя таски 2024-07-06 18:32:26 +03:00
tests Тест на парсинг ЖР 2024-07-06 18:50:57 +03:00
.gitignore v1 2024-07-06 15:52:03 +03:00
packagedef Откатил на пуштокен 2024-07-06 19:20:39 +03:00
README.md Update README.md 2024-07-06 19:35:15 +03:00

tokenizer

Токенайзер - простой пакет для разбиения строки на токены. Задача, которую он решает - разбиение строки на токены, по определенной спецификации.

Примеры использования

Разбиение простой строки 1,2,3 на токены:

Строка = "1,2,3";

Спека = Новый Массив();
Спека.Добавить(Новый СпецификацияТокенЧисло());
Спека.Добавить(Новый СпецификацияТокенСимвол(",", "Запятая"));

Токенайзер = Новый Токенайзер(Спека);

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

Результат = Новый Массив();

Пока Токенайзер.ЕстьЕщеТокены() Цикл
    Результат.Добавить(Токенайзер.СледующийТокен());
КонецЦикла;

В результате выполнения этого кода массив Результат будет содержать пять элементов с типом Токен.

API

API объекта Токен следующий:

  1. Значение() - возвращает значение токена.
  2. ТипТокена() - возвращает тип токена.
  3. Начало() - возвращает позицию токена в тексте.
  4. Размер() - возвращает длину токена в тексте.

API объекта Токенайзер следующий:

  1. Инит(Строка) - инициализирует Токенайзер строкой.
  2. СледующийТокен() - возвращает следующий токен.
  3. ЕстьЕщеТокены() - возвращает Истина, если есть еще токены.

В конструктор Токенайзер передается спецификация токенов. Спецификация токенов - это массив объектов, реализующих интерфейс СпецификацияТокена.

Интерфейс СпецификацияТокена описывает следующие методы:

Функция Проверить(Знач Строка) Экспорт

	Если УдалосьНайтиТокенВСтроке Тогда

		Возврат Новый Структура("Значение, Размер", "ЗначениеТокена", ДлинаТокена);

	КонецЕсли;

	Возврат Неопределено;

КонецФункции

Функция ТипТокена() Экспорт
	Возврат "МойКастомныйТипТокена";
КонецФункции

"Типовые" токены

Поставляемые вместе с пакетом спецификации токенов:

  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

Перем _Токенайзер;
Перем ПрошлиЗаголовок;

Процедура ПриСозданииОбъекта(Токенайзер)
	_Токенайзер = Токенайзер;
	ПрошлиЗаголовок = Ложь;
КонецПроцедуры

Функция Распарсить() Экспорт
	ТекущийМассив = Новый Массив();

	Пока _Токенайзер.ЕстьЕщеТокены() Цикл

		Токен = _Токенайзер.СледующийТокен();

		Если ПрошлиЗаголовок = Ложь И Не Токен.ТипТокена() = "Открыть" Тогда
			Продолжить;
		КонецЕсли;

		ПрошлиЗаголовок = Истина;

		Если Токен.ТипТокена() = "Открыть" Тогда
			ТекущийМассив.Добавить(Распарсить());
			Продолжить;
		КонецЕсли;

		Если Токен.ТипТокена() = "Идентификатор" 
				ИЛИ Токен.ТипТокена() = "Число"
				ИЛИ Токен.ТипТокена() = "Строка"  Тогда
			ТекущийМассив.Добавить(Токен.Значение());
		КонецЕсли;

		Если Токен.ТипТокена() = "Закрыть" Тогда
			Возврат ТекущийМассив; 
		КонецЕсли;

	КонецЦикла;

	Возврат ТекущийМассив;

КонецФункции

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

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

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

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