2

Yacc/Bison で文法ファイルを次のように書くと:

Module
    :ModuleName "=" Functions
      { $$ = Builder::concat($1, $2, ","); }

Functions
    :Functions Function
      { $$ = Builder::concat($1, $2, ","); }
    | Function
      { $$ = $1; }

Function
    : DEF ID ARGS BODY
      {
          /** Lacks module name to do name mangling for the function **/
          /** How can I obtain the "parent" node's module name here ?? **/
          module_name = ; //????

          $$ = Builder::def_function(module_name, $ID, $ARGS, $BODY); 
      }

そして、このパーサーは次のようなコードを解析する必要があります。

main_module:
    def funA (a,b,c) { ... }

私の AST では、「funA」という名前を に変更する必要がありますmain_module.funAFunctionしかし、パーサーがノードを処理している間、モジュールの情報を取得できません!

この問題を処理するのに役立つ Yacc/Bison 機能はありますか? または、このような恥ずかしい状況を避けるために解析スタイルを変更する必要がありますか?

4

1 に答える 1

3

bison機能がありますが、マニュアルに記載されているように、注意して使用してください。

$Nゼロまたは負の値は、現在のルールに一致するものより前Nのスタック上のトークンおよびグループへの参照に使用できます。これは非常にリスクの高い方法であり、確実に使用するには、ルールが適用されるコンテキストを確認する必要があります。これを確実に使用できる場合を次に示します。

 foo:      expr bar '+' expr  { ... }
         | expr bar '-' expr  { ... }
         ;

 bar:      /* empty */
         { previous_expr = $0; }
         ;

barここに示されている方法でのみ使用されている限り、常に$0。の定義のexpr前にあるを参照します。barfoo

よりクリーンに、ルールの途中のアクション(in Module)を使用して、モジュール名を名前スタックにプッシュすることができます(これは解析コンテキストの一部である必要があります)。次に、ルールの最後にスタックをポップします。

ミッドルールアクションの詳細と例については、マニュアルを参照してください。

于 2012-11-23T18:23:53.080 に答える