Feat: add compound assignment and shift operators

Compound assignment: +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
Shift: <<, >>

Each compound assignment token parses at the same precedence as `=`
(right-associative, lowest) and produces ExprKind::CompoundAssign.
Shifts parse between additive and multiplicative precedence.
GRAMMAR.ebnf and SYNTAX.md updated accordingly.
This commit is contained in:
2026-03-10 18:29:52 +01:00
parent 1a4e464d5e
commit a82b7e4633
6 changed files with 269 additions and 56 deletions

View File

@@ -24,20 +24,32 @@ appear as UPPERCASE terminals in `GRAMMAR.ebnf`.
### Operator Tokens
| Token | Lexeme | Description |
| --------- | ------ | -------------------------------------- |
| `PLUS` | `+` | Addition / unary plus (not in grammar) |
| `MINUS` | `-` | Subtraction / unary negation |
| `STAR` | `*` | Multiplication / pointer dereference |
| `SLASH` | `/` | Division |
| `PERCENT` | `%` | Modulo (remainder) |
| `AMP` | `&` | Bitwise AND / address-of |
| `PIPE` | `\|` | Bitwise OR |
| `CARET` | `^` | Bitwise XOR |
| `BANG` | `!` | Logical NOT |
| `TILDE` | `~` | Bitwise NOT |
| `DOT` | `.` | Member access |
| `EQ` | `=` | Assignment |
| Token | Lexeme | Description |
| ------------ | ------ | -------------------------------------- |
| `PLUS` | `+` | Addition / unary plus (not in grammar) |
| `MINUS` | `-` | Subtraction / unary negation |
| `STAR` | `*` | Multiplication / pointer dereference |
| `SLASH` | `/` | Division |
| `PERCENT` | `%` | Modulo (remainder) |
| `AMP` | `&` | Bitwise AND / address-of |
| `PIPE` | `\|` | Bitwise OR |
| `CARET` | `^` | Bitwise XOR |
| `BANG` | `!` | Logical NOT |
| `TILDE` | `~` | Bitwise NOT |
| `DOT` | `.` | Member access |
| `SHL` | `<<` | Left shift |
| `SHR` | `>>` | Right shift |
| `EQ` | `=` | Assignment |
| `PLUS_EQ` | `+=` | Add-assign |
| `MINUS_EQ` | `-=` | Subtract-assign |
| `STAR_EQ` | `*=` | Multiply-assign |
| `SLASH_EQ` | `/=` | Divide-assign |
| `PERCENT_EQ` | `%=` | Modulo-assign |
| `AMP_EQ` | `&=` | Bitwise-AND-assign |
| `PIPE_EQ` | `\|=` | Bitwise-OR-assign |
| `CARET_EQ` | `^=` | Bitwise-XOR-assign |
| `SHL_EQ` | `<<=` | Left-shift-assign |
| `SHR_EQ` | `>>=` | Right-shift-assign |
### Keyword Tokens
@@ -127,19 +139,20 @@ tightly).
### Operator Precedence Table
| Level | Operators | Associativity | Description |
| ----- | --------------------------- | -------------- | -------------------------------- |
| 1 | `=` | right | Assignment (lowest) |
| 2 | `or` | left | Logical OR |
| 3 | `and` | left | Logical AND |
| 4 | `\|` | left | Bitwise OR |
| 5 | `^` | left | Bitwise XOR |
| 6 | `&` | left | Bitwise AND |
| 7 | `+` `-` | left | Addition, subtraction |
| 8 | `*` `/` `%` | left | Multiplication, division, modulo |
| 9 | `!` `~` `-` `*` `&` | right (unary) | Prefix unary operators |
| 10 | `.` `[…]` `(…)` | left (postfix) | Member access, index, call |
| 11 | literals, identifiers, `()` | — | Primary expressions (highest) |
| Level | Operators | Associativity | Description |
| ----- | -------------------------------------------------------- | -------------- | -------------------------------- |
| 1 | `=` `+=` `-=` `*=` `/=` `%=` `&=` `\|=` `^=` `<<=` `>>=` | right | Assignment (lowest) |
| 2 | `or` | left | Logical OR |
| 3 | `and` | left | Logical AND |
| 4 | `\|` | left | Bitwise OR |
| 5 | `^` | left | Bitwise XOR |
| 6 | `&` | left | Bitwise AND |
| 7 | `+` `-` | left | Addition, subtraction |
| 8 | `<<` `>>` | left | Bit shift |
| 9 | `*` `/` `%` | left | Multiplication, division, modulo |
| 10 | `!` `~` `-` `*` `&` | right (unary) | Prefix unary operators |
| 11 | `.` `[…]` `()` | left (postfix) | Member access, index, call |
| 12 | literals, identifiers, `()` | — | Primary expressions (highest) |
### Operator Descriptions
@@ -148,6 +161,18 @@ tightly).
| Operator | Name | Example | Notes |
| -------- | -------------- | --------- | ---------------------------------------------- |
| `=` | Assignment | `a = b` | Right-associative; `a = b = c``a = (b = c)` |
| `+=` | Add-assign | `a += b` | Expands to `a = a + b` |
| `-=` | Sub-assign | `a -= b` | Expands to `a = a - b` |
| `*=` | Mul-assign | `a *= b` | Expands to `a = a * b` |
| `/=` | Div-assign | `a /= b` | Expands to `a = a / b` |
| `%=` | Rem-assign | `a %= b` | Expands to `a = a % b` |
| `&=` | BitAnd-assign | `a &= b` | Expands to `a = a & b` |
| `\|=` | BitOr-assign | `a \|= b` | Expands to `a = a \| b` |
| `^=` | BitXor-assign | `a ^= b` | Expands to `a = a ^ b` |
| `<<` | Left shift | `a << b` | Shift `a` left by `b` bits; integer types |
| `>>` | Right shift | `a >> b` | Shift `a` right by `b` bits; integer types |
| `<<=` | Shl-assign | `a <<= b` | Expands to `a = a << b` |
| `>>=` | Shr-assign | `a >>= b` | Expands to `a = a >> b` |
| `or` | Logical OR | `a or b` | Short-circuits; both operands must be `bool` |
| `and` | Logical AND | `a and b` | Short-circuits; both operands must be `bool` |
| `\|` | Bitwise OR | `a \| b` | Integer types |