Из моего опыта и обучения лучше всего:
Рекурсивно строить грамматику
При построении грамматики этого типа (определенного числа терминалов) лучше всего делать это рекурсивно.Сначала вы предполагаете, что вашим начальным символом является желаемая строка.Затем вы разбиваете его на подстроки, каждая из которых все еще соответствует вашим правилам, пока не останутся только терминалы.
Вы подошли к проблеме аддитивно, построив строку с нуля и попытавшись подсчитать, сколько терминалов у вас есть, какой контекстК сожалению, свободные грамматики не могут (они могут, но только для конечных строк).
Таким образом, первое правило будет
S -> 3
где
S...starting symbol
3..."multiple of three"
"Несколькоиз трех "может быть либо строкой с 3 a, либо строкой длиной 3.
3 -> A | L
, где
A...string with 3 a's
L...string with length of 3
Чтобы иметь возможность построить строку любой длины, мы можем сложить вместелюбые строки, соответствующие одному и тому же «правилу трех».
A -> AA
L -> LL
Теперь - строки длины 3 просты.
L -> aM | bM
M -> aN | bN
N -> a | b
3a строка - это просто строка из трех a с любым количеством b, разбросанных между тремя a и вокруг них.
A -> bA | aB
B -> bB | aC
C -> bC | a | aD
D -> bD | b
Строка 3a строится слева направо.Каждое правило может генерировать любое количество b, пока оно не закроет их a.Последнее правило может производить любое число b с правой стороны.
Все вместе:
S -> 3
3 -> A | L
L -> LL | aM | bM
M -> aN | bN
N -> a | b
A -> AA | bA | aB
B -> bB | aC
C -> bC | a | aD
D -> bD | b
Замечания
- Рекурсивно строить грамматику
- Построить грамматику из маленьких единиц