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

@@ -200,15 +200,21 @@ akerr_ErrorContext AKERR_NOIGNORE *akbasic_leaf_new_binary(akbasic_ASTLeaf *obj,
/**
* @brief Build a unary-operator leaf.
*
* The operand hangs off `.right`, which is why the arity counter in the parser
* miscounts a negative literal argument -- see TODO.md section 6 item 13.
* **The operand hangs off `.left`, not `.right`, and that is deliberate.** The
* reference puts it on `.right` (basicgrammar.go's newUnary), which is also
* where an argument list chains its arguments -- so `ABS(-9)` counted as two
* arguments and was refused, and a unary argument followed by a comma had its
* operand overwritten by the next argument. TODO.md section 6 item 13. A unary
* leaf has no other use for `.left`, so moving it there separates the two
* meanings for the cost of one field nobody was using.
*
* @param obj Leaf to initialize; drawn from a pool by the caller.
* @param op Operator token.
* @param right Operand.
* @param operand The expression the operator applies to.
* @return `NULL` on success, otherwise an error context owned by the caller.
* @throws AKERR_NULLPOINTER When `right` is NULL.
* @throws AKERR_NULLPOINTER When `operand` is NULL.
*/
akerr_ErrorContext AKERR_NOIGNORE *akbasic_leaf_new_unary(akbasic_ASTLeaf *obj, akbasic_TokenType op, akbasic_ASTLeaf *right);
akerr_ErrorContext AKERR_NOIGNORE *akbasic_leaf_new_unary(akbasic_ASTLeaf *obj, akbasic_TokenType op, akbasic_ASTLeaf *operand);
/**
* @brief Build a function-call leaf.
* @param obj Leaf to initialize; drawn from a pool by the caller.