Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change operator precedence

What would be the best way to change operator precedence for a concrete expression?

For example I have a class:

class A(){ 
   def multiply(a) { 
       ... 
   } 

   def plus(a) { 
       ... 
   } 

   def minus(b) {
       ...
   }

} 

a = new A() 
b = new A() 
c = new A() 

d = a + (b - c) * d

As multiplication has higher precedence than + and - I get an AST of form

  +
 / \
a   *
   / \
  -   d
 / \
b   c

What would be the easiest way to convert it to a tree where * has lower precedence than + and -. I assume that parentheses are allowed only to group - and +, i.e. an expression (a * b - c) * d is not valid and should be not expected as an input.

like image 253
Nutel Avatar asked Jun 04 '11 22:06

Nutel


2 Answers

You could simply add parentheses to your code. This will likely make your code a lot more easily understood than using an AST transformation.

like image 110
Dónal Avatar answered Dec 11 '22 12:12

Dónal


You could change it using an AST transformation, but it would be a tricky thing to get right...

If you load your script into the GroovyConsole, and then open the AST browser, you will see this tree for the assignment:

Binary - ( d = ( a & ( b >> c ) ) )
  Variable - d
  Binary - ( a & ( b >> c ) )
    Variable - a
    Binary - ( b >> c )
      Variable - b
      Variable - c

So as you can see, the nodes are executed based on default operator precedence, and a tree of org.codehaus.groovy.ast.expr.BinaryExpression and org.codehaus.groovy.ast.expr.VariableExpression AST nodes is created.

You would need to write an AST transform that scanned the tree for BinaryExpression nodes and then re-order these trees so that they are sorted by your own precedence for the operation field.

Or, you could just use parentheses in your code as Don suggests :-)

like image 20
tim_yates Avatar answered Dec 11 '22 12:12

tim_yates