libidav/davqlparser.c

changeset 83
7d20ce5d235b
parent 82
0567444f2d76
child 85
0ab1cf261a44
equal deleted inserted replaced
82:0567444f2d76 83:7d20ce5d235b
59 } 59 }
60 60
61 static const char* _map_operator(davqloperator_t op) { 61 static const char* _map_operator(davqloperator_t op) {
62 // don't use string array, because enum values may change 62 // don't use string array, because enum values may change
63 switch(op) { 63 switch(op) {
64 case ADD: return "+"; case SUB: return "-"; case MUL: return "*"; 64 case DAVQL_NOOP: return "no operator";
65 case DIV: return "/"; case AND: return "&"; case OR: return "|"; 65 case DAVQL_ADD: return "+"; case DAVQL_SUB: return "-";
66 case XOR: return "^"; case NEG: return "~"; case NOT: return "NOT"; 66 case DAVQL_MUL: return "*"; case DAVQL_DIV: return "/";
67 case LAND: return "AND"; case LOR: return "OR"; case LXOR: return "XOR"; 67 case DAVQL_AND: return "&"; case DAVQL_OR: return "|";
68 case EQ: return "="; case NEQ: return "!="; case LT: return "<"; 68 case DAVQL_XOR: return "^"; case DAVQL_NEG: return "~";
69 case GT: return ">"; case LE: return "<="; case GE: return ">="; 69 case DAVQL_NOT: return "NOT"; case DAVQL_LAND: return "AND";
70 case LIKE: return "LIKE"; case UNLIKE: return "UNLIKE"; 70 case DAVQL_LOR: return "OR"; case DAVQL_LXOR: return "XOR";
71 case DAVQL_EQ: return "="; case DAVQL_NEQ: return "!=";
72 case DAVQL_LT: return "<"; case DAVQL_GT: return ">";
73 case DAVQL_LE: return "<="; case DAVQL_GE: return ">=";
74 case DAVQL_LIKE: return "LIKE"; case DAVQL_UNLIKE: return "UNLIKE";
71 default: return "unknown"; 75 default: return "unknown";
72 } 76 }
73 } 77 }
74 78
75 static void dav_debug_ql_stmt_print(DavQLStatement *stmt) { 79 static void dav_debug_ql_stmt_print(DavQLStatement *stmt) {
84 // Has wildcard 88 // Has wildcard
85 _Bool wildcard = 0; 89 _Bool wildcard = 0;
86 UCX_FOREACH(elm, stmt->fields) { 90 UCX_FOREACH(elm, stmt->fields) {
87 DavQLExpression* expr = (DavQLExpression*)elm->data; 91 DavQLExpression* expr = (DavQLExpression*)elm->data;
88 if (expr->type == DAVQL_IDENTIFIER && 92 if (expr->type == DAVQL_IDENTIFIER &&
89 expr->srctext.length == 1 && *(expr->srctext.ptr) == '*') { 93 expr->srctext.length == 1 && expr->srctext.ptr[0] == '*') {
90 wildcard = 1; 94 wildcard = 1;
91 } 95 }
92 } 96 }
93 printf(" %s wildcard\nPath: %.*s\nHas where clause: %s\n", 97 printf(" %s wildcard\nPath: %.*s\nHas where clause: %s\n",
94 wildcard?"with":"without", 98 wildcard?"with":"without",
263 267
264 if (token) { 268 if (token) {
265 tokens = ucx_list_append(tokens, token); 269 tokens = ucx_list_append(tokens, token);
266 } 270 }
267 271
272 // now find quotes and backsticks and merge enclosed tokens
273 // TODO: make it so or disable tokenization in such cases in above code
274
268 return tokens; 275 return tokens;
269 } 276 }
270 277
271 static DavQLExpression* dav_parse_expression(sstr_t src) { 278 #define token_sstr(listelem) ((sstr_t*)(listelem)->data)
279 static DavQLExpression* dav_parse_expression(UcxList* starttoken, size_t n) {
280 if (n == 0) {
281 return NULL;
282 }
283
272 DavQLExpression *expr = calloc(1, sizeof(DavQLExpression)); 284 DavQLExpression *expr = calloc(1, sizeof(DavQLExpression));
273 expr->srctext = src; 285
286 // set pointer for source text
287 expr->srctext.ptr = token_sstr(starttoken)->ptr;
288
289 // special case - only one token
290 if (n == 1) {
291 expr->srctext.length = token_sstr(starttoken)->length;
292 char firstchar = expr->srctext.ptr[0];
293 if (firstchar == '\'' || isdigit(firstchar)) {
294 expr->type = DAVQL_LITERAL;
295 } else {
296 expr->type = DAVQL_IDENTIFIER;
297 }
298 } else {
299 UcxList* token = starttoken;
300
301 // check, if first token is (
302 // if so, verify that last token is ) and throw both away
303 if (!sstrcmp(*token_sstr(token), S("("))) {
304 if (!sstrcmp(*token_sstr(ucx_list_get(token, n-1)), S(")"))) {
305 token = token->next;
306 n -= 2;
307 } else {
308 // TODO: throw syntax error
309 }
310 }
311
312 // process tokens
313 for (size_t i = 0 ; i < n ; i++) {
314
315 // TODO: make it so
316
317 // go to next token (if this is not the last token)
318 if (i < n-1) {
319 token = token->next;
320 }
321 }
322
323 // compute length of source text (including delimiters)
324 expr->srctext.length = token_sstr(token)->ptr +
325 token_sstr(token)->length - expr->srctext.ptr;
326 }
274 327
275 return expr; 328 return expr;
276 } 329 }
277 330
278 static void dav_parse_get_statement(DavQLStatement *stmt, UcxList *tokens) { 331 static void dav_parse_get_statement(DavQLStatement *stmt, UcxList *tokens) {
288 * 500: ready to quit 341 * 500: ready to quit
289 * 342 *
290 */ 343 */
291 int step = 10; 344 int step = 10;
292 345
346 // Variables for token sublists for expressions
347 UcxList *exprstart = NULL;
348 size_t exprlen = 0;
349
350 // Process tokens
293 UCX_FOREACH(token, tokens) { 351 UCX_FOREACH(token, tokens) {
294 sstr_t tokendata = *(sstr_t*)token->data; 352 sstr_t tokendata = *token_sstr(token);
295 353
296 switch (step) { 354 switch (step) {
297 // optional clauses 355 // optional clauses
298 case 520: 356 case 520:
299 if (!sstrcasecmp(tokendata, S("where"))) { 357 if (!sstrcasecmp(tokendata, S("where"))) {
304 if (!sstrcasecmp(tokendata, S("with"))) { 362 if (!sstrcasecmp(tokendata, S("with"))) {
305 step = 40; 363 step = 40;
306 } 364 }
307 break; 365 break;
308 // field list 366 // field list
309 case 10: 367 case 10: {
310 if (!sstrcasecmp(tokendata, S("from"))) { 368 _Bool fromkeyword = !sstrcasecmp(tokendata, S("from"));
311 step = 20; 369 if (fromkeyword || !sstrcmp(tokendata, S(","))) {
370 if (exprstart) {
371 stmt->fields = ucx_list_append(stmt->fields,
372 dav_parse_expression(exprstart, exprlen));
373 exprstart = NULL;
374 exprlen = 0;
375 } else {
376 // TODO: throw syntax error
377 }
378
379 if (fromkeyword) {
380 step = 20;
381 }
312 } else { 382 } else {
313 stmt->fields = ucx_list_append(stmt->fields, 383 // collect tokens for field expression
314 dav_parse_expression(tokendata)); 384 if (exprstart) {
315 } 385 exprlen++;
316 break; 386 } else {
387 exprstart = token;
388 exprlen = 1;
389 }
390 }
391 break;
392 }
317 // from clause 393 // from clause
318 case 20: 394 case 20:
319 stmt->path = dav_parse_expression(tokendata); 395 stmt->path = dav_parse_expression(token, 1);
320 step = 520; 396 step = 520;
321 break; 397 break;
322 // where clause 398 // where clause
323 case 30: 399 case 30:
324 step = 530; 400 step = 530;
326 // with clause 402 // with clause
327 case 40: 403 case 40:
328 step = 500; 404 step = 500;
329 break; 405 break;
330 } 406 }
331
332 free(token->data);
333 } 407 }
334 408
335 if (step < 500) { 409 if (step < 500) {
336 stmt->type = DAVQL_ERROR; 410 stmt->type = DAVQL_ERROR;
337 // TODO: save parse error message 411 // TODO: save parse error message
340 414
341 static void dav_parse_set_statement(DavQLStatement *stmt, UcxList *tokens) { 415 static void dav_parse_set_statement(DavQLStatement *stmt, UcxList *tokens) {
342 stmt->type = DAVQL_SET; 416 stmt->type = DAVQL_SET;
343 417
344 UCX_FOREACH(token, tokens) { 418 UCX_FOREACH(token, tokens) {
345 sstr_t tokendata = *(sstr_t*)token->data; 419 sstr_t tokendata = *token_sstr(token);
346 420
347 // just free the tokens, until the function is implemented
348
349 free(token->data);
350 } 421 }
351 } 422 }
352 423
353 DavQLStatement* dav_parse_statement(sstr_t srctext) { 424 DavQLStatement* dav_parse_statement(sstr_t srctext) {
354 DavQLStatement *stmt = calloc(1, sizeof(DavQLStatement)); 425 DavQLStatement *stmt = calloc(1, sizeof(DavQLStatement));
361 stmt->srctext = sstrtrim(srctext); 432 stmt->srctext = sstrtrim(srctext);
362 433
363 // tokenization 434 // tokenization
364 UcxList* tokens = dav_parse_tokenize(stmt->srctext); 435 UcxList* tokens = dav_parse_tokenize(stmt->srctext);
365 436
366 // use first token to determine query type
367 if (tokens) { 437 if (tokens) {
368 sstr_t token = *(sstr_t*)tokens->data; 438 // use first token to determine query type
439 sstr_t token = *token_sstr(tokens);
369 free(tokens->data); 440 free(tokens->data);
370 tokens = ucx_list_remove(tokens, tokens); 441 tokens = ucx_list_remove(tokens, tokens);
442
371 if (!sstrcasecmp(token, S("get"))) { 443 if (!sstrcasecmp(token, S("get"))) {
372 dav_parse_get_statement(stmt, tokens); 444 dav_parse_get_statement(stmt, tokens);
373 } else if (!sstrcasecmp(token, S("set"))) { 445 } else if (!sstrcasecmp(token, S("set"))) {
374 dav_parse_set_statement(stmt, tokens); 446 dav_parse_set_statement(stmt, tokens);
375 } else { 447 } else {
376 stmt->type = DAVQL_ERROR; 448 stmt->type = DAVQL_ERROR;
377 } 449 }
450
451 // free token data
452 UCX_FOREACH(token, tokens) {
453 free(token->data);
454 }
378 ucx_list_free(tokens); 455 ucx_list_free(tokens);
379 } else { 456 } else {
380 stmt->type = DAVQL_ERROR; 457 stmt->type = DAVQL_ERROR;
381 } 458 }
382 459

mercurial