Sat, 04 Apr 2015 21:47:40 +0200
parser for with clause + unexpected token message, if something is beyond the with clause
libidav/davqlparser.c | file | annotate | diff | comparison | revisions | |
libidav/davqlparser.h | file | annotate | diff | comparison | revisions |
--- a/libidav/davqlparser.c Sat Apr 04 20:37:03 2015 +0200 +++ b/libidav/davqlparser.c Sat Apr 04 21:47:40 2015 +0200 @@ -245,7 +245,11 @@ #define _unexpected_end_msg "unexpected end of statement" #define _invalid_msg "invalid statement" #define _unexpected_token "unexpected token (%.*s [->]%.*s %.*s)" +#define _expected_token "expected token '%s' before '%.*s'" #define _missing_quote "missing closing quote symbol (%.*s)" +#define _parser_state "parser reached invalid state" +#define _unknown_attribute "unknown attribute '%.*s'" +#define _invalid_depth "invalid depth" static UcxList* dav_parse_tokenize(sstr_t src) { UcxList *tokens = NULL; @@ -410,12 +414,11 @@ /* * 10: field list * 20: FROM clause - * 520: expecting WHERE or WITH clause + * 530: expecting WHERE or WITH clause * 30: WHERE clause - * 530: expecting WITH clause + * 540: expecting WITH clause * 40: WITH clause - * 500: ready to quit - * 999: error + * 500: expect end * */ int step = 10; @@ -433,13 +436,17 @@ sstr_t tokendata = *token_sstr(token); switch (step) { + // too much input data + case 500: + dav_parse_unexpected_token(stmt, token); + goto ultrabreak; // optional clauses - case 520: + case 530: if (!sstrcasecmp(tokendata, S("where"))) { step = 30; } /* no break and no else*/ - case 530: + case 540: if (!sstrcasecmp(tokendata, S("with"))) { step = 40; } else { @@ -479,21 +486,79 @@ DavQLExpression *expr = dav_parse_expression(stmt, token, 1); stmt->path = expr->srctext; dav_free_expression(expr); - step = 520; + step = 530; break; } // where clause case 30: - step = 530; + step = 540; break; // with clause - case 40: - step = 500; + case 40: { + /* + * 0: key + * 1: = + * 2: value + * TODO: commas + */ + static int withparser = 0; + + /* + * 1: depth + */ + int key; + + switch (withparser) { + case 0: + if (!sstrcasecmp(tokendata, S("depth"))) { + key = 1; + withparser = 1; + } else { + stmt->errorcode = DAVQL_ERROR_UNKNOWN_ATTRIBUTE; + stmt->errormessage = ucx_sprintf(_unknown_attribute, + sfmtarg(tokendata)).ptr; + } + break; + case 1: + if (sstrcmp(tokendata, S("="))) { + stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN; + stmt->errormessage = ucx_sprintf(_expected_token, + "=", sfmtarg(tokendata)).ptr; + } else { + withparser = 2; + } + break; + case 2: + switch (key) { + case 1: /* depth */ + if (!sstrcasecmp(tokendata, S("infinity"))) { + stmt->depth = DAV_DEPTH_INFINITY; + } else { + char *conv = malloc(tokendata.length+1); + char *chk; + memcpy(conv, tokendata.ptr, tokendata.length); + conv[tokendata.length] = '\0'; + stmt->depth = strtol(conv, &chk, 10); + if (*chk || stmt->depth < -1) { + stmt->errorcode = DAVQL_ERROR_INVALID_DEPTH; + stmt->errormessage = strdup(_invalid_depth); + } + free(conv); + } + break; + } + step = 500; + break; + } break; } + default: + stmt->errorcode = DAVQL_ERROR_INVALID; + stmt->errormessage = strdup(_parser_state); + } } - if (step < 500) { + if (!stmt->errorcode && step < 500) { stmt->errorcode = DAVQL_ERROR_UNEXPECTED_END; stmt->errormessage = strdup(_unexpected_end_msg); }
--- a/libidav/davqlparser.h Sat Apr 04 20:37:03 2015 +0200 +++ b/libidav/davqlparser.h Sat Apr 04 21:47:40 2015 +0200 @@ -207,6 +207,12 @@ /** Infinity recursion depth for a DavQLStatement. */ #define DAV_DEPTH_INFINITY -1 +/** The with-clause contains an unknown attribute. */ +#define DAVQL_ERROR_UNKNOWN_ATTRIBUTE 20 + +/** Depth must be greater than zero or infinity. */ +#define DAVQL_ERROR_INVALID_DEPTH 21 + /** A quote symbol (' or `) is missing. */ #define DAVQL_ERROR_MISSING_QUOTE 50