Эффективный алгоритм для преобразования набора символов в nfa / dfa

В настоящее время я работаю над генератором сканера. Генератор уже работает нормально. Но при использовании классов символов алгоритм становится очень медленным.

Генератор сканера создает сканер для файлов в кодировке UTF8. Должен поддерживаться полный диапазон символов (от 0x000000 до 0x10ffff).

Если я использую большие наборы символов, например, оператор any '.' или свойство unicode {L}, nfa (а также dfa) содержит много состояний (> 10000). Таким образом, преобразование nfa в dfa и создание минимального dfa занимает много времени (даже если выходной минимальный dfa содержит только несколько состояний).

Вот моя текущая реализация создания части набора символов nfa.

void CreateNfaPart(int startStateIndex, int endStateIndex, Set<int> characters)
{
transitions[startStateIndex] = CreateEmptyTransitionsArray();
foreach (int character in characters) {
    // get the utf8 encoded bytes for the character
    byte[] encoded = EncodingHelper.EncodeCharacter(character);
    int tStartStateIndex = startStateIndex;
    for (int i = 0; i < encoded.Length - 1; i++) {
        int tEndStateIndex = transitions[tStartStateIndex][encoded[i]];
        if (tEndStateIndex == -1) {
           tEndStateIndex = CreateState();
               transitions[tEndStateIndex] = CreateEmptyTransitionsArray();
        }                   
        transitions[tStartStateIndex][encoded[i]] = tEndStateIndex;
        tStartStateIndex = tEndStateIndex;
    }
    transitions[tStartStateIndex][encoded[encoded.Length - 1]] = endStateIndex;
}

Кто-нибудь знает, как реализовать функцию намного эффективнее, чтобы создавать только необходимые состояния?

РЕДАКТИРОВАТЬ:

Чтобы быть более конкретным Мне нужна функция как:

List<Set<byte>[]> Convert(Set<int> characters)
{
     ???????
}

Вспомогательная функция для преобразования символа (int) в байт кодировки UTF8 [] определяется как:

byte[] EncodeCharacter(int character)
{ ... }
9
задан raisyn 22 August 2010 в 00:47
поделиться

2 ответа

Посмотрите, что делают библиотеки регулярных выражений, такие как Google RE2 и TRE.

2
ответ дан 3 November 2019 в 07:11
поделиться

Есть несколько способов справиться с этим. Все они сводятся к одновременной обработке наборов символов в структурах данных вместо того, чтобы вообще перечислять весь алфавит. Это также то, как вы делаете сканеры для Unicode с разумным объемом памяти.

У вас есть много вариантов того, как представлять и обрабатывать наборы символов. В настоящее время я работаю с решением, в котором хранится упорядоченный список граничных условий и соответствующих целевых состояний. Вы можете обрабатывать операции над этими списками намного быстрее, чем если бы вам приходилось сканировать весь алфавит на каждом этапе. Фактически, он достаточно быстр, чтобы работать на Python с приемлемой скоростью.

3
ответ дан 3 November 2019 в 07:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: