I see you found an answer in Scala, but anyway, in Groovy, although it needs the dot (or an AST to insert it automatically), it's not hard to do the command tree:
UPDATE: added a floatNode
method, whose precedence is based in the precedence
list. The nodes with higher precedence "float" upward:
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)" }
}
Tests:
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
The println
will output:
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)))))