2014-03-13 41 views
2

是否可以在Groovy中使用infix操作符創建dsl?groovy dsl - 是中綴運算符可能嗎?

我研究了構建器模式,invokeMethod,propertyInvoke和MetaClass,我只能看到如何使用它來使用前綴運算符(波蘭語符號)創建樹結構。我想要做的是構建具有綁定優先規則的中綴運算符的樹結構。

例如:如果這個僞代碼計算爲8:

add(2,multiply(3, 2)) 

我想它表示爲:

2 add 3 multiply 2 

那裏乘結合不是添加更加緊密。我使用算術只是一個例子 - 我的應用程序是完全不同的。

我不想寫和支持我自己的解析器,所以我希望groovy有這樣的機制?

編輯:在搜索解決方案時,我發現這是可能的,並在Scala中有詳細記錄(請參閱第33章:由馬丁奧德斯基編寫的Scala編程中的組合解析器)。

+0

它嚴格必須遵循'2乘加3 2'具有較高的優先級 「浮動」 向上的節點:

class Operation { static final precedence = ['minus', 'add', 'multiply', 'divide'] def left, right, method Operation parent def invokeMethod(String method, args) { def o = new Operation( parent: this, left: right, method: method, right: args[0]) this.floatNode(o) } def floatNode(Operation op) { if (op.hasHigherPrecedenceThan(this)) { op.parent = this.parent this.parent = op if (op.parent) { this.parent = op.parent.floatNode(op) } return this } else { return op } } def hasHigherPrecedenceThan(Operation o) { return precedence.indexOf(this.method) > precedence.indexOf(o.method) } String toString() { "Operation($left $method $right, parent=$parent)" } } 

測試句法?它可以是「2.加3乘2」嗎? – Will

+0

如果它是'2加3乘2減4',應該理解爲'add(2,subtract(multiply(3,2),4)'? – Will

+0

是的 - 只是運算的正常順序。 – user1373164

回答

1

我看到你發現在斯卡拉的答案,但無論如何,在Groovy中,儘管它需要的點(或AST自動插入的話),這是不難做到的命令樹:

UPDATE :增加了一個floatNode方法,其優先級基於precedence列表。

Integer.metaClass.invokeMethod = { String method, args -> 
    new Operation(parent: null, method: method, left: delegate, right: args.head()) 
} 


a = 2.add 3 multiply 4 minus 5 divide 6 add 7 

println a 

println將輸出:

Operation(3 minus 5, 
    parent=Operation(5 add 7, 
     parent=Operation(2 add 3, 
      parent=Operation(3 multiply 4, 
       parent=Operation(5 divide 6, parent=null))))) 
+0

我還沒有嘗試過,但它看起來很有希望並回答了我的原始問題。我不確定優先解決方案的工作方式雖然(左:這將n按順序碰到吧?),在這個例子中3 * 4應該是第一個要評估的東西。但這是一個很好的起點 - 感謝您的幫助。 – user1373164

+0

是的,'left:這個'會按順序嵌套。我認爲樹可以遍歷來處理運算符的優先級。將盡快寫在 – Will

+0

我認爲這個點可以用函數調用來替換,比如'let 2 add 3 multiply 4 minus 5' ... – Will