Give argument lists their own link, not each argument's .right

An identifier's subscript list, a unary's operand and a binary's right-hand
side all lived in the same field the argument chain used, so ABS(-9),
MOD(A#, B# + 12) and any array reference in a parameter list were counted as
extra arguments and refused. Subscript lists move to .expr and arguments now
chain through a dedicated .next.

This is the third time the same collision was fixed; the first two moved it
along rather than removing it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-31 11:58:15 -04:00
parent 5b7b7d2ed9
commit f4007d80d4
14 changed files with 133 additions and 55 deletions

View File

@@ -292,10 +292,16 @@ akerr_ErrorContext *akbasic_parser_argument_list(akbasic_Parser *obj, akbasic_To
arglist->operator_ = arglisttype;
PASS(errctx, akbasic_parser_expression(obj, &arglist->right));
/*
* Siblings chain through .next, never through .right. Every leaf type that
* can be an argument already uses .right for something of its own -- a
* unary's operand, a binary's right-hand side -- and reusing it here is what
* made ABS(-9) count as two arguments. See akbasic_ASTLeaf.next.
*/
expr = arglist->right;
while ( expr != NULL && akbasic_parser_match1(obj, AKBASIC_TOK_COMMA) ) {
PASS(errctx, akbasic_parser_expression(obj, &expr->right));
expr = expr->right;
PASS(errctx, akbasic_parser_expression(obj, &expr->next));
expr = expr->next;
}
if ( !akbasic_parser_match1(obj, AKBASIC_TOK_RIGHT_PAREN) && requireparens ) {
FAIL_RETURN(errctx, AKBASIC_ERR_SYNTAX, "Unbalanced parenthesis");
@@ -523,7 +529,7 @@ static akerr_ErrorContext *exponent(akbasic_Parser *obj, akbasic_ASTLeaf **dest)
SUCCEED_RETURN(errctx);
}
/* Count the .right-joined chain hanging off an argument list. */
/* Count the arguments hanging off an argument list. */
static int arglist_length(akbasic_ASTLeaf *arglist)
{
akbasic_ASTLeaf *leaf = NULL;
@@ -532,7 +538,7 @@ static int arglist_length(akbasic_ASTLeaf *arglist)
if ( arglist == NULL ) {
return 0;
}
for ( leaf = arglist->right; leaf != NULL; leaf = leaf->right ) {
for ( leaf = arglist->right; leaf != NULL; leaf = leaf->next ) {
count += 1;
}
return count;
@@ -624,15 +630,15 @@ akerr_ErrorContext *akbasic_parser_primary(akbasic_Parser *obj, akbasic_ASTLeaf
break;
case AKBASIC_TOK_IDENTIFIER_INT:
PASS(errctx, akbasic_leaf_new_identifier(expr, AKBASIC_LEAF_IDENTIFIER_INT, previous->lexeme));
PASS(errctx, akbasic_parser_argument_list(obj, AKBASIC_TOK_ARRAY_SUBSCRIPT, true, &expr->right));
PASS(errctx, akbasic_parser_argument_list(obj, AKBASIC_TOK_ARRAY_SUBSCRIPT, true, &expr->expr));
break;
case AKBASIC_TOK_IDENTIFIER_FLOAT:
PASS(errctx, akbasic_leaf_new_identifier(expr, AKBASIC_LEAF_IDENTIFIER_FLOAT, previous->lexeme));
PASS(errctx, akbasic_parser_argument_list(obj, AKBASIC_TOK_ARRAY_SUBSCRIPT, true, &expr->right));
PASS(errctx, akbasic_parser_argument_list(obj, AKBASIC_TOK_ARRAY_SUBSCRIPT, true, &expr->expr));
break;
case AKBASIC_TOK_IDENTIFIER_STRING:
PASS(errctx, akbasic_leaf_new_identifier(expr, AKBASIC_LEAF_IDENTIFIER_STRING, previous->lexeme));
PASS(errctx, akbasic_parser_argument_list(obj, AKBASIC_TOK_ARRAY_SUBSCRIPT, true, &expr->right));
PASS(errctx, akbasic_parser_argument_list(obj, AKBASIC_TOK_ARRAY_SUBSCRIPT, true, &expr->expr));
break;
case AKBASIC_TOK_FUNCTION:
case AKBASIC_TOK_IDENTIFIER: