Search code examples
phpoperator-precedence

What is the real groups of the expression "3<8 ? (9<6 ? 7 : 5) : 2>0 ? 4 : 1" and the meaning of non-associative in PHP?


As for the expression:

3<8 ? (9<6 ? 7 : 5) : 2>0 ? 4 : 1

I have referred to the PHP manual. And I have found that the ternary operator in PHP is left-associative. Moreover, I find that the associativity of relational operator such as >, <= is non-associative, which sounds strange to me.

According to the precedence and associativity of ternary operator in PHP, it can be expressed as groups according to other's opinion:

(3<8 ? (9<6 ? 7 : 5) : 2)>0 ? 4 : 1

But as for me, I group the expression like this:

((3<8) ? (9<6?7:5) : (2>0)) ? 4 : 1

So which one is right? The main difference is that the sub-expression 2>0 is split or not.

And I wonder what the non-associative associativity is in PHP. I find that it sounds strange and haven't seen it in other languages like C, Java, C++.

There is already a question about the meaning of PHP non-associative: do lower precedence operators associate non-associative higher precedence operators?
But I can't figure out what does non-associative associativity mean in PHP?


Solution

  • Ignore the non-?: operators here by substitution as they have a higher precedence.

    3<8 ? (9<6 ? 7 : 5) : 2>0 ? 4 : 1
    

    then becomes

    x ? (y ? 7 : 5) : z ? 4 : 1
    

    and when applying leftward associativity of ?: the result is

    (x ? (y ? 7 : 5) : z) ? 4 : 1
    

    Substitute back as desired.

    As for

    ..what does non-associative associativity mean in PHP?

    Non-associativity describes infix operators that "don't chain" and "generally means that syntactically, there is a special rule for sequences of these operations, and semantically the behavior is different" - including syntax errors! Take the following:

    1 < b < 2
    

    If it < was leftward it would be (1 < b) < 2 (or 1 < (b < 2) for rightward). However, such construct does not make sense in PHP and thus the form 1 < b < 2 merely results in a syntax error.

    While it is valid syntax, although semantically odd, to apply parenthesis manually as done above, the non-associative nature of the operators means PHP will not even try to parse it as such.

    On the other hand, many operators like + and * "do chain" and thus have an associativity.