An expression mixing - and + at the same level is evaluated right to left #1

Open
opened 2026-08-02 19:04:07 -04:00 by tachikoma · 0 comments
Collaborator

Source: TODO.md §6 item 35 (at 9151438)

a - b + c computes a - (b + c). A C128, and every BASIC this descends from, folds a run of
same-precedence additive operators left to right.

PRINT 10 - 3 + 2
PRINT 1 - 2 - 3
5
-4

The second line is right and the first is not; 9 is the answer. Nothing fails -- this is a
program that quietly computes something else -- and both tutorials work around it by
parenthesising every mixed + and - as a rule rather than where it happens to matter.

The cause is the grammar's shape, not a missing loop. subtraction() (src/parser.c:425)
sits above addition() (:447) as its own precedence level, and both loop correctly -- but
subtraction()'s right operand is parsed by addition(), which then consumes the + that
should have been the next term of the subtraction. 1 - 2 - 3 is right because the outer loop
sees both minuses; 10 - 3 + 2 is wrong because the inner one eats the plus first.

The fix is one additive level rather than two: a single function matching PLUS and MINUS
in one while, building left-associatively, with multiplication() beneath it. That is what the
earlier associativity fix left half-done -- it made each of the two levels fold left without
noticing there should only have been one.

Wants cases in tests/parser_expressions.c asserting 10 - 3 + 2 is 9 and 10 + 3 - 2 is 11
(which already passes, and is the asymmetry that gives it away).

Worth doing in the same sitting as the AND/OR associativity issue: one afternoon, one
file, and between them they are the two rules a tutorial currently has to spend a paragraph on.

Files: src/parser.c:425,447, tests/parser_expressions.c


Filed by Tachikoma (Claude Code, Opus 5, 1M context)

**Source:** TODO.md §6 item 35 (at 9151438) `a - b + c` computes `a - (b + c)`. A C128, and every BASIC this descends from, folds a run of same-precedence additive operators left to right. ```basic PRINT 10 - 3 + 2 PRINT 1 - 2 - 3 ``` ```output 5 -4 ``` **The second line is right and the first is not; 9 is the answer.** Nothing fails -- this is a program that quietly computes something else -- and both tutorials work around it by parenthesising every mixed `+` and `-` **as a rule** rather than where it happens to matter. **The cause is the grammar's shape, not a missing loop.** `subtraction()` (`src/parser.c:425`) sits *above* `addition()` (`:447`) as its own precedence level, and both loop correctly -- but `subtraction()`'s right operand is parsed by `addition()`, which then consumes the `+` that should have been the *next* term of the subtraction. `1 - 2 - 3` is right because the outer loop sees both minuses; `10 - 3 + 2` is wrong because the inner one eats the plus first. **The fix is one additive level rather than two:** a single function matching `PLUS` and `MINUS` in one `while`, building left-associatively, with `multiplication()` beneath it. That is what the earlier associativity fix left half-done -- it made each of the two levels fold left without noticing there should only have been one. Wants cases in `tests/parser_expressions.c` asserting `10 - 3 + 2` is 9 and `10 + 3 - 2` is 11 (which already passes, and is the asymmetry that gives it away). **Worth doing in the same sitting as the `AND`/`OR` associativity issue**: one afternoon, one file, and between them they are the two rules a tutorial currently has to spend a paragraph on. **Files:** `src/parser.c:425,447`, `tests/parser_expressions.c` --- Filed by Tachikoma (Claude Code, Opus 5, 1M context)
tachikoma added this to the 0.1.x milestone 2026-08-02 19:04:07 -04:00
tachikoma added the defectblast-radius:highstatus::grooming labels 2026-08-02 19:04:07 -04:00
Sign in to join this conversation.