Ответ 1
Короткая версия для общего подхода.
Там есть алгоритм под названием "Алгоритм построения Томпсона-МакНотона-Ямады", а иногда и просто "Конструкция Томпсона". Каждый строит промежуточные NFA, заполняя части по пути, соблюдая при этом приоритет оператора: сначала круглые скобки, затем Kleene Star (например, a *), затем конкатенация (например, ab), а затем чередование (например, a | b).
Здесь углубленное прохождение для построения (b | a) * b (a | b) NFA
Строительство верхнего уровня
-
Обрабатывать скобки. Примечание. В реальной реализации может иметь смысл обрабатывать скобки с помощью рекурсивного вызова их содержимого. Для ясности я отложу оценку всего, что находится внутри паренов.
-
Kleene Stars: там только один *, поэтому мы создаем заполнитель Kleene Star, называемый P (который позже будет содержать b | a). Промежуточный результат:
-
Объединение: Присоедините P к b и присоедините b к машине-заполнителю с именем Q (которая будет содержать (a | b). Промежуточный результат:
-
За скобками нет чередования, поэтому мы его пропускаем.
Теперь мы сидим на машине P * bQ. (Обратите внимание, что наши заполнители P и Q являются просто машинами конкатенации.) Мы заменяем ребро P на NFA для b | a, и заменяем ребро Q на NFA для a | b посредством рекурсивного применения описанных выше шагов.
Здание П
-
Пропускать. Никаких паренов.
-
Пропускать. Нет звезд Клини.
-
Пропускать. Нет контакта.
-
Постройте машину чередования для b | a. Промежуточный результат:
Интегрирование P
Затем мы возвращаемся к этой машине P * bQ и вырываем P-ребро. Мы имеем источник P-ребра, который служит начальным состоянием для P-машины, а пункт назначения P-ребра служит конечным состоянием для P-машины. Мы также делаем это состояние отклоненным (убираем его свойство быть состоянием принятия). Результат выглядит так:
Здание Q
-
Пропускать. Никаких паренов.
-
Пропускать. Нет звезд Клини.
-
Пропускать. Нет контакта.
-
Постройте машину чередования для a | b. Кстати, чередование коммутативно, поэтому a | b логически эквивалентно b | a. (Читайте: пропустите эту небольшую диаграмму сноски из лени.)
Интегрирование Q
Мы делаем то же, что и с P выше, за исключением того, что заменяем ребро Q интермедиями b | машины, которую мы построили. Это результат:
Тада! Я имею в виду, QED.
Хотите узнать больше?
Все изображения выше были созданы с использованием онлайн-инструмента для автоматического преобразования регулярных выражений в недетерминированные конечные автоматы. Вы можете найти его исходный код для алгоритма строительства Томпсона-Макнотона-Ямады онлайн.
Алгоритм также рассматривается в Aho Compilers: Principles, Techniques и Tools, хотя его объяснение мало на деталях реализации. Вы также можете извлечь уроки из реализации конструкции Томпсона в C превосходным Рассом Коксом, который подробно описал ее в популярной статье о сопоставлении регулярных выражений.