libidav/davqlparser.c

changeset 99
579238097973
parent 98
237844f263b4
child 102
e9ae1318a559
equal deleted inserted replaced
98:237844f263b4 99:579238097973
506 // process tokens 506 // process tokens
507 for (size_t i = 0 ; i < n ; i++) { 507 for (size_t i = 0 ; i < n ; i++) {
508 sstr_t tokendata = *token_sstr(token); 508 sstr_t tokendata = *token_sstr(token);
509 509
510 // TODO: make it so 510 // TODO: make it so
511 printf("Processing %.*s...\n", sfmtarg(tokendata));
512 511
513 // go to next token (if this is not the last token) 512 // go to next token (if this is not the last token)
514 if (i < n-1) { 513 if (i < n-1) {
515 token = token->next; 514 token = token->next;
516 } 515 }
542 #define _step_ORDER_BY_ 50 // ORDER BY clause 541 #define _step_ORDER_BY_ 50 // ORDER BY clause
543 #define _step_end_ 500 // expect end 542 #define _step_end_ 500 // expect end
544 543
545 struct fieldlist_parser_state { 544 struct fieldlist_parser_state {
546 UcxList *expr_firsttoken; 545 UcxList *expr_firsttoken;
546 DavQLField *currentfield;
547 size_t expr_len; 547 size_t expr_len;
548 /* 548 /*
549 * 0: begin of field list - may encounter "*" or "-" special fields 549 * 0: begin of field list - may encounter "*" or "-" special fields
550 * 1: collect expression token 550 * 1: collect expression token
551 * switch to step 2 on keyword "as" 551 * switch to step 2 on keyword "as"
552 * expect "," only if expr_len is 1 (add expr to list and continue) 552 * expect "," or "from" only if expr_len is 1 (add to list and continue)
553 * 2: expect one token (identifier) and a "," - continue with step 1 553 * 2: expect one token (identifier) for as clause
554 * 3: expect a ",": continue with step 1
555 * or a "from": leave field list parser
556 * 4: expect end of field list (i.e. a "from" keyword)
554 */ 557 */
555 int step; 558 int step;
556 }; 559 };
557 560
561 static void dav_free_field(DavQLField *field) {
562 dav_free_expression(field->expr);
563 free(field);
564 }
565
558 static int dav_parse_fieldlist(DavQLStatement *stmt, UcxList *token, 566 static int dav_parse_fieldlist(DavQLStatement *stmt, UcxList *token,
559 struct fieldlist_parser_state *state) { 567 struct fieldlist_parser_state *state) {
560 sstr_t tokendata = *token_sstr(token); 568 sstr_t tokendata = *token_sstr(token);
569
570 _Bool fromkeyword = !sstrcasecmp(tokendata, S("from"));
571 _Bool comma = !sstrcmp(tokendata, S(","));
561 572
562 switch (state->step) { 573 switch (state->step) {
563 case 0: 574 case 0:
575 if (!sstrcmp(tokendata, S("*")) || !sstrcmp(tokendata, S("-"))) {
576 DavQLField *field = malloc(sizeof(DavQLField));
577 field->name = tokendata;
578 field->expr = calloc(1, sizeof(DavQLExpression));
579 field->expr->type = DAVQL_IDENTIFIER;
580 field->expr->srctext = tokendata;
581 stmt->fields = ucx_list_append(stmt->fields, field);
582
583 if (tokendata.ptr[0] == '-') {
584 // no further fields may follow, if dash symbol has been found
585 state->step = 4;
586 } else {
587 state->step = 3;
588 }
589 return _step_fieldlist_;
590 }
564 // did not encounter special field, fall through to step 1 591 // did not encounter special field, fall through to step 1
592 state->step = 1;
565 case 1: 593 case 1:
566 break; 594 if (fromkeyword || comma) {
567 } 595 // add possible identifier to list
568 596 if (state->expr_firsttoken) {
569 _Bool fromkeyword = !sstrcasecmp(tokendata, S("from")); 597 // TODO: skip comma in function call)
570 if (fromkeyword || !sstrcmp(tokendata, S(","))) { 598 if (state->expr_len > 1) {
571 if (state->expr_firsttoken) { 599 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN;
572 DavQLField *field = malloc(sizeof(DavQLField)); 600 stmt->errormessage = ucx_sprintf(_expected_token,
573 field->expr = dav_parse_expression( 601 "AS", sfmtarg(tokendata)).ptr;
602 return 0;
603 }
604
605 DavQLExpression *expr = dav_parse_expression(
606 stmt, state->expr_firsttoken, state->expr_len);
607
608 if (expr->type != DAVQL_IDENTIFIER) {
609 dav_free_expression(expr);
610 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN;
611 stmt->errormessage = ucx_sprintf(_expected_token,
612 "AS", sfmtarg(tokendata)).ptr;
613 return 0;
614 } // TODO: do not allow identifier when wildcard is present
615
616 DavQLField *field = malloc(sizeof(DavQLField));
617 field->expr = expr;
618 field->name = field->expr->srctext;
619 stmt->fields = ucx_list_append(stmt->fields, field);
620
621 state->expr_firsttoken = NULL;
622 state->expr_len = 0;
623
624 if (fromkeyword) {
625 return _step_FROM_;
626 }
627 } else {
628 dav_error_in_context(DAVQL_ERROR_UNEXPECTED_TOKEN,
629 _unexpected_token, stmt, token);
630 return 0;
631 }
632 } else if (!sstrcasecmp(tokendata, S("as"))) {
633 // TODO: return error, if expr_first_token is NULL
634 state->currentfield = malloc(sizeof(DavQLField));
635 state->currentfield->expr = dav_parse_expression(
574 stmt, state->expr_firsttoken, state->expr_len); 636 stmt, state->expr_firsttoken, state->expr_len);
575 field->name = field->expr->srctext; 637
576 stmt->fields = ucx_list_append(stmt->fields, field);
577 state->expr_firsttoken = NULL; 638 state->expr_firsttoken = NULL;
578 state->expr_len = 0; 639 state->expr_len = 0;
579 640
580 if (fromkeyword) { 641 state->step = 2;
581 return _step_FROM_; 642 } else {
582 } 643 // collect tokens for field expression
644 if (state->expr_firsttoken) {
645 state->expr_len++;
646 } else {
647 state->expr_firsttoken = token;
648 state->expr_len = 1;
649 }
650 }
651
652 return _step_fieldlist_;
653 case 2: {
654 DavQLExpression *expr = dav_parse_expression(stmt, token, 1);
655 if (expr->type == DAVQL_IDENTIFIER) {
656 state->currentfield->name = expr->srctext;
657 stmt->fields = ucx_list_append(stmt->fields, state->currentfield);
658 state->currentfield = NULL;
659 } else {
660 dav_free_field(state->currentfield);
661 dav_error_in_context(DAVQL_ERROR_IDENTIFIER_EXPECTED,
662 _identifier_expected, stmt, token);
663
664 }
665 dav_free_expression(expr);
666 state->step = 3;
667
668 return _step_fieldlist_;
669 }
670 case 3:
671 if (fromkeyword) {
672 return _step_FROM_;
673 } else if (comma) {
674 state->step = 1;
675 return _step_fieldlist_;
583 } else { 676 } else {
584 dav_error_in_context(DAVQL_ERROR_UNEXPECTED_TOKEN, 677 dav_error_in_context(DAVQL_ERROR_UNEXPECTED_TOKEN,
585 _unexpected_token, stmt, token); 678 _unexpected_token, stmt, token);
586 } 679 return 0;
587 } else { 680 }
588 // collect tokens for field expression 681 case 4:
589 if (state->expr_firsttoken) { 682 if (fromkeyword) {
590 state->expr_len++; 683 return _step_FROM_;
591 } else { 684 } else {
592 state->expr_firsttoken = token; 685 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN;
593 state->expr_len = 1; 686 stmt->errormessage = ucx_sprintf(_expected_token,
594 } 687 "FROM", sfmtarg(tokendata)).ptr;
595 } 688 return 0;
596 689 }
597 return _step_fieldlist_; 690 }
598 }
599
600 static void dav_free_field(DavQLField *field) {
601 dav_free_expression(field->expr);
602 free(field);
603 } 691 }
604 692
605 static int dav_parse_from(DavQLStatement *stmt, UcxList *token) { 693 static int dav_parse_from(DavQLStatement *stmt, UcxList *token) {
606 sstr_t tokendata = *token_sstr(token); 694 sstr_t tokendata = *token_sstr(token);
607 695

mercurial