| author | |
| committer | |
| log | 04e8a5e42b58f1fdeb749caf22a1c998344b3ba8 |
| tree | 27df45c147ef52ea46763759a055a1067bcb1068 |
| parent | 65924d31e4ed3234303d6c6ca72cf30cda0cbaa3 |
2 files changed, 123 insertions(+), 28 deletions(-)
doc/langref.html.in+36-28| ... | @@ -1907,35 +1907,7 @@ and | ... | @@ -1907,35 +1907,7 @@ and |
| 1907 | or | 1907 | or |
| 1908 | = *= *%= *|= /= %= += +%= +|= -= -%= -|= <<= <<|= >>= &= ^= |={#endsyntax#}</pre> | 1908 | = *= *%= *|= /= %= += +%= +|= -= -%= -|= <<= <<|= >>= &= ^= |={#endsyntax#}</pre> |
| 1909 | {#header_close#} | 1909 | {#header_close#} |
| 1910 | <p> | ||
| 1911 | However, understanding the full ambiguity rules are not necessary for reading or writing code. Instead, having an understanding of the unambiguous cases for the operators, you're using is more practical. To that end, some simplified versions, of the precedence table are provided below, tailored to understanding particular groups of operator groups. The operators that have ambiguous precedence with the given operators in question have been omitted, as have operators with higher precedence. The operators colored <span style="color: orange">orange</span> have ambiguous precedence with other operators on the same line. | ||
| 1912 | |||
| 1913 | For arithmetic and error set operators, the simplfied precedence table would look like this. | ||
| 1914 | </p> | ||
| 1915 | |||
| 1916 | <pre><code>* / *% *| || <span style="color: orange">%</span> | ||
| 1917 | + - ++ +% -% +| -| | ||
| 1918 | == != &lt; > &lt;= >= | ||
| 1919 | <span style="color: orange">and or</span> | ||
| 1920 | = *= *%= *|= /= %= += +%= +|= -= -%= -|= &lt;&lt;= &lt;&lt;|= >>= &= ^= |=</code></pre> | ||
| 1921 | |||
| 1922 | <p> | ||
| 1923 | For bitwise operators, it would look like this: | ||
| 1924 | </p> | ||
| 1925 | 1910 | ||
| 1926 | <pre><code><span style="color: orange">&lt;&lt; &lt;&lt;| >> & ^ |</span> | ||
| 1927 | == != &lt; > &lt;= >= | ||
| 1928 | <span style="color: orange">and or</span> | ||
| 1929 | = *= *%= *|= /= %= += +%= +|= -= -%= -|= &lt;&lt;= &lt;&lt;|= >>= &= ^= |=</code></pre> | ||
| 1930 | |||
| 1931 | <p> | ||
| 1932 | For null and error recovery, it would look like this: | ||
| 1933 | </p> | ||
| 1934 | |||
| 1935 | <pre><code><span style="color: orange">catch orelse</span> | ||
| 1936 | = *= *%= *|= /= %= += +%= +|= -= -%= -|= &lt;&lt;= &lt;&lt;|= >>= &= ^= |=</code></pre> | ||
| 1937 | |||
| 1938 | {#header_close#} | ||
| 1939 | {#header_close#} | 1911 | {#header_close#} |
| 1940 | 1912 | ||
| 1941 | {#header_open|Arrays#} | 1913 | {#header_open|Arrays#} |
| ... | @@ -7909,6 +7881,42 @@ fn readU32Be() u32 {} | ... | @@ -7909,6 +7881,42 @@ fn readU32Be() u32 {} |
| 7909 | {#header_open|Appendix#} | 7881 | {#header_open|Appendix#} |
| 7910 | {#header_open|Grammar#} | 7882 | {#header_open|Grammar#} |
| 7911 | {#grammar#} | 7883 | {#grammar#} |
| 7884 | {#header_open|Operator Precedence Flowchart#} | ||
| 7885 | <p> | ||
| 7886 | To help understand the grammar, this flowchart is provided for the operator precedence. | ||
| 7887 | The bottom represents any location where an expression may occur and the topmost row represents | ||
| 7888 | a parenthesized expression. An operator will have a higher precedence (and therefore be the parent) to | ||
| 7889 | another node if it is strictly lower on the tree (having a directed path from one to another). This is inverted from classical precedence, but | ||
| 7890 | is closer to how a recursive descent parser views the grammar. | ||
| 7891 | </p> | ||
| 7892 | <pre><code> | ||
| 7893 | ┏━━━━━━━━━━━━━━━━━━━┓ | ||
| 7894 | ┃(expr) ┃ | ||
| 7895 | ┃x() x[] x.y x.* x.?┃ | ||
| 7896 | ┃E!T ┃ | ||
| 7897 | ┃x{} ┃ | ||
| 7898 | ┃!x -x -%x ~x &x ?x ┃ | ||
| 7899 | ┗━━━━━━━━━▲━━━━━━━━━┛ | ||
| 7900 | ┌─────────────┬──────┴───────┬───────┬──┬──┬─┐ | ||
| 7901 | │ │ │ │ │ │ │ | ||
| 7902 | ┏━━━━━━┷━━━━━┓╭Non╌Chaining╮ ╭Non╌Chaining╮┏┷┓┏┷┓┏┷┓│ | ||
| 7903 | ┃* *% *| / ||┃╎ % ╎ ╎ &lt;&lt; &lt;&lt;| >> ╎┃&┃┃^┃┃|┃│ | ||
| 7904 | ┗━━━━━━▲━━━━━┛╰╌╌╌╌╌╌▲╌╌╌╌╌╯ ╰╌╌╌╌╌╌▲╌╌╌╌╌╯┗▲┛┗▲┛┗▲┛│ | ||
| 7905 | ┏━━┷━━━━━━━━━━━━━┷━┓ ┌────┴───────┴──┴──┘ │ | ||
| 7906 | ┃+ - +% -% +| -| ++┃ │ │ | ||
| 7907 | ┗━━━━━━━━━━━▲━━━━━━┛ │ │ | ||
| 7908 | ╭┴╌Non-Chaining╌┴╮ │ | ||
| 7909 | ╎== != &lt; &lt;= >= >╎ │ | ||
| 7910 | ╰╌╌╌▲╌╌╌╌▲╌╌╌╌╌╌╌╯ ┌──────┬─────┘ | ||
| 7911 | ┏━┷━┓┏━┷━┓ ┏━━━┷━━┓┏━━┷━━┓ | ||
| 7912 | ┃and┃┃or ┃ ┃orelse┃┃catch┃ | ||
| 7913 | ┗━▲━┛┗━▲━┛ ┗━━━▲━━┛┗━━▲━━┛ | ||
| 7914 | ╭╌╌┴╌╌╌╌┴╌╌╌╌╌╌╌╌╌╌╌╌╌╌┴╌╌╌╌╌╌┴╌╮ | ||
| 7915 | ╎ Any expression location ╎ | ||
| 7916 | ╰╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ | ||
| 7917 | |||
| 7918 | </code></pre> | ||
| 7919 | {#header_close#} | ||
| 7912 | {#header_close#} | 7920 | {#header_close#} |
| 7913 | {#header_open|Zen#} | 7921 | {#header_open|Zen#} |
| 7914 | <ul> | 7922 | <ul> |
doc/langref/incremental_operator_precedence.zig created+87| ... | @@ -0,0 +1,87 @@ | ||
| 1 | const expectEqual = @import("std").testing.expectEqual; | ||
| 2 | const expect = @import("std").testing.expect; | ||
| 3 | |||
| 4 | test "Operator Precedence" { | ||
| 5 | // Arithmetic | ||
| 6 | // + and - can be freely mixed and are left associative | ||
| 7 | try expectEqual((2 + 3) + 4, 2 + 3 + 4); | ||
| 8 | try expectEqual((1 - 2) - 3, 1 - 2 - 3); | ||
| 9 | |||
| 10 | // Saturating and wrapping modifications to arithmetic operators act the same | ||
| 11 | const x: u8 = 255; | ||
| 12 | try expectEqual((x +% 2) -| 3, x +% 2 -| 3); | ||
| 13 | try expectEqual(0, x +% 2 -| 3); | ||
| 14 | |||
| 15 | // Since all associative operators are left associative, non-left-to-right evaluation must be forced with parenthesis | ||
| 16 | try expectEqual(255, x +% (2 -| 3)); | ||
| 17 | |||
| 18 | // * and / can be freely mixed and bind tigher than any addition | ||
| 19 | try expectEqual((8 / 2) * 4, 8 / 2 * 4); | ||
| 20 | try expectEqual(1 + (2 * 3), 1 + 2 * 3); | ||
| 21 | |||
| 22 | // The Modulus is special in that it cannot be repeated without parenthesis | ||
| 23 | // The following line would be a compile error | ||
| 24 | // _ = x % 7 % 3; | ||
| 25 | // However it does bind tighter than addition | ||
| 26 | try expectEqual(1 + (x % 3), 1 + x % 3); | ||
| 27 | |||
| 28 | // Bitwise Operators | ||
| 29 | // &, |, and ^ can all be freely repeated, but not mixed without parenthesis | ||
| 30 | try expectEqual((x & 0xF) & 1, x & 0xF & 1); | ||
| 31 | try expectEqual((x | 0xF) | 1, x | 0xF | 1); | ||
| 32 | try expectEqual((x ^ 0xF) ^ 1, x ^ 0xF ^ 1); | ||
| 33 | // The following line would be a compile error | ||
| 34 | // _ = x & 0xF | 0xF0; | ||
| 35 | |||
| 36 | // Bitshifts <<, <<|, and >> cannot be repeated without parenthesis nor mixed with other bitwise operators | ||
| 37 | // The following lines would be compile errors | ||
| 38 | // _ = x >> 1 >> 2; | ||
| 39 | // _ = 1 << 16 | 1 << 8 | 1; | ||
| 40 | // Instead parentheses should be used | ||
| 41 | try expectEqual(63, (x >> 1) >> 2); | ||
| 42 | try expectEqual(0x10101, (1 << 16) | (1 << 8) | 1); | ||
| 43 | |||
| 44 | // Comparisons | ||
| 45 | // < > <= >= == != cannot be chained | ||
| 46 | // Binds lower than either bitwise operators or arithmetic operators | ||
| 47 | // which allows one on one side and one on the other | ||
| 48 | try expect(1 | 4 <= 1 + 4); | ||
| 49 | // equivilent to this code | ||
| 50 | try expect((1 | 4) <= (1 + 4)); | ||
| 51 | |||
| 52 | // Boolean Operators | ||
| 53 | // `and` and `or` can be freely chained with themselves, shortcircuiting left to right | ||
| 54 | // they may not be mixed with each other without parenthesis | ||
| 55 | // bind looser than comparisons | ||
| 56 | const false_expr: bool = 7 < 2; | ||
| 57 | const true_expr: bool = 1 + 1 == 2; | ||
| 58 | |||
| 59 | try expect(false_expr or false_expr or true_expr); | ||
| 60 | try expect(7 < 2 or 7 < 2 or 1 + 1 == 2); | ||
| 61 | try expect(((7 < 2) or (7 < 2)) or (1 + 1 == 2)); | ||
| 62 | |||
| 63 | try expect(true_expr and true_expr and true_expr); | ||
| 64 | try expect(1 + 1 == 2 and 1 + 1 == 2 and 1 + 1 == 2); | ||
| 65 | try expect(((1 + 1 == 2) and (1 + 1 == 2)) and (1 + 1 == 2)); | ||
| 66 | |||
| 67 | // The following line would be a compile error | ||
| 68 | // _ = false_expr or true_expr and true_expr | ||
| 69 | // Instead parentheses should be used | ||
| 70 | try expect(false_expr or (true_expr and true_expr)); | ||
| 71 | |||
| 72 | // Orelse and Catch | ||
| 73 | // Like Boolean Operators, may be chained with themselves, but not each other | ||
| 74 | // bind looser than prefix expressions | ||
| 75 | const some_null: ?u8 = null; | ||
| 76 | try expectEqual(2, some_null orelse some_null orelse 2); | ||
| 77 | |||
| 78 | const some_error: error{invalid}!u8 = error.invalid; | ||
| 79 | try expectEqual(3, some_error catch some_error catch 3); | ||
| 80 | |||
| 81 | // The following line would be a compile error | ||
| 82 | // _ = some_error catch some_null orelse 1; | ||
| 83 | // Instead parentheses should be used | ||
| 84 | try expectEqual(1, (some_error catch some_null) orelse 1); | ||
| 85 | } | ||
| 86 | |||
| 87 | // obj | ||
| \ No newline at end of file | |||