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

@@ -69,8 +69,8 @@ akerr_ErrorContext *akbasic_parse_draw(akbasic_Parser *parser, akbasic_ASTLeaf *
"DRAW expected a color source and a coordinate");
tail = arglist->right;
while ( tail->right != NULL ) {
tail = tail->right;
while ( tail->next != NULL ) {
tail = tail->next;
}
for ( ;; ) {
@@ -82,16 +82,16 @@ akerr_ErrorContext *akbasic_parse_draw(akbasic_Parser *parser, akbasic_ASTLeaf *
}
FAIL_ZERO_RETURN(errctx, akbasic_parser_match1(parser, AKBASIC_TOK_COMMAND),
AKBASIC_ERR_SYNTAX, "DRAW expected TO");
PASS(errctx, akbasic_parser_expression(parser, &tail->right));
FAIL_ZERO_RETURN(errctx, (tail->right != NULL), AKBASIC_ERR_SYNTAX,
PASS(errctx, akbasic_parser_expression(parser, &tail->next));
FAIL_ZERO_RETURN(errctx, (tail->next != NULL), AKBASIC_ERR_SYNTAX,
"DRAW expected X after TO");
tail = tail->right;
tail = tail->next;
FAIL_ZERO_RETURN(errctx, akbasic_parser_match1(parser, AKBASIC_TOK_COMMA),
AKBASIC_ERR_SYNTAX, "DRAW expected TO X,Y");
PASS(errctx, akbasic_parser_expression(parser, &tail->right));
FAIL_ZERO_RETURN(errctx, (tail->right != NULL), AKBASIC_ERR_SYNTAX,
PASS(errctx, akbasic_parser_expression(parser, &tail->next));
FAIL_ZERO_RETURN(errctx, (tail->next != NULL), AKBASIC_ERR_SYNTAX,
"DRAW expected Y after TO X,");
tail = tail->right;
tail = tail->next;
}
PASS(errctx, akbasic_parser_new_leaf(parser, &expr));
@@ -174,7 +174,7 @@ akerr_ErrorContext *akbasic_parse_def(akbasic_Parser *parser, akbasic_ASTLeaf **
FAIL_ZERO_RETURN(errctx, (arglist != NULL), AKBASIC_ERR_SYNTAX,
"Expected argument list (identifier names)");
for ( walk = arglist->right; walk != NULL; walk = walk->right ) {
for ( walk = arglist->right; walk != NULL; walk = walk->next ) {
FAIL_ZERO_RETURN(errctx,
(walk->leaftype == AKBASIC_LEAF_IDENTIFIER_STRING ||
walk->leaftype == AKBASIC_LEAF_IDENTIFIER_INT ||
@@ -321,12 +321,12 @@ akerr_ErrorContext *akbasic_parse_read(akbasic_Parser *parser, akbasic_ASTLeaf *
"Expected identifier");
PASS(errctx, akbasic_leaf_clone(expr, &env->readLeafPool, &env->readIdentifierLeaves[i]));
/*
* A cloned identifier keeps its .right chain, which for READ is the
* *next* identifier, not a subscript. Sever it so evaluating this leaf
* cannot walk into its sibling.
* A cloned identifier keeps its sibling chain, which for READ is the
* *next* identifier. Sever it so evaluating this leaf cannot walk into
* its sibling.
*/
env->readIdentifierLeaves[i]->right = NULL;
expr = expr->right;
env->readIdentifierLeaves[i]->next = NULL;
expr = expr->next;
}
env->readReturnLine = env->lineno + 1;
@@ -350,7 +350,7 @@ akerr_ErrorContext *akbasic_parse_data(akbasic_Parser *parser, akbasic_ASTLeaf *
PASS(errctx, akbasic_parser_argument_list(parser, AKBASIC_TOK_FUNCTION_ARGUMENT, false, &arglist));
FAIL_ZERO_RETURN(errctx, (arglist != NULL && arglist->right != NULL), AKBASIC_ERR_SYNTAX,
"Expected literal");
for ( expr = arglist->right; expr != NULL; expr = expr->right ) {
for ( expr = arglist->right; expr != NULL; expr = expr->next ) {
FAIL_ZERO_RETURN(errctx, akbasic_leaf_is_literal(expr), AKBASIC_ERR_SYNTAX,
"Expected literal");
}