На самом деле, вариантов не строить AST в нетривиальных случаях особо и нет. Единственный выход обойтись без AST: это построение однопроходного компилятора, который прям во время парсинга и только по данным из парсера и ещё максимум из таблицы символов будет генерировать некий код.
кажется, что это неявное AST в дереве вызовов, например, рекурсивного спуска 🤔