ソース言語のすべてのセマンティック詳細をモデル化する AST だけで十分です。定義上、セマンティクスが正しくモデル化されていて、言語に三項演算子が含まれている場合、演算子が適用される特定の順序 (たとえば、括弧などの先行モジュロ オーバーライドの結果) も正しくモデル化されます。
したがって、問題は AST にはありません。優先順位が異なる同様の(三項)演算子を使用して別の言語に生成しています。
これはコード生成における古くからの問題です。ターゲットの演算子はソースの演算子と完全には一致しないため、出力は 1 対 1 になりません。あなたの場合、PHP三項演算子を括弧で囲んで生成し、元のセマンティクスを達成する順序を制御することで問題を解決できるはずなので、これは大きな問題ではありません。
一般に、目的の結果を達成する一連のコードを生成することは非常に複雑になる可能性があり、それを行う方法はたくさんあります。コンパイラの本が薄いのではなく厚いのはそのためです。「ASTを取得し、ASTを歩き、コードを吐き出す」ことに暗黙のうちに落ち着いたようです。これはほとんどオンザフライのコード ジェネレーターです。生成されたコードが特に優れていて、ターゲット言語がソース言語に非常に近いかどうかを気にしない場合、これは適切に機能します。
コード生成の問題がより複雑な場合、通常は AST を使用して、計算のデータ フロー モデルに相当するものを生成します。これは、結果を生成し、前の演算子からの結果を消費する演算子で構成され、「演算子」で接地されます。変数値と定数をフェッチします。次に、データ フロー表現が走査されてコードが生成されます。これには、データ フロー表現で演算子を選択し、ターゲット言語で一致するコード シーケンスを見つけてそれを生成し、オペランドがどのように収集されるかを心配できるという利点があります。より良いスキームは、データ フロー サブグラフ (同等の複合ターゲット言語構造を表す) を生成されたデータ フロー グラフに一致させます。これにより、大幅に優れたコードが生成されます。頻繁、ローコード生成後にターゲット言語固有の最適化を適用して、さらに優れたコードを生成できます。どちらの場合も、演算子の結果の管理について心配する必要があります。それらを次のターゲット言語演算子に直接渡すことができるか、またはある種の一時記憶域に移動する必要があります (マシンコードの場合、これは別のレジスタまたはメモリの場所である可能性があります)。これをすべて行うのは簡単ではありません。繰り返しますが、それがコンパイラの本が薄くない理由です。
この考え方のバリエーションは、ソースからソースへのプログラム変換です。これは、ソース コード内の構成要素をターゲット コード内の構成要素に "直接" マップしますが、解析されていないプログラミング言語テキストは一致しにくいため、これは通常、AST を操作することによって舞台裏で行われます。当社のDMS Software Reengineering Toolkitは、この種のシステムの一例です。このようなツールを使用すると、ソース言語でパターンを記述し (構文解析ツリーと暗黙的に一致します)、ターゲット言語で対応するパターンを記述します (ターゲット言語の AST を暗黙的に生成します)。上記のデータ フロー グラフ マッチングの多くの効果を与える、複雑なソースまたはターゲット構造を記述できます。生成後の最適化は、ターゲット コードをターゲット コードに変換するより多くの書き換えルールで構成されます。
結論: 翻訳が本当に簡単でない限り、AST を持っているだけでは十分ではありません。この SO の回答で必要なものについて詳しく読むことができます: https://stackoverflow.com/a/3460977/120163
警告: 大声での意見が続きます。
「トランスコーダー」について: 私は「コンパイル」、「翻訳」、または「ソースからソースへ」コンパイラーという用語を好みます。私はほぼ 40 年間、プログラムの分析および操作ツールを構築してきました。このSOの質問に遭遇するまで、「トランスコーダー」という用語を聞いたことがありませんでした。レガシーCobol / PL1をJavaに移行した経験 と、NACAと呼ばれる本当にひどいコード変換スキームを説明する応答。それ以来、この用語が勢いを増していると聞いています。完全に適切な用語があるのに、なぜ別の用語を発明しなければならなかったのかわかりません。通常、これは誰かが大祭司職を発明した兆候です。「私たちがやっていることを人々が本当に理解しないように、ピカピカの新しい用語を発明しましょう」. 私'