2010-11-22 141 views
2

我已經爲一種類型的DSL編寫了JJTree(JavaCC)配置,併成功標記了給定格式的文件,並在請求時轉儲AST。如何使用JavaCC/JJTree存儲令牌?

問題是樹中的每個節點都是空的,因爲我當前沒有存儲令牌(我無法理解這些例子)。

這裏是我的.jjt文件的一部分:

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

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

我想存儲SECTION1,第2節和爲Section3引用列表的引用根節點。我希望Section3節點存儲標識符,標題塊並保留詳細信息塊的列表。

我的fill .jjt文件是數百行,但我覺得如果我能理解這兩個部分,那麼我就能理解JJTree是如何工作的。請讓我知道如何正確使用JJTree。

謝謝。

回答

2

如果您查看SimpleNode類,您會注意到它的實例會自動存儲對其父節點和子節點的引用(除非它們的創建使用#void進行了抑制)。例如,您的根節點將包含對0..1 Section1節點,0..1 Section2節點和0 .. * Section3節點的引用,並且可以使用返回節點對象的jjtGetChild()方法訪問它們。要確定此子節點是否爲Section1,Section2或Section3節點,可以調用它的toString()方法(如dump()那樣)。另外,如果您厭倦了這種初始節點迭代和toString檢查的風格,您可以定義自己的節點類型,而不是依賴SimpleNode實現。在我下面的例子中,Start()現在返回一個自定義RootNode,而不是一個普通的SimpleNode。 RootNode包含對其子節點的特定引用(根據需要定義這些節點的getter)。請注意,我的簡短片段假定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 class讓你與你的節點做的是從分離節點類本身。您最終可能會有幾個訪問類,每個訪問類在分析樹上執行一個函數,並且對每種類型的節點都有訪問方法重載。

讓我知道是否有什麼你不明白。我不是JavaCC專家(我曾在uni使用它)但我應該能夠幫助你:)

+0

感謝您的信息。如果可能的話,你可以告訴我如何處理這個例子而不定義自定義節點類(如何添加字段來將自定義標記保存在已有的JJTree定義的節點類型中)?那就是 - 舉一個你在第一段中解釋的方法的例子。 – Chris 2010-11-23 17:38:12