I have a partial solution (I'm seeking a general one). If your grammar has NO epsilon productions, then no nonterminals are nullable. This means the algorithm to remove left recursion goes through (though it introduces epsilon productions).
If you add semantic actions of the form Action (label, count) which recognise the empty string, and use a shift/reduce parser, and examine all** alternatives, there is no need at all to reorganise the parse tree. When parsing, if a terminal is recognised it pushes an attribute onto the parser stack, this is a shift action. When an action is encountered, it pops N values off the stack, and pushes a node with the specified label and the values popped off the stack, in reverse, as children. This is the reduce action.
The parser must propagate the current position and parser stack, and the operations of shift and reduce should be done with functional updates not mutations. It is then clear than refactoring the grammar does not change the sequence of shift and reduce actions, so the resultant parse tree is invariant under refactoring.
This means if you generate an AST rather than a parse tree you must refer to the attributes by number. The machinery works because the parser stack and control stack are decoupled and refactoring only changes the control stack. The difficulty is that the grammar must be epsilon free initially because the Reduce action terms are themselves nullable.
** The assumption all alternatives are examined is made so that the order of consideration is immaterial. Although refactorings produce equivalent grammars, there is no automatic assurance the resultant parse trees will be the same unless all possibilities are examined. In that case the ordering remains indeterminate, but the set of results will be equal.
\text{...}
; I have found this to be more readable than a mix of math and ordinary text. $\endgroup$