243 // ------------------------------------------------------------------------ |
243 // ------------------------------------------------------------------------ |
244 |
244 |
245 #define _unexpected_end_msg "unexpected end of statement" |
245 #define _unexpected_end_msg "unexpected end of statement" |
246 #define _invalid_msg "invalid statement" |
246 #define _invalid_msg "invalid statement" |
247 #define _unexpected_token "unexpected token (%.*s [->]%.*s %.*s)" |
247 #define _unexpected_token "unexpected token (%.*s [->]%.*s %.*s)" |
|
248 #define _expected_token "expected token '%s' before '%.*s'" |
248 #define _missing_quote "missing closing quote symbol (%.*s)" |
249 #define _missing_quote "missing closing quote symbol (%.*s)" |
|
250 #define _parser_state "parser reached invalid state" |
|
251 #define _unknown_attribute "unknown attribute '%.*s'" |
|
252 #define _invalid_depth "invalid depth" |
249 |
253 |
250 static UcxList* dav_parse_tokenize(sstr_t src) { |
254 static UcxList* dav_parse_tokenize(sstr_t src) { |
251 UcxList *tokens = NULL; |
255 UcxList *tokens = NULL; |
252 |
256 |
253 // Delimiters: whitespace and dead whitespace around commas |
257 // Delimiters: whitespace and dead whitespace around commas |
431 } |
434 } |
432 |
435 |
433 sstr_t tokendata = *token_sstr(token); |
436 sstr_t tokendata = *token_sstr(token); |
434 |
437 |
435 switch (step) { |
438 switch (step) { |
|
439 // too much input data |
|
440 case 500: |
|
441 dav_parse_unexpected_token(stmt, token); |
|
442 goto ultrabreak; |
436 // optional clauses |
443 // optional clauses |
437 case 520: |
444 case 530: |
438 if (!sstrcasecmp(tokendata, S("where"))) { |
445 if (!sstrcasecmp(tokendata, S("where"))) { |
439 step = 30; |
446 step = 30; |
440 } |
447 } |
441 /* no break and no else*/ |
448 /* no break and no else*/ |
442 case 530: |
449 case 540: |
443 if (!sstrcasecmp(tokendata, S("with"))) { |
450 if (!sstrcasecmp(tokendata, S("with"))) { |
444 step = 40; |
451 step = 40; |
445 } else { |
452 } else { |
446 dav_parse_unexpected_token(stmt, token); |
453 dav_parse_unexpected_token(stmt, token); |
447 goto ultrabreak; |
454 goto ultrabreak; |
477 // from clause |
484 // from clause |
478 case 20: { |
485 case 20: { |
479 DavQLExpression *expr = dav_parse_expression(stmt, token, 1); |
486 DavQLExpression *expr = dav_parse_expression(stmt, token, 1); |
480 stmt->path = expr->srctext; |
487 stmt->path = expr->srctext; |
481 dav_free_expression(expr); |
488 dav_free_expression(expr); |
482 step = 520; |
489 step = 530; |
483 break; |
490 break; |
484 } |
491 } |
485 // where clause |
492 // where clause |
486 case 30: |
493 case 30: |
487 step = 530; |
494 step = 540; |
488 break; |
495 break; |
489 // with clause |
496 // with clause |
490 case 40: |
497 case 40: { |
491 step = 500; |
498 /* |
492 break; |
499 * 0: key |
493 } |
500 * 1: = |
494 } |
501 * 2: value |
495 |
502 * TODO: commas |
496 if (step < 500) { |
503 */ |
|
504 static int withparser = 0; |
|
505 |
|
506 /* |
|
507 * 1: depth |
|
508 */ |
|
509 int key; |
|
510 |
|
511 switch (withparser) { |
|
512 case 0: |
|
513 if (!sstrcasecmp(tokendata, S("depth"))) { |
|
514 key = 1; |
|
515 withparser = 1; |
|
516 } else { |
|
517 stmt->errorcode = DAVQL_ERROR_UNKNOWN_ATTRIBUTE; |
|
518 stmt->errormessage = ucx_sprintf(_unknown_attribute, |
|
519 sfmtarg(tokendata)).ptr; |
|
520 } |
|
521 break; |
|
522 case 1: |
|
523 if (sstrcmp(tokendata, S("="))) { |
|
524 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN; |
|
525 stmt->errormessage = ucx_sprintf(_expected_token, |
|
526 "=", sfmtarg(tokendata)).ptr; |
|
527 } else { |
|
528 withparser = 2; |
|
529 } |
|
530 break; |
|
531 case 2: |
|
532 switch (key) { |
|
533 case 1: /* depth */ |
|
534 if (!sstrcasecmp(tokendata, S("infinity"))) { |
|
535 stmt->depth = DAV_DEPTH_INFINITY; |
|
536 } else { |
|
537 char *conv = malloc(tokendata.length+1); |
|
538 char *chk; |
|
539 memcpy(conv, tokendata.ptr, tokendata.length); |
|
540 conv[tokendata.length] = '\0'; |
|
541 stmt->depth = strtol(conv, &chk, 10); |
|
542 if (*chk || stmt->depth < -1) { |
|
543 stmt->errorcode = DAVQL_ERROR_INVALID_DEPTH; |
|
544 stmt->errormessage = strdup(_invalid_depth); |
|
545 } |
|
546 free(conv); |
|
547 } |
|
548 break; |
|
549 } |
|
550 step = 500; |
|
551 break; |
|
552 } |
|
553 break; |
|
554 } |
|
555 default: |
|
556 stmt->errorcode = DAVQL_ERROR_INVALID; |
|
557 stmt->errormessage = strdup(_parser_state); |
|
558 } |
|
559 } |
|
560 |
|
561 if (!stmt->errorcode && step < 500) { |
497 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_END; |
562 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_END; |
498 stmt->errormessage = strdup(_unexpected_end_msg); |
563 stmt->errormessage = strdup(_unexpected_end_msg); |
499 } |
564 } |
500 } |
565 } |
501 |
566 |