Search code examples
javaoperator-precedence

Forcing order precedence (right associative)


Forcing order precedence on left-associated operations comes pretty easily: 10 - 5 + 3 vs. 10 - (5 + 3)

But, I was wondering if there was a way to force precedence like this with right-associative operators? I'm having a hard time figuring it out. Like, for example, if I was working in Java, could I force the precedence of something like the ++ or the = operators?


Solution

  • Generally, changing the evaluation order of right-associative operators works the same way as with left-associative operators.

    When you have an expression of the form a × b × c, you can determine the evaluation order by specifying either, (a × b) × c or a × (b × c), regardless of which was the default. The JLS, §15.7.3 states:

    The Java programming language respects the order of evaluation indicated explicitly by parentheses and implicitly by operator precedence.

    However, the result of an assignment is a value and a value is not allowed to the left of an assignment operator, so (a = b) = c is always invalid. This differs from programming languages like C++ where an expression¹ could evaluate to an assignable reference.

    As explained in this answer, the precedence is given implicitly by the grammar of the Java programming language. Since the grammar of the assignment operator is already defined in a way that it doesn’t allow arbitrary expressions to the left of the operator, notably the braced expression is not supported at this place, an attempt to assign to a braced assignment would already get rejected by the parser².

    Note that similarly, a -> b -> c is right-associative, but can’t be changed, as (a -> b) -> c is not a valid expression because the only valid thing to the left of -> is a parameter list.

    The only right-associative expression in Java, where changing the order would be meaningful, is the tertiary operator, as a? b: c? d: e gets evaluated as a? b: (c? d: e), but can be changed to (a? b: c)? d: e, which would be valid if b and c evaluate to a boolean result.

    For a combination of unary operators, you can’t change the evaluation order by inserting parentheses. If you have an expression of the form op1 op2 value but want op2 op1 value instead, just use the latter. A different thing would be, e.g. - a - b, for which (- a) - b and - (a - b) have a different meaning, but that’s another case where a binary operator is involved.

    ¹ other than those ending in a variable name or array index
    ² at least, it should. I just noticed that both, ecj and javac, contradict the specification and only reject it after parsing