反復する必要がある抽象構文ツリーがあります。AST は、 PHP へのレモン ポートによって生成されます。
さて、「通常」、私は真新しくてピカピカの (PHP 5.3.1) SPL クラスでそれを行います。それは次のようになります:
$it = new \RecursiveIteratorIterator(
new \RecursiveArrayIterator($ast['rule']),
\RecursiveIteratorIterator::SELF_FIRST);
実際、これはツリー全体の大まかなタイプを決定するコードの別の部分で既に行っていることです (つまり、代入、条件などである可能性があります)。詳細はさておき、唯一重要なことは、反復が RecursiveIteratorIterator::SELF_FIRST、つまりトップダウンで行われることです。
私の問題に戻ると、ツリーでいくつかの置換と最適化を行うために、AST ボトムアップ、つまり RecursiveIteratorIterator::CHILD_FIRST のようなものを繰り返す必要があります。
問題は、これらの操作がコンテキストを認識している必要があることです。つまり、現在のノードまでのパスが必要です。そして、ボトムアップで反復したいので、RecursiveIteratorIterator ではそれができません。
ちょっと考えてみてください。ボトムアップを反復し、各反復で現在のノードのトップダウン コンテキスト (スタック) を取得したいと考えています。RecursiveIteratorIterator は逆方向に反復するために、最初にツリーの末尾に移動する必要があるため、技術的には可能であるはずです。末尾に向かう途中で、現在の位置をキャッシュし、再帰から戻るときに要素を単純にポップアウトすることができます。
これはキーワードです: caching。これが、別の SPL クラス RecursiveCachingIterator で可能であると思われる理由です。
問題は、それは本当に可能かということです。はいの場合、どのように?
私はいくつかのコードでパズルを解こうとしましたが、成功しませんでした。ドキュメントはほとんどありません。本当に、本当に希少です。
SPL を使用してこれに対する最もエレガントなソリューションを見つけた人は誰でも脱帽です! あなたはPHPの第一人者です!
PS: 不明な点がある場合は、できるだけ多くの SPL (再) 使用法を探しています。カスタム スタックを使用して独自の再帰関数を記述できることはわかっています。そのことを思い出させる必要はありません。