2015-01-06 40 views
0

我已經用Xtext創建了一個自定義的DSL,這對於描述層次結構(本例中固定高度爲2)非常有用。我想現在要做的是生成一個簡單的Java Swing應用程序,它可以使用JTree顯示這樣的層次結構。我使用Xtend從Xtext擴展了代碼生成示例。一切正常,但可以做得更好。在Xtend循環中使用唯一的變量名(代碼生成)

我的模板的一部分是很醜陋至今:

def compile(Level a) ''' 
    DefaultMutableTreeNode «a.name» = new DefaultMutableTreeNode("«a.name»"); 
    «FOR b:a.sublevels» 
     DefaultMutableTreeNode «b.name» = new DefaultMutableTreeNode("«b.name»"); 
     «a.name».add(«b.name»); 
    «ENDFOR» 
''' 

正如你所看到的,我用了DSL作爲代碼生成的變量名,用戶定義的實體的名稱,其不好。如果用戶在Java中選擇的名稱不是有效的變量名稱,則以後將不會編譯該應用程序。

我這樣做的原因是因爲在創建JTree及其節點時,我需要唯一的變量名稱。生成的代碼看起來是這樣的:

DefaultMutableTreeNode a = new DefaultMutableTreeNode("a"); 
DefaultMutableTreeNode a1 = new DefaultMutableTreeNode("a1"); 
a.add(a1); 
DefaultMutableTreeNode a2 = new DefaultMutableTreeNode("a2"); 
a.add(a2); 
DefaultMutableTreeNode a3 = new DefaultMutableTreeNode("a2"); 
a.add(a3); 
... 

因爲一切都在相同的範圍內,變量名必須是不同的 - A,A1,A2和A3這種情況。但是,我怎樣才能創建有效的唯一變量名稱,而不是使用用戶的輸入(這可能是無效的)?任何幫助表示讚賞,謝謝。

回答

1

您需要節點和計數器變量的人爲變量名稱。最簡單的方法是在調用編譯方法之前將其作爲字段添加到生成器並重置它。

int count 

def compile(Level a) { 
    count = 0 
    return compile(a, -1) 
} 

def compile(Level a, int parentCount) { 
    var aCount = count++ 
    return ''' 
    DefaultMutableTreeNode node«aCount» = new DefaultMutableTreeNode("«a.name»"); 
    «IF parentCount > -1» 
     node«parentCount».add(node«aCount»); 
    «ENDIF» 
    «FOR b:a.sublevels» 
     «compile(b, aCount)» 
    «ENDFOR» 
    ''' 
} 

如果您能抽出變量名,我寧願生成使用Java的鮮爲人知的非靜態初始化代碼,因爲它們反映了樹的結構在Java代碼,例如

new DefaultMutableTreeNode("a") {{ 
    add(new DefaultMutableTreeNode("a1") {{ 
    add(new DefaultMutableTreeNode("b1")) 
    }}) 
    add(new DefaultMutableTreeNode("a2")) 
    add(new DefaultMutableTreeNode("a2")) 
}} 

通過非常簡單的發電機

def CharSequence compile(Level a) ''' 
    new DefaultMutableTreeNode("«a.name»")«IF !a.sublevels.empty» {{ 
    «FOR b:a.sublevels» 
     add(«compile(b)»); 
    «ENDFOR» 
    }}«ENDIF»''' 
+0

謝謝你,我真的很喜歡你的第二個解決方案。由於我以後不需要這些名字,所以它很優雅。今天學到了一些東西;) – ceran