diff -r 0ab1cf261a44 -r ecba8bdf9741 libidav/davqlparser.c --- a/libidav/davqlparser.c Sat Apr 04 17:44:33 2015 +0200 +++ b/libidav/davqlparser.c Sat Apr 04 19:05:09 2015 +0200 @@ -27,6 +27,7 @@ */ #include "davqlparser.h" +#include #include #include #include @@ -58,6 +59,15 @@ } } +static const char* _map_specialfield(int info) { + switch(info) { + case 0: return ""; + case 1: return "with wildcard"; + case 2: return "(resource data only)"; + default: return "with mysterious identifier"; + } +} + static const char* _map_operator(davqloperator_t op) { // don't use string array, because enum values may change switch(op) { @@ -80,22 +90,27 @@ sstr_t empty = ST("(empty)"); // Basic information - printf("Statement: %.*s\nType: %s\nField count: %zu", + size_t fieldcount = ucx_list_size(stmt->fields); + int specialfield = 0; + UCX_FOREACH(elm, stmt->fields) { + DavQLExpression* expr = (DavQLExpression*)elm->data; + if (expr->type == DAVQL_IDENTIFIER && expr->srctext.length == 1) { + if (expr->srctext.ptr[0] == '*') { + specialfield = 1; + } else if (expr->srctext.ptr[0] == '-') { + specialfield = 2; + } + } + } + if (specialfield) { + fieldcount--; + } + printf("Statement: %.*s\nType: %s\nField count: %zu %s\nPath: %.*s\n" + "Has where clause: %s\n", sfmtarg(stmt->srctext), _map_querytype(stmt->type), - ucx_list_size(stmt->fields)); - - // Has wildcard - _Bool wildcard = 0; - UCX_FOREACH(elm, stmt->fields) { - DavQLExpression* expr = (DavQLExpression*)elm->data; - if (expr->type == DAVQL_IDENTIFIER && - expr->srctext.length == 1 && expr->srctext.ptr[0] == '*') { - wildcard = 1; - } - } - printf(" %s wildcard\nPath: %.*s\nHas where clause: %s\n", - wildcard?"with":"without", + fieldcount, + _map_specialfield(specialfield), sfmtarg(stmt->path ? stmt->path->srctext : empty), stmt->where ? "yes" : "no"); if (stmt->type == DAVQL_SET) { @@ -110,6 +125,10 @@ } else { printf("Depth: %d\n", stmt->depth); } + if (stmt->errorcode) { + printf("\nError code: %d\nError: %s\n", + stmt->errorcode, stmt->errormessage); + } } static int dav_debug_ql_expr_selected(DavQLExpression *expr) { @@ -176,6 +195,10 @@ printf("Starting DavQL debugger (type 'h' for help)...\n\n"); dav_debug_ql_stmt_print(stmt); + if (stmt->errorcode) { + return; + } + DavQLExpression *examineexpr = NULL; while(1) { @@ -228,6 +251,10 @@ // P A R S E R // ------------------------------------------------------------------------ +#define _unexpected_end_msg "unexpected end of statement" +#define _invalid_msg "invalid statement" +#define _unexpected_token "unexpected token (%.*s [->]%.*s %.*s)" + static UcxList* dav_parse_tokenize(sstr_t src) { UcxList *tokens = NULL; @@ -328,6 +355,16 @@ return expr; } +static void dav_parse_unexpected_token(DavQLStatement *stmt, UcxList *token) { + sstr_t emptystring = ST(""); + stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN; + sstr_t errormsg = ucx_sprintf(_unexpected_token, + sfmtarg(token->prev?*token_sstr(token->prev):emptystring), + sfmtarg(*token_sstr(token)), + sfmtarg(token->next?*token_sstr(token->next):emptystring)); + stmt->errormessage = errormsg.ptr; +} + static void dav_parse_get_statement(DavQLStatement *stmt, UcxList *tokens) { stmt->type = DAVQL_GET; @@ -339,6 +376,7 @@ * 530: expecting WITH clause * 40: WITH clause * 500: ready to quit + * 999: error * */ int step = 10; @@ -357,10 +395,13 @@ if (!sstrcasecmp(tokendata, S("where"))) { step = 30; } - /* no break */ + /* no break and no else*/ case 530: if (!sstrcasecmp(tokendata, S("with"))) { step = 40; + } else { + dav_parse_unexpected_token(stmt, token); + step = 999; } break; // field list @@ -407,8 +448,8 @@ } if (step < 500) { - stmt->type = DAVQL_ERROR; - // TODO: save parse error message + stmt->errorcode = DAVQL_ERROR_UNEXPECTED_END; + stmt->errormessage = strdup(_unexpected_end_msg); } } @@ -446,6 +487,8 @@ dav_parse_set_statement(stmt, tokens); } else { stmt->type = DAVQL_ERROR; + stmt->errorcode = DAVQL_ERROR_INVALID; + stmt->errormessage = strdup(_invalid_msg); } // free token data @@ -455,6 +498,8 @@ ucx_list_free(tokens); } else { stmt->type = DAVQL_ERROR; + stmt->errorcode = DAVQL_ERROR_INVALID; + stmt->errormessage = strdup(_invalid_msg); } return stmt; @@ -486,5 +531,8 @@ if (stmt->where) { dav_free_expression(stmt->where); } + if (stmt->errormessage) { + free(stmt->errormessage); + } free(stmt); }