25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
26 * POSSIBILITY OF SUCH DAMAGE. |
26 * POSSIBILITY OF SUCH DAMAGE. |
27 */ |
27 */ |
28 |
28 |
29 #include "davqlparser.h" |
29 #include "davqlparser.h" |
|
30 #include <ucx/utils.h> |
30 #include <string.h> |
31 #include <string.h> |
31 #include <stdio.h> |
32 #include <stdio.h> |
32 #include <ctype.h> |
33 #include <ctype.h> |
33 |
34 |
34 #define sfmtarg(s) ((int)(s).length), (s).ptr |
35 #define sfmtarg(s) ((int)(s).length), (s).ptr |
53 case DAVQL_UNARY: return "UNARY"; |
54 case DAVQL_UNARY: return "UNARY"; |
54 case DAVQL_BINARY: return "BINARY"; |
55 case DAVQL_BINARY: return "BINARY"; |
55 case DAVQL_LOGICAL: return "LOGICAL"; |
56 case DAVQL_LOGICAL: return "LOGICAL"; |
56 case DAVQL_FUNCCALL: return "FUNCCALL"; |
57 case DAVQL_FUNCCALL: return "FUNCCALL"; |
57 default: return "unknown"; |
58 default: return "unknown"; |
|
59 } |
|
60 } |
|
61 |
|
62 static const char* _map_specialfield(int info) { |
|
63 switch(info) { |
|
64 case 0: return ""; |
|
65 case 1: return "with wildcard"; |
|
66 case 2: return "(resource data only)"; |
|
67 default: return "with mysterious identifier"; |
58 } |
68 } |
59 } |
69 } |
60 |
70 |
61 static const char* _map_operator(davqloperator_t op) { |
71 static const char* _map_operator(davqloperator_t op) { |
62 // don't use string array, because enum values may change |
72 // don't use string array, because enum values may change |
78 |
88 |
79 static void dav_debug_ql_stmt_print(DavQLStatement *stmt) { |
89 static void dav_debug_ql_stmt_print(DavQLStatement *stmt) { |
80 sstr_t empty = ST("(empty)"); |
90 sstr_t empty = ST("(empty)"); |
81 |
91 |
82 // Basic information |
92 // Basic information |
83 printf("Statement: %.*s\nType: %s\nField count: %zu", |
93 size_t fieldcount = ucx_list_size(stmt->fields); |
|
94 int specialfield = 0; |
|
95 UCX_FOREACH(elm, stmt->fields) { |
|
96 DavQLExpression* expr = (DavQLExpression*)elm->data; |
|
97 if (expr->type == DAVQL_IDENTIFIER && expr->srctext.length == 1) { |
|
98 if (expr->srctext.ptr[0] == '*') { |
|
99 specialfield = 1; |
|
100 } else if (expr->srctext.ptr[0] == '-') { |
|
101 specialfield = 2; |
|
102 } |
|
103 } |
|
104 } |
|
105 if (specialfield) { |
|
106 fieldcount--; |
|
107 } |
|
108 printf("Statement: %.*s\nType: %s\nField count: %zu %s\nPath: %.*s\n" |
|
109 "Has where clause: %s\n", |
84 sfmtarg(stmt->srctext), |
110 sfmtarg(stmt->srctext), |
85 _map_querytype(stmt->type), |
111 _map_querytype(stmt->type), |
86 ucx_list_size(stmt->fields)); |
112 fieldcount, |
87 |
113 _map_specialfield(specialfield), |
88 // Has wildcard |
|
89 _Bool wildcard = 0; |
|
90 UCX_FOREACH(elm, stmt->fields) { |
|
91 DavQLExpression* expr = (DavQLExpression*)elm->data; |
|
92 if (expr->type == DAVQL_IDENTIFIER && |
|
93 expr->srctext.length == 1 && expr->srctext.ptr[0] == '*') { |
|
94 wildcard = 1; |
|
95 } |
|
96 } |
|
97 printf(" %s wildcard\nPath: %.*s\nHas where clause: %s\n", |
|
98 wildcard?"with":"without", |
|
99 sfmtarg(stmt->path ? stmt->path->srctext : empty), |
114 sfmtarg(stmt->path ? stmt->path->srctext : empty), |
100 stmt->where ? "yes" : "no"); |
115 stmt->where ? "yes" : "no"); |
101 if (stmt->type == DAVQL_SET) { |
116 if (stmt->type == DAVQL_SET) { |
102 printf("Value list size matches: %s", |
117 printf("Value list size matches: %s", |
103 ucx_list_size(stmt->fields) == ucx_list_size(stmt->setvalues) |
118 ucx_list_size(stmt->fields) == ucx_list_size(stmt->setvalues) |
107 // WITH attributes |
122 // WITH attributes |
108 if (stmt->depth < 0) { |
123 if (stmt->depth < 0) { |
109 printf("Depth: infinity\n"); |
124 printf("Depth: infinity\n"); |
110 } else { |
125 } else { |
111 printf("Depth: %d\n", stmt->depth); |
126 printf("Depth: %d\n", stmt->depth); |
|
127 } |
|
128 if (stmt->errorcode) { |
|
129 printf("\nError code: %d\nError: %s\n", |
|
130 stmt->errorcode, stmt->errormessage); |
112 } |
131 } |
113 } |
132 } |
114 |
133 |
115 static int dav_debug_ql_expr_selected(DavQLExpression *expr) { |
134 static int dav_debug_ql_expr_selected(DavQLExpression *expr) { |
116 if (!expr) { |
135 if (!expr) { |
225 } |
248 } |
226 |
249 |
227 // ------------------------------------------------------------------------ |
250 // ------------------------------------------------------------------------ |
228 // P A R S E R |
251 // P A R S E R |
229 // ------------------------------------------------------------------------ |
252 // ------------------------------------------------------------------------ |
|
253 |
|
254 #define _unexpected_end_msg "unexpected end of statement" |
|
255 #define _invalid_msg "invalid statement" |
|
256 #define _unexpected_token "unexpected token (%.*s [->]%.*s %.*s)" |
230 |
257 |
231 static UcxList* dav_parse_tokenize(sstr_t src) { |
258 static UcxList* dav_parse_tokenize(sstr_t src) { |
232 UcxList *tokens = NULL; |
259 UcxList *tokens = NULL; |
233 |
260 |
234 // Delimiters: whitespace and dead whitespace around commas |
261 // Delimiters: whitespace and dead whitespace around commas |
326 } |
353 } |
327 |
354 |
328 return expr; |
355 return expr; |
329 } |
356 } |
330 |
357 |
|
358 static void dav_parse_unexpected_token(DavQLStatement *stmt, UcxList *token) { |
|
359 sstr_t emptystring = ST(""); |
|
360 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN; |
|
361 sstr_t errormsg = ucx_sprintf(_unexpected_token, |
|
362 sfmtarg(token->prev?*token_sstr(token->prev):emptystring), |
|
363 sfmtarg(*token_sstr(token)), |
|
364 sfmtarg(token->next?*token_sstr(token->next):emptystring)); |
|
365 stmt->errormessage = errormsg.ptr; |
|
366 } |
|
367 |
331 static void dav_parse_get_statement(DavQLStatement *stmt, UcxList *tokens) { |
368 static void dav_parse_get_statement(DavQLStatement *stmt, UcxList *tokens) { |
332 stmt->type = DAVQL_GET; |
369 stmt->type = DAVQL_GET; |
333 |
370 |
334 /* |
371 /* |
335 * 10: field list |
372 * 10: field list |
355 // optional clauses |
393 // optional clauses |
356 case 520: |
394 case 520: |
357 if (!sstrcasecmp(tokendata, S("where"))) { |
395 if (!sstrcasecmp(tokendata, S("where"))) { |
358 step = 30; |
396 step = 30; |
359 } |
397 } |
360 /* no break */ |
398 /* no break and no else*/ |
361 case 530: |
399 case 530: |
362 if (!sstrcasecmp(tokendata, S("with"))) { |
400 if (!sstrcasecmp(tokendata, S("with"))) { |
363 step = 40; |
401 step = 40; |
|
402 } else { |
|
403 dav_parse_unexpected_token(stmt, token); |
|
404 step = 999; |
364 } |
405 } |
365 break; |
406 break; |
366 // field list |
407 // field list |
367 case 10: { |
408 case 10: { |
368 _Bool fromkeyword = !sstrcasecmp(tokendata, S("from")); |
409 _Bool fromkeyword = !sstrcasecmp(tokendata, S("from")); |
444 dav_parse_get_statement(stmt, tokens); |
485 dav_parse_get_statement(stmt, tokens); |
445 } else if (!sstrcasecmp(token, S("set"))) { |
486 } else if (!sstrcasecmp(token, S("set"))) { |
446 dav_parse_set_statement(stmt, tokens); |
487 dav_parse_set_statement(stmt, tokens); |
447 } else { |
488 } else { |
448 stmt->type = DAVQL_ERROR; |
489 stmt->type = DAVQL_ERROR; |
|
490 stmt->errorcode = DAVQL_ERROR_INVALID; |
|
491 stmt->errormessage = strdup(_invalid_msg); |
449 } |
492 } |
450 |
493 |
451 // free token data |
494 // free token data |
452 UCX_FOREACH(token, tokens) { |
495 UCX_FOREACH(token, tokens) { |
453 free(token->data); |
496 free(token->data); |
454 } |
497 } |
455 ucx_list_free(tokens); |
498 ucx_list_free(tokens); |
456 } else { |
499 } else { |
457 stmt->type = DAVQL_ERROR; |
500 stmt->type = DAVQL_ERROR; |
|
501 stmt->errorcode = DAVQL_ERROR_INVALID; |
|
502 stmt->errormessage = strdup(_invalid_msg); |
458 } |
503 } |
459 |
504 |
460 return stmt; |
505 return stmt; |
461 } |
506 } |
462 |
507 |