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; |
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 |
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 |
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; |