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:
@@ -185,14 +185,19 @@ akerr_ErrorContext *akbasic_leaf_new_binary(akbasic_ASTLeaf *obj, akbasic_ASTLea
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
akerr_ErrorContext *akbasic_leaf_new_unary(akbasic_ASTLeaf *obj, akbasic_TokenType op, akbasic_ASTLeaf *right)
|
||||
akerr_ErrorContext *akbasic_leaf_new_unary(akbasic_ASTLeaf *obj, akbasic_TokenType op, akbasic_ASTLeaf *operand)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
|
||||
FAIL_ZERO_RETURN(errctx, (obj != NULL), AKERR_NULLPOINTER, "NULL leaf in new_unary");
|
||||
FAIL_ZERO_RETURN(errctx, (right != NULL), AKERR_NULLPOINTER, "nil pointer arguments");
|
||||
FAIL_ZERO_RETURN(errctx, (operand != NULL), AKERR_NULLPOINTER, "nil pointer arguments");
|
||||
PASS(errctx, akbasic_leaf_init(obj, AKBASIC_LEAF_UNARY));
|
||||
obj->right = right;
|
||||
/*
|
||||
* .left, not .right. An argument list chains its arguments through .right,
|
||||
* so an operand there is indistinguishable from a second argument: ABS(-9)
|
||||
* counted as two and was refused. See the note on the declaration.
|
||||
*/
|
||||
obj->left = operand;
|
||||
obj->operator_ = op;
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
@@ -268,16 +273,14 @@ akerr_ErrorContext *akbasic_leaf_new_literal_int(akbasic_ASTLeaf *obj, const cha
|
||||
FAIL_ZERO_RETURN(errctx, (lexeme[0] != '\0'), AKBASIC_ERR_VALUE, "Empty integer literal");
|
||||
|
||||
/*
|
||||
* The reference selects base 8 for any lexeme starting with '0', so `010`
|
||||
* parses as 8 and `08` is an error. Commodore BASIC has no octal literals
|
||||
* and this is TODO.md section 12 item 10 -- but it is reproduced here,
|
||||
* because "port the behaviour first" is the rule and the fix is its own
|
||||
* commit with its own test.
|
||||
* Base 10 unless the lexeme is prefixed `0x`. The reference selects base 8
|
||||
* for *any* lexeme starting with '0' (basicgrammar.go:224), so `PRINT 010`
|
||||
* printed 8 and `PRINT 08` was a parse error -- TODO.md section 6 item 10.
|
||||
* Commodore BASIC has no octal literals, and a leading zero in a listing is
|
||||
* padding, not a radix.
|
||||
*/
|
||||
if ( strlen(lexeme) > 2 && strncmp(lexeme, "0x", 2) == 0 ) {
|
||||
base = 16;
|
||||
} else if ( lexeme[0] == '0' ) {
|
||||
base = 8;
|
||||
}
|
||||
PASS(errctx, akbasic_leaf_init(obj, AKBASIC_LEAF_LITERAL_INT));
|
||||
PASS(errctx, aksl_strtoll(lexeme, NULL, base, &value));
|
||||
@@ -366,7 +369,7 @@ akerr_ErrorContext *akbasic_leaf_to_string(akbasic_ASTLeaf *self, char *dest, si
|
||||
snprintf(dest, len, "NOT IMPLEMENTED");
|
||||
break;
|
||||
case AKBASIC_LEAF_UNARY:
|
||||
PASS(errctx, akbasic_leaf_to_string(self->right, sub1, sizeof(sub1)));
|
||||
PASS(errctx, akbasic_leaf_to_string(self->left, sub1, sizeof(sub1)));
|
||||
snprintf(dest, len, "(%s %s)", operator_to_str(self->operator_), sub1);
|
||||
break;
|
||||
case AKBASIC_LEAF_BINARY:
|
||||
|
||||
Reference in New Issue
Block a user