1

Al Aho のコンパイラ クラスのコンパイラを作成しており、AST の生成用に次のコードを検討しています。ここにいくつかの背景があります。名前と ID のマッピングのスタックとしてスコープ ルールを実装し、宣言のノードを生成する前に一連のマッピングをスタックにプッシュします。

compound_statement : {pushScope();} statement_list {popScope();}

それでは、私の質問です。これはどのように作動しますか?このコードはいつ実行されますか? このプロダクションがパーサーによって削減されたときに実行されますか? いつどの部分が発生しますか?オフィスアワーに行って確認する必要がありますか?

4

2 に答える 2

1

あなたの質問はASTノードの構築について語っていますが、説明の本文は明らかにシンボルテーブルについて語っています。これらのアイデアは同じではありません!AST はプログラムの構造を表します。シンボル テーブルは、どのような名前がどこに表示され、どのような型を持つかについての推論を表します。

シンボルテーブルのフォーカスに従って、ブロックに「入る」ときに現在のスコープをプッシュし、「出る」ときにポップするという概念は、ブロックごとの新しいスコープを抽象的に実現するため、概念的に正しいです。

文法規則の任意の時点でセマンティック アクションを付加できるかどうかわからないので、YACC にあなたが言ったことを実行させることはできないと思います。ルール全体にのみアクションを追加できると思います。そのアクションは、ルールが認識された(「縮小」された)場合にのみ実行されます。したがって、本当にこれを行いたい場合は、文法を曲げて、セマンティック アクションを挿入する機会を作成する必要があります。ルールを書き直すことでこれを行うことができます (あなたのスタイルに従うと、これは実際には有効な YACC 構文ではないと思います):

  compound_statement : block_start statement_list block_end ;
  block_start = '{' pushScope() ;
  block_end = '}' popScope();

開始と終了を対称的にブロックするアクションを追加しましたが、もう少し節約できます (にやにや笑い):

  compound_statement : block_start statement_list '}' popScope() ;
  block_start = '{' pushScope() ;

ここでの本当の秘密は、元のルールにサブルールを追加することによって、ブロックに入った後に削減/セマンティック アクションの実行機会を作成することでした。私はしばしば空のルールを使用してこれを行いました:

  compound_statement : '{' compound_statement_sub_rule block_start statement_list '}' popScope() ;
  compound_statement_sub_rule = pushScope() ;

これを行う方法を示したので、これを行う必要はまったくないと思います。あなたがしていることは、セマンティクスを解析プロセスと絡ませることです。この道をたどると、識別子の作成/検索のための複雑なアクションで文法の残りの部分を装飾していることに気付くでしょう。一般に、セマンティック アクションを使用して単純に構文ツリーを構築し、構文解析が完了したら、構文ツリーをたどってシンボル テーブルの構築/識別子ルックアップを実装することをお勧めします。

私はオフィスアワーに行って、あなたがばかげていると思うかどうかにかかわらず、あなたが考えることができる限り多くの質問をします. それは見事に報われます。

于 2011-04-13T03:48:24.473 に答える
0

アクションを yacc のルールの「中間」に貼り付けると、実際にはアクションの新しい非表示の非終端が作成され、非表示の非終端が削減されたときにルールが実行されます。だからあなたのルール:

compound_statement : {pushScope();} statement_list {popScope();} ;

は次と同等です:

compound_statement : hidden_rule statement_list {popScope();} ;
hidden_rule : {pushScope();} ;

さらに、yacc はアクション内の $n 参照を適切に変更して、正しいものを参照するようにします。

そのため、が縮小pushScopeされたときに実行されますhidden_rule(これは、 内のステートメントが縮小される前statement_listです)。 popScope は、すべてのステートメントが縮小された後に実行されるため、実際には、これはまさにあなたが望むことを行います。

于 2011-04-13T17:16:25.087 に答える