Skip to content

Commit

Permalink
Fix/update operators.precedence (#509)
Browse files Browse the repository at this point in the history
- explain why associativity is not applicable to unary operators
- distinguish between unary and binary `+`/`-`
- add some missing reference links
- update the precedence of string concatenation for PHP 8
- fix "(n/a)" ("not applicable") to "non-associative" for ternary

References:
- https://github.com/php/php-src/blob/master/Zend/zend_ast.c
  (search "Operator Precedence")
- https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y
  (search "precedence")
  (NOTE: in opposite order)
  • Loading branch information
guilliamxavier committed Apr 12, 2021
1 parent 6936064 commit 011596b
Showing 1 changed file with 49 additions and 9 deletions.
58 changes: 49 additions & 9 deletions language/operators.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,14 @@
Operators of equal precedence that are non-associative cannot be used
next to each other, for example <literal>1 &lt; 2 &gt; 1</literal> is
illegal in PHP. The expression <literal>1 &lt;= 1 == 1</literal> on the
other hand is legal, because the <literal>==</literal> operator has lesser
other hand is legal, because the <literal>==</literal> operator has a lower
precedence than the <literal>&lt;=</literal> operator.
</para>
<para>
Associativity is only meaningful for binary (and ternary) operators.
Unary operators are either prefix or postfix so this notion is not applicable.
For example <literal>!!$a</literal> can only be grouped as <literal>!(!$a)</literal>.
</para>
<para>
Use of parentheses, even when not strictly necessary, can often increase
readability of the code by making grouping explicit rather than relying
Expand Down Expand Up @@ -93,6 +98,8 @@
<row>
<entry>(n/a)</entry>
<entry>
<literal>+</literal>
<literal>-</literal>
<literal>++</literal>
<literal>--</literal>
<literal>~</literal>
Expand All @@ -105,14 +112,18 @@
<literal>@</literal>
</entry>
<entry>
<link linkend="language.types">types</link> and <link linkend="language.operators.increment">increment/decrement</link>
<link linkend="language.operators.arithmetic">arithmetic</link> (unary <literal>+</literal> and <literal>-</literal>),
<link linkend="language.operators.increment">increment/decrement</link>,
<link linkend="language.operators.bitwise">bitwise</link>,
<link linkend="language.types.typecasting">type casting</link>&listendand;
<link linkend="language.operators.errorcontrol">error control</link>
</entry>
</row>
<row>
<entry>left</entry>
<entry><literal>instanceof</literal></entry>
<entry>
<link linkend="language.types">types</link>
<link linkend="language.operators.type">type</link>
</entry>
</row>
<row>
Expand Down Expand Up @@ -141,8 +152,10 @@
<literal>.</literal>
</entry>
<entry>
<link linkend="language.operators.arithmetic">arithmetic</link>&listendand;
<link linkend="language.operators.string">string</link></entry>
<link linkend="language.operators.arithmetic">arithmetic</link> (binary <literal>+</literal> and <literal>-</literal>),
<link linkend="language.operators.array">array</link>&listendand;
<link linkend="language.operators.string">string</link> (<literal>.</literal> prior to PHP 8.0.0)
</entry>
</row>
<row>
<entry>left</entry>
Expand All @@ -154,6 +167,13 @@
<link linkend="language.operators.bitwise">bitwise</link>
</entry>
</row>
<row>
<entry>left</entry>
<entry><literal>.</literal></entry>
<entry>
<link linkend="language.operators.string">string</link> (as of PHP 8.0.0)
</entry>
</row>
<row>
<entry>non-associative</entry>
<entry>
Expand Down Expand Up @@ -223,10 +243,11 @@
</entry>
</row>
<row>
<entry>(n/a)</entry>
<entry>non-associative</entry>
<entry><literal>? :</literal></entry>
<entry>
<link linkend="language.operators.comparison.ternary">ternary</link>
(left-associative prior to PHP 8.0.0)
</entry>
</row>
<row>
Expand Down Expand Up @@ -303,7 +324,7 @@
<?php
$a = 3 * 3 % 5; // (3 * 3) % 5 = 4
// ternary operator associativity differs from C/C++
$a = true ? 0 : true ? 1 : 2; // (true ? 0 : true) ? 1 : 2 = 2
$a = true ? 0 : true ? 1 : 2; // (true ? 0 : true) ? 1 : 2 = 2 (prior to PHP 8.0.0)
$a = 1;
$b = 2;
Expand Down Expand Up @@ -335,14 +356,14 @@ $array[$i] = $i++; // may set either index 1 or 2
</programlisting>
</example>
<example>
<title><literal>+</literal>, <literal>-</literal> and <literal>.</literal> have the same precedence</title>
<title><literal>+</literal>, <literal>-</literal> and <literal>.</literal> have the same precedence (prior to PHP 8.0.0)</title>
<programlisting role="php">
<![CDATA[
<?php
$x = 4;
// this line might result in unexpected output:
echo "x minus one equals " . $x-1 . ", or so I hope\n";
// because it is evaluated like this line:
// because it is evaluated like this line (prior to PHP 8.0.0):
echo (("x minus one equals " . $x) - 1) . ", or so I hope\n";
// the desired precedence can be enforced by using parentheses:
echo "x minus one equals " . ($x-1) . ", or so I hope\n";
Expand Down Expand Up @@ -379,13 +400,32 @@ x minus one equals 3, or so I hope
</row>
</thead>
<tbody>
<row>
<entry>8.0.0</entry>
<entry>
String concatenation (<literal>.</literal>) now has a lower precedence than
arithmetic addition/subtraction (<literal>+</literal> and <literal>-</literal>) and
bitwise shift left/right (<literal>&lt;&lt;</literal> and <literal>&gt;&gt;</literal>);
previously it had the same precedence as <literal>+</literal> and <literal>-</literal>
and a higher precedence than <literal>&lt;&lt;</literal> and <literal>&gt;&gt;</literal>.
</entry>
</row>
<row>
<entry>8.0.0</entry>
<entry>
The ternary operator (<literal>? :</literal>) is non-associative now;
previously it was left-associative.
</entry>
</row>
<row>
<entry>7.4.0</entry>
<entry>
Relying on the precedence of string concatenation (<literal>.</literal>) relative to
arithmetic addition/subtraction (<literal>+</literal> or <literal>-</literal>) or
bitwise shift left/right (<literal>&lt;&lt;</literal> or <literal>&gt;&gt;</literal>),
i.e. using them together in an unparenthesized expression, is deprecated.
</entry>
</row>
<row>
<entry>7.4.0</entry>
<entry>
Expand Down

0 comments on commit 011596b

Please sign in to comment.