libidav/davqlparser.c

changeset 114
943548492a47
parent 113
412b06dc0162
child 115
5744a3dee766
equal deleted inserted replaced
113:412b06dc0162 114:943548492a47
73 73
74 static const char* _map_operator(davqloperator_t op) { 74 static const char* _map_operator(davqloperator_t op) {
75 // don't use string array, because enum values may change 75 // don't use string array, because enum values may change
76 switch(op) { 76 switch(op) {
77 case DAVQL_NOOP: return "no operator"; 77 case DAVQL_NOOP: return "no operator";
78 case DAVQL_CALL: return "function call"; case DAVQL_ARGLIST: return ",";
78 case DAVQL_ADD: return "+"; case DAVQL_SUB: return "-"; 79 case DAVQL_ADD: return "+"; case DAVQL_SUB: return "-";
79 case DAVQL_MUL: return "*"; case DAVQL_DIV: return "/"; 80 case DAVQL_MUL: return "*"; case DAVQL_DIV: return "/";
80 case DAVQL_AND: return "&"; case DAVQL_OR: return "|"; 81 case DAVQL_AND: return "&"; case DAVQL_OR: return "|";
81 case DAVQL_XOR: return "^"; case DAVQL_NEG: return "~"; 82 case DAVQL_XOR: return "^"; case DAVQL_NEG: return "~";
82 case DAVQL_NOT: return "NOT"; case DAVQL_LAND: return "AND"; 83 case DAVQL_NOT: return "NOT"; case DAVQL_LAND: return "AND";
420 421
421 static _Bool iskeyword(DavQLToken *token) { 422 static _Bool iskeyword(DavQLToken *token) {
422 sstr_t keywords[] = {ST("get"), ST("set"), ST("from"), ST("at"), ST("as"), 423 sstr_t keywords[] = {ST("get"), ST("set"), ST("from"), ST("at"), ST("as"),
423 ST("where"), ST("with"), ST("order"), ST("by"), ST("asc"), ST("desc") 424 ST("where"), ST("with"), ST("order"), ST("by"), ST("asc"), ST("desc")
424 }; 425 };
425 for (int i = 0 ; i < sizeof(keywords)/sizeof(char*) ; i++) { 426 for (int i = 0 ; i < sizeof(keywords)/sizeof(sstr_t) ; i++) {
426 if (!sstrcasecmp(token->value, keywords[i])) { 427 if (!sstrcasecmp(token->value, keywords[i])) {
427 return 1; 428 return 1;
428 } 429 }
429 } 430 }
430 return 0; 431 return 0;
545 546
546 return tokens; 547 return tokens;
547 } 548 }
548 549
549 static void dav_free_expression(DavQLExpression *expr) { 550 static void dav_free_expression(DavQLExpression *expr) {
550 if (expr->left) { 551 if (expr) {
551 dav_free_expression(expr->left); 552 if (expr->left) {
552 } 553 dav_free_expression(expr->left);
553 if (expr->right) { 554 }
554 dav_free_expression(expr->right); 555 if (expr->right) {
555 } 556 dav_free_expression(expr->right);
556 free(expr); 557 }
558 free(expr);
559 }
557 } 560 }
558 561
559 static void dav_free_field(DavQLField *field) { 562 static void dav_free_field(DavQLField *field) {
560 dav_free_expression(field->expr); 563 dav_free_expression(field->expr);
561 free(field); 564 free(field);
590 DavQLExpression left, right; 593 DavQLExpression left, right;
591 594
592 // RULE: LEFT, [Operator, RIGHT] 595 // RULE: LEFT, [Operator, RIGHT]
593 memset(&left, 0, sizeof(DavQLExpression)); 596 memset(&left, 0, sizeof(DavQLExpression));
594 consumed = parseL(stmt, token, &left); 597 consumed = parseL(stmt, token, &left);
595 if (!consumed) { 598 if (!consumed || stmt->errorcode) {
596 return 0; 599 return 0;
597 } 600 }
598 total_consumed += consumed; 601 total_consumed += consumed;
599 token = ucx_list_get(token, consumed); 602 token = ucx_list_get(token, consumed);
600 603
605 expr->type = DAVQL_BINARY; 608 expr->type = DAVQL_BINARY;
606 total_consumed++; 609 total_consumed++;
607 token = token->next; 610 token = token->next;
608 memset(&right, 0, sizeof(DavQLExpression)); 611 memset(&right, 0, sizeof(DavQLExpression));
609 consumed = parseR(stmt, token, &right); 612 consumed = parseR(stmt, token, &right);
613 if (stmt->errorcode) {
614 return 0;
615 }
610 if (!consumed) { 616 if (!consumed) {
611 dav_error_in_context(DAVQL_ERROR_MISSING_EXPR, 617 dav_error_in_context(DAVQL_ERROR_MISSING_EXPR,
612 _error_missing_expr, stmt, token); 618 _error_missing_expr, stmt, token);
613 return 0; 619 return 0;
614 } 620 }
658 } 664 }
659 665
660 return 1; 666 return 1;
661 } 667 }
662 668
663 static int dav_parse_funccall(DavQLStatement* stmt, UcxList* token,
664 DavQLExpression* expr) {
665
666 // TODO: make it so
667 return 0;
668 }
669
670 // forward declaration 669 // forward declaration
671 static int dav_parse_expression(DavQLStatement* stmt, UcxList* token, 670 static int dav_parse_expression(DavQLStatement* stmt, UcxList* token,
672 DavQLExpression* expr); 671 DavQLExpression* expr);
672
673 static int dav_parse_arglist(DavQLStatement* stmt, UcxList* token,
674 DavQLExpression* expr) {
675
676 expr->srctext.ptr = token_sstr(token).ptr;
677 expr->srctext.length = 0;
678 expr->left = expr->right = NULL; // in case we fail, we want them to be sane
679
680 int total_consumed = 0;
681
682 // RULE: Expression, {",", Expression};
683 DavQLExpression *arglist = expr;
684 DavQLExpression arg;
685 char *lastchar = expr->srctext.ptr;
686 int consumed;
687 do {
688 memset(&arg, 0, sizeof(DavQLExpression));
689 consumed = dav_parse_expression(stmt, token, &arg);
690 if (consumed) {
691 lastchar = arg.srctext.ptr + arg.srctext.length;
692 total_consumed += consumed;
693 token = ucx_list_get(token, consumed);
694 // look ahead for a comma
695 if (token_is(token, DAVQL_TOKEN_COMMA)) {
696 total_consumed++;
697 token = token->next;
698 /* we have more arguments, so put the current argument to the
699 * left subtree and create a new node to the right
700 */
701 arglist->left = malloc(sizeof(DavQLExpression));
702 memcpy(arglist->left, &arg, sizeof(DavQLExpression));
703 arglist->srctext.ptr = arg.srctext.ptr;
704 arglist->op = DAVQL_ARGLIST;
705 arglist->type = DAVQL_FUNCCALL;
706 arglist->right = calloc(1, sizeof(DavQLExpression));
707 arglist = arglist->right;
708 } else {
709 // this was the last argument, so write it to the current node
710 memcpy(arglist, &arg, sizeof(DavQLExpression));
711 consumed = 0;
712 }
713 }
714 } while (consumed && !stmt->errorcode);
715
716 // recover source text
717 arglist = expr;
718 while (arglist && arglist->type == DAVQL_FUNCCALL) {
719 arglist->srctext.length = lastchar - arglist->srctext.ptr;
720 arglist = arglist->right;
721 }
722
723 return total_consumed;
724 }
725
726 static int dav_parse_funccall(DavQLStatement* stmt, UcxList* token,
727 DavQLExpression* expr) {
728
729 // RULE: Identifier, "(", ArgumentList, ")";
730 if (token_is(token, DAVQL_TOKEN_IDENTIFIER) &&
731 token_is(token->next, DAVQL_TOKEN_OPENP)) {
732
733 expr->type = DAVQL_FUNCCALL;
734 expr->op = DAVQL_CALL;
735
736 expr->left = calloc(1, sizeof(DavQLExpression));
737 expr->left->type = DAVQL_IDENTIFIER;
738 expr->left->srctext = token_sstr(token);
739 expr->right = NULL;
740
741 token = token->next->next;
742
743 DavQLExpression arg;
744 int argtokens = dav_parse_arglist(stmt, token, &arg);
745 if (stmt->errorcode) {
746 // if an error occurred while parsing the arglist, return now
747 return 2;
748 }
749 if (argtokens) {
750 token = ucx_list_get(token, argtokens);
751 expr->right = malloc(sizeof(DavQLExpression));
752 memcpy(expr->right, &arg, sizeof(DavQLExpression));
753 } else {
754 // arg list may be empty
755 expr->right = NULL;
756 }
757
758 if (token_is(token, DAVQL_TOKEN_CLOSEP)) {
759 return 3 + argtokens;
760 } else {
761 dav_error_in_context(DAVQL_ERROR_MISSING_PAR, _error_missing_par,
762 stmt, token);
763 return 2; // it MUST be a function call, but it is invalid
764 }
765 } else {
766 return 0;
767 }
768 }
673 769
674 static int dav_parse_unary_expr(DavQLStatement* stmt, UcxList* token, 770 static int dav_parse_unary_expr(DavQLStatement* stmt, UcxList* token,
675 DavQLExpression* expr) { 771 DavQLExpression* expr) {
676 772
677 UcxList *firsttoken = token; // save for srctext recovery 773 UcxList *firsttoken = token; // save for srctext recovery
687 switch (*op) { 783 switch (*op) {
688 case '+': expr->op = DAVQL_ADD; break; 784 case '+': expr->op = DAVQL_ADD; break;
689 case '-': expr->op = DAVQL_SUB; break; 785 case '-': expr->op = DAVQL_SUB; break;
690 case '~': expr->op = DAVQL_NEG; break; 786 case '~': expr->op = DAVQL_NEG; break;
691 } 787 }
692 expr->left = calloc(sizeof(DavQLExpression), 1); 788 expr->left = calloc(1, sizeof(DavQLExpression));
693 atom = expr->left; 789 atom = expr->left;
694 total_consumed++; 790 total_consumed++;
695 token = token->next; 791 token = token->next;
696 } else { 792 } else {
697 dav_error_in_context(DAVQL_ERROR_INVALID_UNARY_OP, 793 dav_error_in_context(DAVQL_ERROR_INVALID_UNARY_OP,
738 } 834 }
739 } 835 }
740 836
741 // recover source text 837 // recover source text
742 expr->srctext.ptr = token_sstr(firsttoken).ptr; 838 expr->srctext.ptr = token_sstr(firsttoken).ptr;
743 sstr_t lasttoken = token_sstr(ucx_list_get(firsttoken, total_consumed-1)); 839 if (total_consumed > 0) {
744 expr->srctext.length = lasttoken.ptr - expr->srctext.ptr + lasttoken.length; 840 sstr_t lasttoken =
841 token_sstr(ucx_list_get(firsttoken, total_consumed-1));
842 expr->srctext.length =
843 lasttoken.ptr - expr->srctext.ptr + lasttoken.length;
844 } else {
845 // the expression should not be used anyway, but we want to be safe
846 expr->srctext.length = 0;
847 }
745 848
746 849
747 return total_consumed; 850 return total_consumed;
748 } 851 }
749 852
777 static int dav_parse_named_field(DavQLStatement *stmt, UcxList *token, 880 static int dav_parse_named_field(DavQLStatement *stmt, UcxList *token,
778 DavQLField *field) { 881 DavQLField *field) {
779 int total_consumed = 0, consumed; 882 int total_consumed = 0, consumed;
780 883
781 // RULE: Expression, " as ", Identifier; 884 // RULE: Expression, " as ", Identifier;
782 DavQLExpression * expr = calloc(sizeof(DavQLExpression), 1); 885 DavQLExpression *expr = calloc(1, sizeof(DavQLExpression));
783 consumed = dav_parse_expression(stmt, token, expr); 886 consumed = dav_parse_expression(stmt, token, expr);
887 if (stmt->errorcode) {
888 dav_free_expression(expr);
889 return 0;
890 }
784 if (expr->type == DAVQL_UNDEFINED_TYPE) { 891 if (expr->type == DAVQL_UNDEFINED_TYPE) {
785 dav_free_expression(expr); 892 dav_free_expression(expr);
786 dav_error_in_context(DAVQL_ERROR_INVALID_EXPR, 893 dav_error_in_context(DAVQL_ERROR_INVALID_EXPR,
787 _error_invalid_expr, stmt, token); 894 _error_invalid_expr, stmt, token);
788 return 0; 895 return 0;
792 total_consumed += consumed; 899 total_consumed += consumed;
793 900
794 if (token_is(token, DAVQL_TOKEN_KEYWORD) && tokenvalue_is(token, "as")) { 901 if (token_is(token, DAVQL_TOKEN_KEYWORD) && tokenvalue_is(token, "as")) {
795 token = token->next; total_consumed++; 902 token = token->next; total_consumed++;
796 } else { 903 } else {
797 free(expr); 904 dav_free_expression(expr);
798 dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN, 905 dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
799 _error_missing_as, stmt, token); 906 _error_missing_as, stmt, token);
800 return 0; 907 return 0;
801 } 908 }
802 909
803 if (token_is(token, DAVQL_TOKEN_IDENTIFIER)) { 910 if (token_is(token, DAVQL_TOKEN_IDENTIFIER)) {
804 field->name = token_sstr(token); 911 field->name = token_sstr(token);
805 field->expr = expr; 912 field->expr = expr;
806 return total_consumed + 1; 913 return total_consumed + 1;
807 } else { 914 } else {
808 free(expr); 915 dav_free_expression(expr);
809 dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN, 916 dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
810 _error_missing_identifier, stmt, token); 917 _error_missing_identifier, stmt, token);
811 return 0; 918 return 0;
812 } 919 }
813 } 920 }
815 static int dav_parse_fieldlist(DavQLStatement *stmt, UcxList *token) { 922 static int dav_parse_fieldlist(DavQLStatement *stmt, UcxList *token) {
816 923
817 // RULE: "-" 924 // RULE: "-"
818 if (token_is(token, DAVQL_TOKEN_OPERATOR) && tokenvalue_is(token, "-")) { 925 if (token_is(token, DAVQL_TOKEN_OPERATOR) && tokenvalue_is(token, "-")) {
819 DavQLField *field = malloc(sizeof(DavQLField)); 926 DavQLField *field = malloc(sizeof(DavQLField));
820 field->expr = calloc(sizeof(DavQLExpression), 1); 927 field->expr = calloc(1, sizeof(DavQLExpression));
821 field->expr->type = DAVQL_IDENTIFIER; 928 field->expr->type = DAVQL_IDENTIFIER;
822 field->expr->srctext = field->name = token_sstr(token); 929 field->expr->srctext = field->name = token_sstr(token);
823 stmt->fields = ucx_list_append(stmt->fields, field); 930 stmt->fields = ucx_list_append(stmt->fields, field);
824 return 1; 931 return 1;
825 } 932 }
826 933
827 // RULE: "*", {",", NamedExpression} 934 // RULE: "*", {",", NamedExpression}
828 if (token_is(token, DAVQL_TOKEN_OPERATOR) && tokenvalue_is(token, "*")) { 935 if (token_is(token, DAVQL_TOKEN_OPERATOR) && tokenvalue_is(token, "*")) {
829 DavQLField *field = malloc(sizeof(DavQLField)); 936 DavQLField *field = malloc(sizeof(DavQLField));
830 field->expr = calloc(sizeof(DavQLExpression), 1); 937 field->expr = calloc(1, sizeof(DavQLExpression));
831 field->expr->type = DAVQL_IDENTIFIER; 938 field->expr->type = DAVQL_IDENTIFIER;
832 field->expr->srctext = field->name = token_sstr(token); 939 field->expr->srctext = field->name = token_sstr(token);
833 stmt->fields = ucx_list_append(stmt->fields, field); 940 stmt->fields = ucx_list_append(stmt->fields, field);
834 941
835 int total_consumed = 0; 942 int total_consumed = 0;
873 // look ahead, if the field is JUST the identifier 980 // look ahead, if the field is JUST the identifier
874 && (token_is(token->next, DAVQL_TOKEN_COMMA) || 981 && (token_is(token->next, DAVQL_TOKEN_COMMA) ||
875 tokenvalue_is(token->next, "from"))) { 982 tokenvalue_is(token->next, "from"))) {
876 983
877 DavQLField *field = malloc(sizeof(DavQLField)); 984 DavQLField *field = malloc(sizeof(DavQLField));
878 field->expr = calloc(sizeof(DavQLExpression), 1); 985 field->expr = calloc(1, sizeof(DavQLExpression));
879 field->expr->type = DAVQL_IDENTIFIER; 986 field->expr->type = DAVQL_IDENTIFIER;
880 field->expr->srctext = field->name = token_sstr(token); 987 field->expr->srctext = field->name = token_sstr(token);
881 stmt->fields = ucx_list_append(stmt->fields, field); 988 stmt->fields = ucx_list_append(stmt->fields, field);
882 989
883 consumed = 1; 990 consumed = 1;
924 token = token->next; total_consumed++; 1031 token = token->next; total_consumed++;
925 if (tokenvalue_is(token, "infinity")) { 1032 if (tokenvalue_is(token, "infinity")) {
926 stmt->depth = DAV_DEPTH_INFINITY; 1033 stmt->depth = DAV_DEPTH_INFINITY;
927 token = token->next; total_consumed++; 1034 token = token->next; total_consumed++;
928 } else { 1035 } else {
929 DavQLExpression *depthexpr = calloc(sizeof(DavQLExpression), 1); 1036 DavQLExpression *depthexpr = calloc(1, sizeof(DavQLExpression));
930 1037
931 int consumed = dav_parse_expression(stmt, token, depthexpr); 1038 int consumed = dav_parse_expression(stmt, token, depthexpr);
932 1039
933 if (consumed) { 1040 if (consumed) {
934 if (depthexpr->type == DAVQL_NUMBER) { 1041 if (depthexpr->type == DAVQL_NUMBER) {

mercurial