377 #define _error_unexpected_token "unexpected token " _error_context |
377 #define _error_unexpected_token "unexpected token " _error_context |
378 #define _error_invalid_token "invalid token " _error_context |
378 #define _error_invalid_token "invalid token " _error_context |
379 #define _error_missing_path "expected path " _error_context |
379 #define _error_missing_path "expected path " _error_context |
380 #define _error_missing_from "expecting FROM keyword " _error_context |
380 #define _error_missing_from "expecting FROM keyword " _error_context |
381 #define _error_missing_by "expecting BY keyword " _error_context |
381 #define _error_missing_by "expecting BY keyword " _error_context |
|
382 #define _error_missing_par "missing closed parenthesis " _error_context |
382 #define _error_invalid_depth "invalid depth " _error_context |
383 #define _error_invalid_depth "invalid depth " _error_context |
383 #define _error_missing_expr "missing expression " _error_context |
384 #define _error_missing_expr "missing expression " _error_context |
384 #define _error_invalid_expr "invalid expression " _error_context |
385 #define _error_invalid_expr "invalid expression " _error_context |
385 #define _error_invalid_unary_op "invalid unary operator " _error_context |
386 #define _error_invalid_unary_op "invalid unary operator " _error_context |
386 #define _error_invalid_fmtspec "invalid format specifier " _error_context |
387 #define _error_invalid_fmtspec "invalid format specifier " _error_context |
647 |
648 |
648 // TODO: make it so |
649 // TODO: make it so |
649 return 0; |
650 return 0; |
650 } |
651 } |
651 |
652 |
|
653 // forward declaration |
|
654 static int dav_parse_expression(DavQLStatement* stmt, UcxList* token, |
|
655 DavQLExpression* expr); |
|
656 |
652 static int dav_parse_unary_expr(DavQLStatement* stmt, UcxList* token, |
657 static int dav_parse_unary_expr(DavQLStatement* stmt, UcxList* token, |
653 DavQLExpression* expr) { |
658 DavQLExpression* expr) { |
654 |
659 |
|
660 UcxList *firsttoken = token; // save for srctext recovery |
|
661 |
655 DavQLExpression* atom = expr; |
662 DavQLExpression* atom = expr; |
656 expr->srctext.ptr = token_sstr(token).ptr; |
|
657 |
|
658 int total_consumed = 0; |
663 int total_consumed = 0; |
659 |
664 |
660 // optional unary operator |
665 // optional unary operator |
661 if (token_is(token, DAVQL_TOKEN_OPERATOR)) { |
666 if (token_is(token, DAVQL_TOKEN_OPERATOR)) { |
662 char *op = strchr("+-~", token_sstr(token).ptr[0]); |
667 char *op = strchr("+-~", token_sstr(token).ptr[0]); |
678 } |
683 } |
679 } |
684 } |
680 |
685 |
681 // RULE: (ParExpression | AtomicExpression) |
686 // RULE: (ParExpression | AtomicExpression) |
682 if (token_is(token, DAVQL_TOKEN_OPENP)) { |
687 if (token_is(token, DAVQL_TOKEN_OPENP)) { |
683 // TODO: make it so (and don't forget CLOSEP) |
688 token = token->next; total_consumed++; |
|
689 // RULE: "(", Expression, ")" |
|
690 int consumed = dav_parse_expression(stmt, token, atom); |
|
691 if (stmt->errorcode) { |
|
692 return 0; |
|
693 } |
|
694 if (!consumed) { |
|
695 dav_error_in_context(DAVQL_ERROR_INVALID_EXPR, |
|
696 _error_invalid_expr, stmt, token); |
|
697 return 0; |
|
698 } |
|
699 token = ucx_list_get(token, consumed); |
|
700 total_consumed += consumed; |
|
701 if (token_is(token, DAVQL_TOKEN_CLOSEP)) { |
|
702 token = token->next; total_consumed++; |
|
703 } else { |
|
704 dav_error_in_context(DAVQL_ERROR_MISSING_PAR, |
|
705 _error_missing_par, stmt, token); |
|
706 return 0; |
|
707 } |
684 } else { |
708 } else { |
685 // RULE: FunctionCall |
709 // RULE: FunctionCall |
686 int consumed = dav_parse_funccall(stmt, token, atom); |
710 int consumed = dav_parse_funccall(stmt, token, atom); |
687 if (consumed) { |
711 if (consumed) { |
688 total_consumed += consumed; |
712 total_consumed += consumed; |
696 total_consumed += dav_parse_literal(stmt, token, atom); |
720 total_consumed += dav_parse_literal(stmt, token, atom); |
697 } |
721 } |
698 } |
722 } |
699 |
723 |
700 // recover source text |
724 // recover source text |
701 if (atom != expr) { |
725 expr->srctext.ptr = token_sstr(firsttoken).ptr; |
702 expr->srctext.length = |
726 sstr_t lasttoken = token_sstr(ucx_list_get(firsttoken, total_consumed-1)); |
703 atom->srctext.ptr - expr->srctext.ptr + atom->srctext.length; |
727 expr->srctext.length = lasttoken.ptr - expr->srctext.ptr + lasttoken.length; |
704 } |
|
705 |
728 |
706 |
729 |
707 return total_consumed; |
730 return total_consumed; |
708 } |
731 } |
709 |
732 |