Fix five defects the port uncovered in the reference parser and scanner

Chained subtraction and exponentiation fold left instead of abandoning the
rest of the line -- `1 - 2 - 3` gave -1 and dropped the `- 3`. A unary leaf's
operand moves to .left, so a negative literal is one argument again and a
second argument no longer overwrites it. An operator in a line's final column
survives. Hex literals reach the parser whole. A leading zero is padding, not
a radix.

Item 16 stays pinned: the fix works and costs an upstream golden case, which
is a decision rather than a defect.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-31 11:35:14 -04:00
parent f24201fdef
commit 1eb8f9ffaa
14 changed files with 272 additions and 167 deletions

View File

@@ -73,19 +73,18 @@ int main(void)
/* AND and OR sit below comparison. */
expect_tree("A# = 1 == 1 AND 2 == 2", "( A# (AND (= 1 1) (= 2 2)))");
/* Exponent. */
expect_tree("A# = 2 ^ 3", "( A# (^ 2 3))");
/*
* Addition loops over its operator; subtraction returns after one. So
* `1 + 2 + 3` folds left, while `1 - 2 - 3` parses only `1 - 2` and leaves
* `- 3` in the token stream for the statement loop to pick up as a second
* statement. That silently computes the wrong answer -- TODO.md section 12
* item 12 -- and is pinned here so the fix is a deliberate change to this
* assertion and not an accident.
* Every same-precedence run folds left, which is what a C128 does and what
* TODO.md section 6 item 12 was about: the reference returns after one
* operator in subtraction() and exponent(), so `1 - 2 - 3` computed `1 - 2`
* and left `- 3` in the token stream for the statement loop to evaluate and
* discard. A wrong answer, silently. These four are the regression test.
*/
expect_tree("A# = 1 + 2 + 3", "( A# (+ (+ 1 2) 3))");
expect_tree("A# = 1 - 2 - 3", "( A# (- 1 2))");
expect_tree("A# = 1 - 2 - 3", "( A# (- (- 1 2) 3))");
expect_tree("A# = 10 - 1 - 2 - 3", "( A# (- (- (- 10 1) 2) 3))");
expect_tree("A# = 2 ^ 3", "( A# (^ 2 3))");
expect_tree("A# = 2 ^ 3 ^ 2", "( A# (^ (^ 2 3) 2))");
/* An array reference parses as an identifier carrying a subscript list. */
TEST_REQUIRE_OK(harness_parse("A#(2) = 1", &leaf));