@@ -321,51 +321,9 @@ contains |
| 321 | 321 | call advance(parser) ! Skip ')' |
| 322 | 322 | node => create_function_node(func_name) |
| 323 | 323 | else |
| 324 | | - ! Single argument function - parse one expression |
| 325 | | - ! Support numbers and negative numbers |
| 326 | | - if (parser%current_token%token_type == TOKEN_NUMBER) then |
| 327 | | - read(parser%current_token%text, *) num_val |
| 328 | | - value = create_scalar(num_val) |
| 329 | | - single_arg => create_literal_node(value) |
| 330 | | - call advance(parser) |
| 331 | | - else if (parser%current_token%token_type == TOKEN_OPERATOR .and. & |
| 332 | | - parser%current_token%text == '-') then |
| 333 | | - ! Handle negative numbers |
| 334 | | - call advance(parser) ! Skip minus |
| 335 | | - if (parser%current_token%token_type == TOKEN_NUMBER) then |
| 336 | | - read(parser%current_token%text, *) num_val |
| 337 | | - value = create_scalar(-num_val) ! Make negative |
| 338 | | - single_arg => create_literal_node(value) |
| 339 | | - call advance(parser) |
| 340 | | - else |
| 341 | | - call set_error(parser, 'Expected number after minus sign') |
| 342 | | - return |
| 343 | | - end if |
| 344 | | - else |
| 345 | | - call set_error(parser, 'Function arguments currently support numbers only') |
| 346 | | - return |
| 347 | | - end if |
| 348 | | - |
| 349 | | - if (.not. associated(single_arg)) then |
| 350 | | - call set_error(parser, 'Invalid function argument') |
| 351 | | - return |
| 352 | | - end if |
| 353 | | - |
| 354 | | - if (parser%current_token%token_type == TOKEN_RPAREN) then |
| 355 | | - ! Single argument - create function with one arg |
| 356 | | - call advance(parser) ! Skip ')' |
| 357 | | - |
| 358 | | - ! Create function node properly |
| 359 | | - allocate(node) |
| 360 | | - node%node_type = AST_FUNCTION_CALL |
| 361 | | - node%function_name = trim(func_name) |
| 362 | | - node%arg_count = 1 |
| 363 | | - allocate(node%arguments(1)) |
| 364 | | - node%arguments(1)%ptr => single_arg |
| 365 | | - else |
| 366 | | - call set_error(parser, 'Expected closing parenthesis') |
| 367 | | - if (associated(single_arg)) call free_ast(single_arg) |
| 368 | | - end if |
| 324 | + ! Parse arguments (single or multiple) |
| 325 | + call parse_function_arguments(parser, func_name, node) |
| 326 | + if (parser%has_error) return |
| 369 | 327 | end if |
| 370 | 328 | else |
| 371 | 329 | ! Variable identifier |
@@ -541,4 +499,109 @@ contains |
| 541 | 499 | end if |
| 542 | 500 | end function parse_matrix_literal |
| 543 | 501 | |
| 502 | + !> Parse function arguments (supports single and multiple arguments) |
| 503 | + subroutine parse_function_arguments(parser, func_name, node) |
| 504 | + type(parser_state_t), intent(inout) :: parser |
| 505 | + character(len=*), intent(in) :: func_name |
| 506 | + type(ast_node_t), pointer, intent(out) :: node |
| 507 | + |
| 508 | + type(ast_node_t), pointer :: arg1, arg2, arg3 |
| 509 | + integer :: arg_count |
| 510 | + |
| 511 | + arg_count = 0 |
| 512 | + nullify(arg1, arg2, arg3) |
| 513 | + |
| 514 | + ! Parse first argument |
| 515 | + call parse_single_argument(parser, arg1) |
| 516 | + if (.not. associated(arg1)) then |
| 517 | + call set_error(parser, 'Invalid function argument') |
| 518 | + return |
| 519 | + end if |
| 520 | + arg_count = 1 |
| 521 | + |
| 522 | + ! Check for more arguments |
| 523 | + if (parser%current_token%token_type == TOKEN_COMMA) then |
| 524 | + call advance(parser) ! Skip comma |
| 525 | + call parse_single_argument(parser, arg2) |
| 526 | + if (.not. associated(arg2)) then |
| 527 | + call set_error(parser, 'Invalid second argument') |
| 528 | + if (associated(arg1)) call free_ast(arg1) |
| 529 | + return |
| 530 | + end if |
| 531 | + arg_count = 2 |
| 532 | + |
| 533 | + ! Check for third argument |
| 534 | + if (parser%current_token%token_type == TOKEN_COMMA) then |
| 535 | + call advance(parser) ! Skip comma |
| 536 | + call parse_single_argument(parser, arg3) |
| 537 | + if (.not. associated(arg3)) then |
| 538 | + call set_error(parser, 'Invalid third argument') |
| 539 | + if (associated(arg1)) call free_ast(arg1) |
| 540 | + if (associated(arg2)) call free_ast(arg2) |
| 541 | + return |
| 542 | + end if |
| 543 | + arg_count = 3 |
| 544 | + end if |
| 545 | + end if |
| 546 | + |
| 547 | + ! Expect closing parenthesis |
| 548 | + if (parser%current_token%token_type /= TOKEN_RPAREN) then |
| 549 | + call set_error(parser, 'Expected closing parenthesis') |
| 550 | + if (associated(arg1)) call free_ast(arg1) |
| 551 | + if (associated(arg2)) call free_ast(arg2) |
| 552 | + if (associated(arg3)) call free_ast(arg3) |
| 553 | + return |
| 554 | + end if |
| 555 | + call advance(parser) ! Skip ')' |
| 556 | + |
| 557 | + ! Create function node with arguments |
| 558 | + allocate(node) |
| 559 | + node%node_type = AST_FUNCTION_CALL |
| 560 | + node%function_name = trim(func_name) |
| 561 | + node%arg_count = arg_count |
| 562 | + allocate(node%arguments(arg_count)) |
| 563 | + |
| 564 | + ! Set arguments |
| 565 | + if (arg_count >= 1) node%arguments(1)%ptr => arg1 |
| 566 | + if (arg_count >= 2) node%arguments(2)%ptr => arg2 |
| 567 | + if (arg_count >= 3) node%arguments(3)%ptr => arg3 |
| 568 | + end subroutine parse_function_arguments |
| 569 | + |
| 570 | + !> Parse a single function argument (number, negative number, or constant) |
| 571 | + subroutine parse_single_argument(parser, arg_node) |
| 572 | + type(parser_state_t), intent(inout) :: parser |
| 573 | + type(ast_node_t), pointer, intent(out) :: arg_node |
| 574 | + |
| 575 | + real(real64) :: num_val |
| 576 | + type(value_t) :: value |
| 577 | + |
| 578 | + if (parser%current_token%token_type == TOKEN_NUMBER) then |
| 579 | + read(parser%current_token%text, *) num_val |
| 580 | + value = create_scalar(num_val) |
| 581 | + arg_node => create_literal_node(value) |
| 582 | + call advance(parser) |
| 583 | + else if (parser%current_token%token_type == TOKEN_OPERATOR .and. & |
| 584 | + parser%current_token%text == '-') then |
| 585 | + ! Handle negative numbers |
| 586 | + call advance(parser) ! Skip minus |
| 587 | + if (parser%current_token%token_type == TOKEN_NUMBER) then |
| 588 | + read(parser%current_token%text, *) num_val |
| 589 | + value = create_scalar(-num_val) ! Make negative |
| 590 | + arg_node => create_literal_node(value) |
| 591 | + call advance(parser) |
| 592 | + else |
| 593 | + call set_error(parser, 'Expected number after minus sign') |
| 594 | + nullify(arg_node) |
| 595 | + return |
| 596 | + end if |
| 597 | + else if (parser%current_token%token_type == TOKEN_IDENTIFIER) then |
| 598 | + ! Handle constants like pi, e |
| 599 | + arg_node => create_identifier_node(parser%current_token%text) |
| 600 | + call advance(parser) |
| 601 | + else |
| 602 | + call set_error(parser, 'Function arguments support numbers and constants') |
| 603 | + nullify(arg_node) |
| 604 | + end if |
| 605 | + end subroutine parse_single_argument |
| 606 | + |
| 544 | 607 | end module fortbite_parser_m |