libidav/davqlparser.c

changeset 115
5744a3dee766
parent 114
943548492a47
child 116
44ffe073b5e3
equal deleted inserted replaced
114:943548492a47 115:5744a3dee766
385 #define _error_missing_par "missing closed parenthesis " _error_context 385 #define _error_missing_par "missing closed parenthesis " _error_context
386 #define _error_invalid_depth "invalid depth " _error_context 386 #define _error_invalid_depth "invalid depth " _error_context
387 #define _error_missing_expr "missing expression " _error_context 387 #define _error_missing_expr "missing expression " _error_context
388 #define _error_invalid_expr "invalid expression " _error_context 388 #define _error_invalid_expr "invalid expression " _error_context
389 #define _error_invalid_unary_op "invalid unary operator " _error_context 389 #define _error_invalid_unary_op "invalid unary operator " _error_context
390 #define _error_invalid_logical_op "invalid logical operator " _error_context
390 #define _error_invalid_fmtspec "invalid format specifier " _error_context 391 #define _error_invalid_fmtspec "invalid format specifier " _error_context
392 #define _error_invalid_string "string expected " _error_context
391 393
392 #define token_sstr(token) (((DavQLToken*)(token)->data)->value) 394 #define token_sstr(token) (((DavQLToken*)(token)->data)->value)
393 395
394 static void dav_error_in_context(int errorcode, const char *errormsg, 396 static void dav_error_in_context(int errorcode, const char *errormsg,
395 DavQLStatement *stmt, UcxList *token) { 397 DavQLStatement *stmt, UcxList *token) {
423 sstr_t keywords[] = {ST("get"), ST("set"), ST("from"), ST("at"), ST("as"), 425 sstr_t keywords[] = {ST("get"), ST("set"), ST("from"), ST("at"), ST("as"),
424 ST("where"), ST("with"), ST("order"), ST("by"), ST("asc"), ST("desc") 426 ST("where"), ST("with"), ST("order"), ST("by"), ST("asc"), ST("desc")
425 }; 427 };
426 for (int i = 0 ; i < sizeof(keywords)/sizeof(sstr_t) ; i++) { 428 for (int i = 0 ; i < sizeof(keywords)/sizeof(sstr_t) ; i++) {
427 if (!sstrcasecmp(token->value, keywords[i])) { 429 if (!sstrcasecmp(token->value, keywords[i])) {
430 return 1;
431 }
432 }
433 return 0;
434 }
435
436 static _Bool islongoperator(DavQLToken *token) {
437 sstr_t operators[] = {ST("and"), ST("or"), ST("not"), ST("xor"),
438 ST("like"), ST("unlike")
439 };
440 for (int i = 0 ; i < sizeof(operators)/sizeof(sstr_t) ; i++) {
441 if (!sstrcasecmp(token->value, operators[i])) {
428 return 1; 442 return 1;
429 } 443 }
430 } 444 }
431 return 0; 445 return 0;
432 } 446 }
451 case '!': token->tokenclass = DAVQL_TOKEN_EXCLAIM; break; 465 case '!': token->tokenclass = DAVQL_TOKEN_EXCLAIM; break;
452 default: 466 default:
453 token->tokenclass = strchr(special_token_symbols, firstchar) ? 467 token->tokenclass = strchr(special_token_symbols, firstchar) ?
454 DAVQL_TOKEN_OPERATOR : DAVQL_TOKEN_IDENTIFIER; 468 DAVQL_TOKEN_OPERATOR : DAVQL_TOKEN_IDENTIFIER;
455 } 469 }
470 } else if (islongoperator(token)) {
471 token->tokenclass = DAVQL_TOKEN_OPERATOR;
456 } else if (firstchar == '\'') { 472 } else if (firstchar == '\'') {
457 token->tokenclass = DAVQL_TOKEN_STRING; 473 token->tokenclass = DAVQL_TOKEN_STRING;
458 } else if (firstchar == '`') { 474 } else if (firstchar == '`') {
459 token->tokenclass = DAVQL_TOKEN_IDENTIFIER; 475 token->tokenclass = DAVQL_TOKEN_IDENTIFIER;
460 } else if (iskeyword(token)) { 476 } else if (iskeyword(token)) {
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;

mercurial