改变运算符优先级

7

如何更改具体表达式的运算符优先级?

例如,我有一个类:

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

由于乘法比加法和减法具有更高的优先级,因此我得到的AST形式为:
  +
 / \
a   *
   / \
  -   d
 / \
b   c

什么是将其转换为树的最简单方法,其中*的优先级低于+-。我假设只允许使用括号来分组-+,即表达式(a * b - c) * d不合法,不应作为输入期望。

我会小心一些:运算符重载*可能会引起混淆,改变运算符优先级可能会引起更多的问题! - Joachim Sauer
这是关于编程的内容,应该是DSL,所以应该没问题。 - Nutel
你提到了“右移”,但没有指明表示它的符号。 “*”是表示“右移”的符号吗? - Jonathan Leffler
最好的方法是在语法中声明其他运算符优先级,并将规则放在括号中。这意味着使用自己的解析器,但是更改某种语言内部的基本语法规则只会让人感到困惑。从你的问题中我无法推断出你实际使用的解析器或语言。 - Christopher Creutzig
2个回答

4
你可以在代码中添加括号。这比使用AST转换更容易理解你的代码。

3

您可以使用AST转换来更改它,但是正确实现会很棘手...

如果您将脚本加载到GroovyConsole中,然后打开AST浏览器,您将看到此赋值的树形结构:

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

如您所见,节点是根据默认运算符优先级执行的,并创建了一个org.codehaus.groovy.ast.expr.BinaryExpressionorg.codehaus.groovy.ast.expr.VariableExpression AST节点的树。您需要编写一个AST变换器,扫描树以查找二元表达式节点,然后重新排序这些树,使其按照您自己的operation字段的优先级进行排序。或者,您可以像Don建议的那样在代码中使用括号 :-)

这实际上是一种DSL,因此介绍会增加一些噪音。另外,如果用户使用括号,我将无法在AST中获取此信息,对吗? - Nutel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接