Используй методы формальных грамматик (термин для гугла).
Представим генерируемый текст как последовательность символов (символ != буква).
У нас есть терминальные символы - это строки, которые будут встречаться в итоговом тексте. Например: "if", "for", ":"
У нас есть нетерминальные символы - это обозначения сущностей в тексте. Например: ПРИСВАИВАНИЕ, ВЕТВЛЕНИЕ, ОПЕРАТОР, КЛАСС
У нас есть аксиома - нетерминальный символ, с которого мы начинаем генерацию. Например, ПРОГРАММА.
И, самое главное, у нас есть правила замены одних символов другими.
Например:
ПРИСВАИВАНИЕ = ПЕРЕМЕННАЯ "=" ВЫРАЖЕНИЕ
Один символ может заменяться по нескольким правилам - выбор случаен (возможно с некоторым весом?)
ВЕТВЛЕНИЕ = "if" ВЫРАЖЕНИЕ ":\n" ОТСТУП+ ОПЕРАТОРЫ ОТСТУП-
ВЕТВЛЕНИЕ = "if" ВЫРАЖЕНИЕ ":\n" ОТСТУП+ ОПЕРАТОРЫ ОТСТУП- "else:\n" ОТСТУП+ ОПЕРАТОРЫ ОТСТУП-
Чтобы генерировать цепочки символов, используй рекурсию. Первое правило продолжает цепочку, второе - прерывает.
ОПЕРАТОРЫ = ОПЕРАТОРЫ "\n" ОПЕРАТОР
ОПЕРАТОРЫ = ОПЕРАТОР
Тебе также потребуется хранить некое глобальное состояние - использованные имена функций и переменных, текущий отступ, и т.п. То есть у тебя замена символа может требовать дополнительной логики, как для ОТСТУП+ и ОТСТУП-.
Правила замены применяются до тех пор, пока в цепочке символов остался хотя бы один нетерминал.