2

あるタイプのDSL用にJJTree(JavaCC)構成を作成しましたが、これは特定の形式のファイルを正常にトークン化し、要求されたときにASTをダンプします。

問題は、現在トークンを保存していないため、ツリー内の各ノードが空であるということです(例を理解できません)。

これが私の.jjtファイルの一部です:

SimpleNode Start() #Root : {} {
  (
    ( Section1() )?
    ( Section2() )?
    ( Section3() )*
  )  {
    return jjtThis;
  }
}

void Section3() #Section3 : {}
{
  < SECTION_3 > Identifier() <LBRACE >
    Header()
        (Details() < SEMICOLON > )*
  < RBRACE >
}

ルートノードにSection1、Section2への参照とSection3への参照のリストを保存したいと思います。Section3ノードに識別子とヘッダーブロックを保存し、詳細ブロックのリストを保持してほしい。

私のfill.jjtファイルは数百行ですが、これら2つのセクションで理解できれば、JJTreeがどのように機能するかを理解できると思います。JJTreeの使い方を教えてください。

ありがとう。

4

1 に答える 1

2

SimpleNodeクラスを見ると、そのインスタンスが親ノードと子ノードへの参照を自動的に格納していることがわかります(#voidを使用して作成が抑制された場合を除く)。たとえば、ルートノードには0..1 Section1ノード、0..1 Section2ノード、0 .. * Section3ノードへの参照が含まれ、Nodeオブジェクトを返すjjtGetChild()メソッドを使用してアクセスできます。この子ノードがSection1、Section2、またはSection3ノードであるかどうかを判断するには、そのtoString()メソッドを呼び出します(dump()と同様)。

または、このスタイルの単純なノードの反復とtoStringチェックにうんざりしている場合は、SimpleNodeの実装に依存する代わりに、独自のノードタイプを定義できます。以下の私の例では、Start()がプレーンなSimpleNodeではなくカスタムRootNodeを返すようになりました。RootNodeには、その子ノードへの特定の参照が含まれています(適切と思われる場合は、これらの子ノードのゲッターを定義します)。私の簡単なスニペットは、Section1 / 2/3()がすべてカスタムノードを返すことを前提としていますが、そうである必要はありません...あなたが言ったことから、Section3()のカスタムノードが必要ですが、Section1の場合/ 2は些細なことなので、SimpleNodesのままにしておくことができます。

RootNode Start() : 
{
  Section1Node s1Node = null;
  Section2Node s2Node = null;

  List s3Nodes = new LinkedList();
  Section3Node s3Node = null;
} 
{
  (
    ( s1Node = Section1() )?
    ( s2Node = Section2() )?
    ( s3Node = Section3() {s3Nodes.add(s3Node); } )*
  )  {

    return new RootNode(s1Node, s2Node, s3Nodes);
  }
}

解析ツリーをトラバースしてノードで複雑なことをしている場合は、ノードで行っていることがノードクラス自体から切り離されるように、その一部をVisitorクラスに移動することをお勧めします。最終的に、それぞれが解析ツリーで機能を実行し、ノードのタイプごとに訪問メソッドのオーバーロードを持つ複数の訪問者クラスが発生する可能性があります。

わからないことがあれば教えてください。私はJavaCCの専門家ではありません(私は一度uniで使用しました)が、あなたを助けることができるはずです:)

于 2010-11-22T18:20:59.840 に答える