1014 |
1030 |
1015 return total_consumed; |
1031 return total_consumed; |
1016 } |
1032 } |
1017 } |
1033 } |
1018 |
1034 |
|
1035 // forward declaration |
|
1036 static int dav_parse_logical_expr(DavQLStatement *stmt, UcxList *token, |
|
1037 DavQLExpression *expr); |
|
1038 |
|
1039 static int dav_parse_bool_prim(DavQLStatement *stmt, UcxList *token, |
|
1040 DavQLExpression *expr) { |
|
1041 |
|
1042 expr->type = DAVQL_LOGICAL; |
|
1043 |
|
1044 int total_consumed = 0; |
|
1045 |
|
1046 DavQLExpression bexpr; |
|
1047 memset(&bexpr, 0, sizeof(DavQLExpression)); |
|
1048 total_consumed = dav_parse_expression(stmt, token, &bexpr); |
|
1049 if (!total_consumed || stmt->errorcode) { |
|
1050 return 0; |
|
1051 } |
|
1052 token = ucx_list_get(token, total_consumed); |
|
1053 |
|
1054 UcxList* optok = token; |
|
1055 // RULE: Expression, (" like " | " unlike "), String |
|
1056 if (token_is(optok, DAVQL_TOKEN_OPERATOR) && (tokenvalue_is(optok, |
|
1057 "like") || tokenvalue_is(optok, "unlike"))) { |
|
1058 |
|
1059 total_consumed++; |
|
1060 token = token->next; |
|
1061 if (token_is(token, DAVQL_TOKEN_STRING)) { |
|
1062 expr->op = tokenvalue_is(optok, "like") ? |
|
1063 DAVQL_LIKE : DAVQL_UNLIKE; |
|
1064 expr->left = malloc(sizeof(DavQLExpression)); |
|
1065 memcpy(expr->left, &bexpr, sizeof(DavQLExpression)); |
|
1066 expr->right = calloc(1, sizeof(DavQLExpression)); |
|
1067 expr->right->type = DAVQL_STRING; |
|
1068 expr->right->srctext = token_sstr(token); |
|
1069 |
|
1070 return total_consumed + 1; |
|
1071 } else { |
|
1072 dav_error_in_context(DAVQL_ERROR_INVALID_STRING, |
|
1073 _error_invalid_string, stmt, token); |
|
1074 return 0; |
|
1075 } |
|
1076 } |
|
1077 // RULE: Expression, Comparison, Expression |
|
1078 else if (token_is(optok, DAVQL_TOKEN_OPERATOR) && ( |
|
1079 tokenvalue_is(optok, "=") || tokenvalue_is(optok, "!") || |
|
1080 tokenvalue_is(optok, "<") || tokenvalue_is(optok, ">"))) { |
|
1081 |
|
1082 total_consumed++; |
|
1083 token = token->next; |
|
1084 |
|
1085 if (tokenvalue_is(optok, "=")) { |
|
1086 expr->op = DAVQL_EQ; |
|
1087 } else { |
|
1088 if (tokenvalue_is(token, "=")) { |
|
1089 if (tokenvalue_is(optok, "!")) { |
|
1090 expr->type = DAVQL_NEQ; |
|
1091 } else if (tokenvalue_is(optok, "<")) { |
|
1092 expr->type = DAVQL_LE; |
|
1093 } else if (tokenvalue_is(optok, ">")) { |
|
1094 expr->type = DAVQL_GE; |
|
1095 } |
|
1096 total_consumed++; |
|
1097 token = token->next; |
|
1098 } else { |
|
1099 if (tokenvalue_is(optok, "<")) { |
|
1100 expr->type = DAVQL_LT; |
|
1101 } else if (tokenvalue_is(optok, ">")) { |
|
1102 expr->type = DAVQL_GT; |
|
1103 } |
|
1104 } |
|
1105 } |
|
1106 |
|
1107 int consumed = dav_parse_expression(stmt, token, expr->right); |
|
1108 if (stmt->errorcode) { |
|
1109 return 0; |
|
1110 } |
|
1111 if (!consumed) { |
|
1112 dav_error_in_context( |
|
1113 DAVQL_ERROR_MISSING_EXPR, _error_missing_expr, |
|
1114 stmt, token); |
|
1115 return 0; |
|
1116 } |
|
1117 |
|
1118 total_consumed += consumed; |
|
1119 expr->left = malloc(sizeof(DavQLExpression)); |
|
1120 memcpy(expr->left, &bexpr, sizeof(DavQLExpression)); |
|
1121 |
|
1122 return total_consumed; |
|
1123 } |
|
1124 // RULE: FunctionCall | Identifier; |
|
1125 else if (bexpr.type == DAVQL_FUNCCALL || bexpr.type == DAVQL_IDENTIFIER) { |
|
1126 memcpy(expr, &bexpr, sizeof(DavQLExpression)); |
|
1127 |
|
1128 return total_consumed; |
|
1129 } else { |
|
1130 return 0; |
|
1131 } |
|
1132 } |
|
1133 |
|
1134 static int dav_parse_bool_expr(DavQLStatement *stmt, UcxList *token, |
|
1135 DavQLExpression *expr) { |
|
1136 |
|
1137 // RULE: "not ", LogicalExpression |
|
1138 if (token_is(token, DAVQL_TOKEN_OPERATOR) && tokenvalue_is(token, "not")) { |
|
1139 token = token->next; |
|
1140 expr->type = DAVQL_LOGICAL; |
|
1141 expr->op = DAVQL_NOT; |
|
1142 expr->left = calloc(1, sizeof(DavQLExpression)); |
|
1143 expr->srctext = token_sstr(token); |
|
1144 |
|
1145 int consumed = dav_parse_logical_expr(stmt, token, expr->left); |
|
1146 if (stmt->errorcode) { |
|
1147 return 0; |
|
1148 } |
|
1149 if (consumed) { |
|
1150 sstr_t lasttok = token_sstr(ucx_list_get(token, consumed-1)); |
|
1151 expr->srctext.length = |
|
1152 lasttok.ptr - expr->srctext.ptr + lasttok.length; |
|
1153 return consumed + 1; |
|
1154 } else { |
|
1155 dav_error_in_context(DAVQL_ERROR_MISSING_EXPR, |
|
1156 _error_missing_expr, stmt, token); |
|
1157 return 0; |
|
1158 } |
|
1159 } |
|
1160 // RULE: "(", LogicalExpression, ")" |
|
1161 else if (token_is(token, DAVQL_TOKEN_OPENP)) { |
|
1162 token = token->next; |
|
1163 |
|
1164 int consumed = dav_parse_logical_expr(stmt, token, expr); |
|
1165 if (stmt->errorcode) { |
|
1166 return 0; |
|
1167 } |
|
1168 if (!consumed) { |
|
1169 dav_error_in_context(DAVQL_ERROR_MISSING_EXPR, |
|
1170 _error_missing_expr, stmt, token); |
|
1171 return 0; |
|
1172 } |
|
1173 |
|
1174 token = ucx_list_get(token, consumed); |
|
1175 |
|
1176 if (token_is(token, DAVQL_TOKEN_CLOSEP)) { |
|
1177 token = token->next; |
|
1178 return consumed + 2; |
|
1179 } else { |
|
1180 dav_error_in_context(DAVQL_ERROR_MISSING_PAR, _error_missing_par, |
|
1181 stmt, token); |
|
1182 return 0; |
|
1183 } |
|
1184 } |
|
1185 // RULE: BooleanExpression |
|
1186 else { |
|
1187 return dav_parse_bool_prim(stmt, token, expr); |
|
1188 } |
|
1189 } |
|
1190 |
|
1191 static int dav_parse_logical_expr(DavQLStatement *stmt, UcxList *token, |
|
1192 DavQLExpression *expr) { |
|
1193 |
|
1194 UcxList *firsttoken = token; |
|
1195 int total_consumed = 0; |
|
1196 |
|
1197 // RULE: BooleanLiteral, [LogicalOperator, LogicalExpression]; |
|
1198 DavQLExpression left, right; |
|
1199 memset(&left, 0, sizeof(DavQLExpression)); |
|
1200 int consumed = dav_parse_bool_expr(stmt, token, &left); |
|
1201 if (stmt->errorcode) { |
|
1202 return 0; |
|
1203 } |
|
1204 if (!consumed) { |
|
1205 dav_error_in_context(DAVQL_ERROR_MISSING_EXPR, |
|
1206 _error_missing_expr, stmt, token); |
|
1207 return 0; |
|
1208 } |
|
1209 total_consumed += consumed; |
|
1210 token = ucx_list_get(token, consumed); |
|
1211 |
|
1212 if (token_is(token, DAVQL_TOKEN_OPERATOR)) { |
|
1213 |
|
1214 davqloperator_t op = DAVQL_NOOP; |
|
1215 if (tokenvalue_is(token, "and")) { |
|
1216 op = DAVQL_LAND; |
|
1217 } else if (tokenvalue_is(token, "or")) { |
|
1218 op = DAVQL_LOR; |
|
1219 } else if (tokenvalue_is(token, "xor")) { |
|
1220 op = DAVQL_LXOR; |
|
1221 } |
|
1222 |
|
1223 if (op == DAVQL_NOOP) { |
|
1224 dav_error_in_context(DAVQL_ERROR_INVALID_LOGICAL_OP, |
|
1225 _error_invalid_logical_op, stmt, token); |
|
1226 return 0; |
|
1227 } else { |
|
1228 expr->op = op; |
|
1229 total_consumed++; |
|
1230 token = token->next; |
|
1231 |
|
1232 memset(&right, 0, sizeof(DavQLExpression)); |
|
1233 consumed = dav_parse_logical_expr(stmt, token, &right); |
|
1234 if (stmt->errorcode) { |
|
1235 return 0; |
|
1236 } |
|
1237 if (!consumed) { |
|
1238 dav_error_in_context(DAVQL_ERROR_MISSING_EXPR, |
|
1239 _error_missing_expr, stmt, token); |
|
1240 return 0; |
|
1241 } |
|
1242 total_consumed += consumed; |
|
1243 token = ucx_list_get(token, consumed); |
|
1244 |
|
1245 expr->left = malloc(sizeof(DavQLExpression)); |
|
1246 memcpy(expr->left, &left, sizeof(DavQLExpression)); |
|
1247 expr->right = malloc(sizeof(DavQLExpression)); |
|
1248 memcpy(expr->right, &right, sizeof(DavQLExpression)); |
|
1249 } |
|
1250 } else { |
|
1251 memcpy(expr, &left, sizeof(DavQLExpression)); |
|
1252 } |
|
1253 |
|
1254 // set type and recover source text |
|
1255 if (total_consumed > 0) { |
|
1256 expr->type = DAVQL_LOGICAL; |
|
1257 |
|
1258 expr->srctext.ptr = token_sstr(firsttoken).ptr; |
|
1259 sstr_t lasttok = token_sstr(ucx_list_get(firsttoken, total_consumed-1)); |
|
1260 expr->srctext.length = lasttok.ptr-expr->srctext.ptr+lasttok.length; |
|
1261 } |
|
1262 |
|
1263 return total_consumed; |
|
1264 } |
|
1265 |
1019 static int dav_parse_where_clause(DavQLStatement *stmt, UcxList *token) { |
1266 static int dav_parse_where_clause(DavQLStatement *stmt, UcxList *token) { |
1020 return 0; |
1267 stmt->where = calloc(1, sizeof(DavQLExpression)); |
|
1268 |
|
1269 return dav_parse_logical_expr(stmt, token, stmt->where); |
1021 } |
1270 } |
1022 |
1271 |
1023 static int dav_parse_with_clause(DavQLStatement *stmt, UcxList *token) { |
1272 static int dav_parse_with_clause(DavQLStatement *stmt, UcxList *token) { |
1024 |
1273 |
1025 int total_consumed = 0; |
1274 int total_consumed = 0; |