Update operator precedence table - #2625
Conversation
9016bac to
0a3e857
Compare
|
@iluuu1994 could you double-check the accuracy? |
| <entry> | ||
| <link linkend="language.types.array">array</link>, | ||
| <link linkend="control-structures.match">match</link>&listendand; | ||
| <link linkend="functions.arrow">fn</link> |
There was a problem hiding this comment.
I think this precedence is there exclusively to disambiguate [yield $expr => $expr]. All other uses of => are unambiguous due to braces.
There was a problem hiding this comment.
I've updated the link block to only mention yield and linked to the language page for that.
| </row> | ||
| <row> | ||
| <entry>(n/a)</entry> | ||
| <entry><literal>fn</literal></entry> |
There was a problem hiding this comment.
PREC_ARROW_FUNCTION is used for the backup flags, rather than the global expression precedence. I think this can be dropped.
There was a problem hiding this comment.
Maybe @bwoebi can verify, I don't know exactly how %prec works in Bison. Maybe it's there to disambiguate fn() => (1 + 2) vs (fn() => 1) + 2
There was a problem hiding this comment.
PREC_ARROW_FUNCTION is actually defining the real precedence, but it's not about +, but about the logical operators. If it weren't for %precedence PREC_ARROW_FUNCTION, fn() => 1 or 2 would be (fn() => 1) or 2. Basically overriding the precedence of the T_DOUBLE_ARROW and resolving the s/r conflict with yield.
There was a problem hiding this comment.
Also, the precedence does not really apply to fn, but to the T_DOUBLE_ARROW used in a fn() expression. (backup_fn_flags is explicitly at the place it is, to apply it's precedence there, exactly where the => is.)
There was a problem hiding this comment.
Hmm.. how should I change this in that case ? Cause that sounds like it should be a double arrow, but then we'd end up with the double arrow twice in the table, once for yield and once for fn. Did I understand that correctly ? And is that what you'd like me to change it to ?
There was a problem hiding this comment.
Sorry for the late response. I suppose this case is somewhat special, in that the precedence is only applies in the arrow function context. Maybe we can make that clear by using fn (...) => as the operator, or we just leave this out as an implementation detail.
I.e. we're trying to decrease the precedence of => in that context to something lower than T_LOGICAL_*, so that fn() => 1 or 2 is parsed as fn() => (1 or 2) instead of (fn() => 1) + 2 (thanks Bob for the explanation!).
0a3e857 to
75f7c14
Compare
|
Anything I can do to move this forward ? |
Updates the table to match the information per the parser. This adds entries for: * `=>` * `include`, `include_once`, `require`, `require_once` * `fn` * `throw` Ref: https://github.com/php/php-src/blob/2e2416825d2270d256f7597904e14e386cc0d854/Zend/zend_language_parser.y#L54-L82 Fixes 2622
Thanks for the pointer, but that didn't answer my question, which I asked well before a conflict ever got created for this PR. Either way, I'll rebase the PR while keeping the current page split in mind to get rid of the conflict. |
|
Oh and the underlying issue ( |
75f7c14 to
9ef4f87
Compare
| <entry><literal>=></literal></entry> | ||
| <entry><link linkend="functions.arrow">fn arrow</link> disambiguity</entry> |
There was a problem hiding this comment.
PREC_ARROW_FUNCTION is attached to the empty backup_fn_flags rule, which sits after expr in the arrow function rule, so what it governs is where the body stops, not how => binds:
zend_language_parser.y#L1401-L1402,T_DOUBLE_ARROW backup_fn_flags expr backup_fn_flagszend_language_parser.y#L1420-L1421,backup_fn_flags: %prec PREC_ARROW_FUNCTION %emptyzend_language_parser.y#L53-L56, the declaration, betweenT_THROWandT_INCLUDE, hence belowT_LOGICAL_OR
At fn() => 1 • or 2 the parser chooses between reducing that empty rule and shifting or; since PREC_ARROW_FUNCTION is below T_LOGICAL_OR it shifts. That is a different thing from the => of yield, whose precedence is carried by the token itself in L1383 (T_YIELD expr T_DOUBLE_ARROW expr) and declared at L61.
Putting => in the operator column for both rows therefore reads as two contradictory precedences for one token, which is what makes the entry look odd. The effect is still worth a row, since it is the one case the table cannot currently predict:
$x = 1 or 2; // $x is 1 -> ($x = 1) or 2
yield 'k' => 1 or 2; // yields 1 -> (yield 'k' => 1) or 2
fn() => 1 or 2; // Closure, body returns true -> fn() => (1 or 2)Naming the construct instead of the token says it without the contradiction. The wording holds for every operator: no binary operator is declared below PREC_ARROW_FUNCTION, only T_THROW, which cannot follow an expression anyway.
| <entry><literal>=></literal></entry> | |
| <entry><link linkend="functions.arrow">fn arrow</link> disambiguity</entry> | |
| <entry><literal>fn</literal></entry> | |
| <entry> | |
| The body of an <link linkend="functions.arrow">arrow function</link> | |
| extends as far to the right as possible | |
| </entry> |
The row's position is right as it stands and should not move: between include/require and throw.
There was a problem hiding this comment.
@lacatoire This has been discussed before above: #2625 (comment) - also your take reads as AI generated.
There was a problem hiding this comment.
Got it, it's the T_DOUBLE_ARROW, and it would appear twice. Let's go with iluuu1994's first suggestion. Write the operator as fn (...) => rather than a bare =>, so the two rows can't be confused.
The behaviour is worth the row: fn() => 1 or 2 puts the or inside the body, which nothing else in the table lets you predict. I'll merge as soon as you've rebased.
Updates the table to match the information per the parser.
This adds entries for:
=>include,include_once,require,require_oncefnthrowRef: https://github.com/php/php-src/blob/2e2416825d2270d256f7597904e14e386cc0d854/Zend/zend_language_parser.y#L54-L82Ref: https://github.com/php/php-src/blob/82a15338e298142f52854b64d803695d4e5252df/Zend/zend_language_parser.y#L53-L82 (Sept 2026)
Fixes++Related to++ #2622