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:
20
src/parser.c
20
src/parser.c
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user