Я чувствую, что мог бы быть способ сделать это путем преобразования регулярного выражения в грамматику, помещения грамматики в нормальную форму Хомского, объединения общих нетерминалов и поиска шаблонов с использованием некоторого эвристического сравнения.Вы могли бы даже получить более краткие ответы, если не поместите его в «настоящий» CNF ... Я бы оставил лямбды / эпсилоны внутри.
ba*b|ba*c|ca*b|ca*c
S -> bAb | bAc | cAb | cAc
A -> aA | lambda
S -> BAB | BAC | CAB | CAC
A -> AA | a | lambda
B -> b
C -> c
S -> DB | DC | EB | EC
A -> AA | a | lambda
B -> b
C -> c
D -> BA
E -> CA
На данный момент, возможно, вы найдете эвристическийкоторый распознает
S -> (D+E)(B+C)
Заменить в обратном порядке,
S -> (BA|CA)(b|c) -> (ba*|ca*)(b|c)
Повторите это для подвыражений, например,
S' -> bA' | cA'
A' -> aA' | lambda
S' -> B'A' | C'A'
A' -> A'A' | a | lambda
B' -> b
C' -> c
Теперь признав, что S -> (B | C) (A), мы можем получить
S' -> (B'|C')(A') -> (b|c)(a*)
Для окончательного решения
S -> ((b|c)a*)(b|c)
Затем вы можете просто найти лишние скобки для удаления (отметив, что конкатенация ассоциативна, и этосущественно оптимизировать вещи в конкатенативную нормальную форму, просто отбросьте все скобки, которые не заключают в себе только | -ограниченный список опций ... так что вышеприведенное становится
(b|c)a*(b|c)
Трюк с эвристикой,и это не может сделать все возможные оптимизации. Я не знаю, как это будет работать. Тем не менее, это может быть что-то, чтобы рассмотреть.