グラマーから残りの再編成を削除するときのセマンティックアクションを変更する方法
-
16-10-2019 - |
質問
残りの再回帰文法に関連するセマンティックアクションを変更する方法を教えてくれるアルゴリズムはありますか?たとえば、次の文法とそれに関連するセマンティックアクションがあります。
$ s rightArrow id = expr $ {ss = expr.size}
s $ rightArrow $ if expr then $ s_1 $ els $ s_2 $ {$ s_1.t = st + 2; $ $ s_2.t = st + 2; $ $ ss = expr.size + s_1.size + s_2.size + 2; $}
s $ rightArrow $ while expr do $ s_1 $ {$ s_1.t = st + 4; $ $ ss = expr.size + s_1.s + 1; $}
S $ rightArrow $ $ s_1 $; $ s_2 $ {$ s_1.t = s_2.t = st; $ $ ss = s_1.s + s_2.s; $}
明らかに、グラマーの非再帰バージョンは次のとおりです。
S $ rightArrow $ id = expr t
s $ rightArrow $ if if expr then $ s_1 $ else $ s_2 $ t
s $ rightArrow $ while expr do $ s_1 $ t
t $ rightArrow $; $ s_2 $ t
t $ rightArrow $ $ epsilon $
ただし、それに応じてセマンティックアクションを変更する必要があります。これがどのようにできるかというアイデアはありますか?
解決
私が発見したことから、左利き回りを削除しながらセマンティックアクションを変更する一般的なテクニックはありません。代わりに、最良の方法は、代表的な例を挙げ、その解析ツリーを描き、次にどのセマンティックアクションが以前の文法と同じ結果をもたらすかを確認することです。
他のヒント
私には部分的な解決策があります(私は一般的なものを求めています)。あなたの文法にエプシロンのプロダクションがない場合、非末端は気付かれません。これは、左再帰を削除するアルゴリズムが通過することを意味します(ただし、Epsilon Productionsを導入します)。
空の文字列を認識するフォームアクション(ラベル、カウント)のセマンティックアクションを追加し、シフト/削減パーサーを使用し、すべての**の代替案を調べる場合、パースツリーを再編成する必要はまったくありません。解析するとき、端子が認識されている場合、属性をパーサースタックに押し込みますが、これはシフトアクションです。アクションが発生すると、n値がスタックからn値をポップし、指定されたラベルを使用してノードをプッシュし、子供のように逆に値がスタックから飛び出します。これは削減アクションです。
パーサーは現在の位置とパーサースタックを伝播する必要があり、シフトと削減の操作は、変異ではなく機能的な更新で行う必要があります。文法をリファクタリングすることは、シフトのシーケンスを変更せず、アクションを削減しないことは明らかです。したがって、結果の解析ツリーはリファクタリング下で不変です。
これは、解析ツリーではなくASTを生成する場合、数字で属性を参照する必要があることを意味します。パーサースタックとコントロールスタックが分離され、リファクタリングが制御スタックのみが変更されるため、機械は機能します。難易度は、削減されたアクション項がそれ自体が気付かないので、最初はイプシロンのないものでなければならないということです。
**すべての代替案が調べられる仮定は、考慮の順序が重要ではないように行われます。リファクタリングは同等の文法を生成しますが、自動保証はありません。すべての可能性が調査されない限り、結果の解析ツリーは同じになります。その場合、順序は不定のままですが、結果のセットは等しくなります。