libidav/davqlparser.c

changeset 362
9a75b6df3307
parent 359
bacb54502b24
child 365
f04ab0420512
equal deleted inserted replaced
361:b6f2462ee055 362:9a75b6df3307
180 sfmtarg(expr->right?expr->right->srctext:empty)); 180 sfmtarg(expr->right?expr->right->srctext:empty));
181 } 181 }
182 } 182 }
183 } 183 }
184 184
185 static void dav_debug_ql_field_print(DavQLField *field) {
186 if (field) {
187 printf("Name: %.*s\n", sfmtarg(field->name));
188 if (field->expr) {
189 dav_debug_ql_expr_print(field->expr);
190 } else {
191 printf("No expression.\n");
192 }
193 } else {
194 printf("No field selected.\n");
195 }
196 }
197
185 static void dav_debug_ql_tree_print(DavQLExpression *expr, int depth) { 198 static void dav_debug_ql_tree_print(DavQLExpression *expr, int depth) {
186 if (expr) { 199 if (expr) {
187 if (expr->left) { 200 if (expr->left) {
188 printf("%*c%s\n", depth, ' ', _map_operator(expr->op)); 201 printf("%*c%s\n", depth, ' ', _map_operator(expr->op));
189 dav_debug_ql_tree_print(expr->left, depth+1); 202 dav_debug_ql_tree_print(expr->left, depth+1);
277 case DQLD_CMD_PS: dav_debug_ql_stmt_print(stmt); break; 290 case DQLD_CMD_PS: dav_debug_ql_stmt_print(stmt); break;
278 case DQLD_CMD_PE: dav_debug_ql_expr_print(examineexpr); break; 291 case DQLD_CMD_PE: dav_debug_ql_expr_print(examineexpr); break;
279 case DQLD_CMD_PT: dav_debug_ql_tree_print(examineexpr, 1); break; 292 case DQLD_CMD_PT: dav_debug_ql_tree_print(examineexpr, 1); break;
280 case DQLD_CMD_PF: dav_debug_ql_fnames_print(stmt); break; 293 case DQLD_CMD_PF: dav_debug_ql_fnames_print(stmt); break;
281 case DQLD_CMD_F: 294 case DQLD_CMD_F:
282 if (examineclause != DQLD_CMD_F) { 295 examineclause = DQLD_CMD_F;
283 examineclause = DQLD_CMD_F; 296 examineelem = stmt->fields;
284 examineelem = stmt->fields; 297 if (stmt->fields) {
285 examineexpr = stmt->fields ? 298 DavQLField* field = ((DavQLField*)stmt->fields->data);
286 ((DavQLField*)stmt->fields->data)->expr : NULL; 299 examineexpr = field->expr;
287 dav_debug_ql_expr_print(examineexpr); 300 dav_debug_ql_field_print(field);
301 } else {
302 examineexpr = NULL;
288 } 303 }
289 break; 304 break;
290 case DQLD_CMD_W: 305 case DQLD_CMD_W:
291 examineclause = 0; examineelem = NULL; 306 examineclause = 0; examineelem = NULL;
292 examineexpr = stmt->where; 307 examineexpr = stmt->where;
293 dav_debug_ql_expr_print(examineexpr); 308 dav_debug_ql_expr_print(examineexpr);
294 break; 309 break;
295 case DQLD_CMD_O: 310 case DQLD_CMD_O:
296 if (examineclause != DQLD_CMD_O) { 311 examineclause = DQLD_CMD_O;
297 examineclause = DQLD_CMD_O; 312 examineelem = stmt->orderby;
298 examineelem = stmt->orderby; 313 examineexpr = stmt->orderby ?
299 examineexpr = stmt->orderby ? 314 ((DavQLOrderCriterion*)stmt->orderby->data)->column : NULL;
300 ((DavQLOrderCriterion*)stmt->orderby->data)->column : NULL; 315 dav_debug_ql_expr_print(examineexpr);
301 dav_debug_ql_expr_print(examineexpr);
302 }
303 break; 316 break;
304 case DQLD_CMD_N: 317 case DQLD_CMD_N:
305 case DQLD_CMD_P: 318 case DQLD_CMD_P:
306 if (examineelem) { 319 if (examineelem) {
307 UcxList *newelem = (cmd == DQLD_CMD_N ? 320 UcxList *newelem = (cmd == DQLD_CMD_N ?
309 if (newelem) { 322 if (newelem) {
310 examineelem = newelem; 323 examineelem = newelem;
311 if (examineclause == DQLD_CMD_O) { 324 if (examineclause == DQLD_CMD_O) {
312 examineexpr = ((DavQLOrderCriterion*) 325 examineexpr = ((DavQLOrderCriterion*)
313 examineelem->data)->column; 326 examineelem->data)->column;
327 dav_debug_ql_expr_print(examineexpr);
314 } else if (examineclause == DQLD_CMD_F) { 328 } else if (examineclause == DQLD_CMD_F) {
315 examineexpr = ((DavQLField*)examineelem->data)->expr; 329 DavQLField* field = (DavQLField*)examineelem->data;
330 examineexpr = field->expr;
331 dav_debug_ql_field_print(field);
316 } else { 332 } else {
317 printf("Examining unknown clause type."); 333 printf("Examining unknown clause type.");
318 } 334 }
319 dav_debug_ql_expr_print(examineexpr);
320 } else { 335 } else {
321 printf("Reached end of list.\n"); 336 printf("Reached end of list.\n");
322 } 337 }
323 } else { 338 } else {
324 printf("Currently not examining an expression list.\n"); 339 printf("Currently not examining an expression list.\n");
377 #define _error_out_of_memory "out of memory" 392 #define _error_out_of_memory "out of memory"
378 #define _error_unexpected_token "unexpected token " _error_context 393 #define _error_unexpected_token "unexpected token " _error_context
379 #define _error_invalid_token "invalid token " _error_context 394 #define _error_invalid_token "invalid token " _error_context
380 #define _error_missing_path "expected path " _error_context 395 #define _error_missing_path "expected path " _error_context
381 #define _error_missing_from "expecting FROM keyword " _error_context 396 #define _error_missing_from "expecting FROM keyword " _error_context
397 #define _error_missing_at "expecting AT keyword " _error_context
382 #define _error_missing_by "expecting BY keyword " _error_context 398 #define _error_missing_by "expecting BY keyword " _error_context
383 #define _error_missing_as "expecting alias ('as <identifier>') " _error_context 399 #define _error_missing_as "expecting alias ('as <identifier>') " _error_context
384 #define _error_missing_identifier "expecting identifier " _error_context 400 #define _error_missing_identifier "expecting identifier " _error_context
385 #define _error_missing_par "missing closed parenthesis " _error_context 401 #define _error_missing_par "missing closed parenthesis " _error_context
402 #define _error_missing_assign "expecting assignment ('=') " _error_context
403 #define _error_missing_where "SET statements must have a WHERE clause or " \
404 "explicitly use ANYWHERE " _error_context
386 #define _error_invalid_depth "invalid depth " _error_context 405 #define _error_invalid_depth "invalid depth " _error_context
387 #define _error_missing_expr "missing expression " _error_context 406 #define _error_missing_expr "missing expression " _error_context
388 #define _error_invalid_expr "invalid expression " _error_context 407 #define _error_invalid_expr "invalid expression " _error_context
389 #define _error_invalid_unary_op "invalid unary operator " _error_context 408 #define _error_invalid_unary_op "invalid unary operator " _error_context
390 #define _error_invalid_logical_op "invalid logical operator " _error_context 409 #define _error_invalid_logical_op "invalid logical operator " _error_context
1460 } while (consumed); 1479 } while (consumed);
1461 1480
1462 return total_consumed; 1481 return total_consumed;
1463 } 1482 }
1464 1483
1484
1485 static int dav_parse_assignments(DavQLStatement *stmt, UcxList *token) {
1486
1487 // RULE: Assignment, {",", Assignment}
1488 int total_consumed = 0, consumed;
1489 do {
1490 // RULE: Identifier, "=", Expression
1491 if (token_is(token, DAVQL_TOKEN_IDENTIFIER)) {
1492
1493 // Identifier
1494 DavQLField *field;
1495 dqlsec_malloc(stmt, field, DavQLField);
1496 field->name = token_sstr(token);
1497 total_consumed++;
1498 token = token->next;
1499
1500 // "="
1501 if (!token_is(token, DAVQL_TOKEN_OPERATOR)
1502 || !tokenvalue_is(token, "=")) {
1503 dav_free_field(field);
1504
1505 dav_error_in_context(DAVQL_ERROR_MISSING_ASSIGN,
1506 _error_missing_assign, stmt, token);
1507 return total_consumed;
1508 }
1509 total_consumed++;
1510 token = token->next;
1511
1512 // Expression
1513 dqlsec_mallocz(stmt, field->expr, DavQLExpression);
1514 consumed = dav_parse_expression(stmt, token, field->expr);
1515 if (stmt->errorcode) {
1516 dav_free_field(field);
1517 return total_consumed;
1518 }
1519 token = ucx_list_get(token, consumed);
1520 total_consumed += consumed;
1521
1522 // Add assignment to list and check if there's another one
1523 dqlsec_list_append_or_free(stmt, stmt->fields, field);
1524 consumed = token_is(token, DAVQL_TOKEN_COMMA) ? 1 : 0;
1525 if (consumed) {
1526 token = token->next;
1527 total_consumed++;
1528 }
1529 } else {
1530 dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
1531 _error_missing_identifier, stmt, token);
1532 return total_consumed;
1533 }
1534 } while (consumed);
1535
1536 return total_consumed;
1537 }
1538
1539 static int dav_parse_path(DavQLStatement *stmt, UcxList *tokens) {
1540 if (token_is(tokens, DAVQL_TOKEN_STRING)) {
1541 stmt->path = token_sstr(tokens);
1542 tokens = tokens->next;
1543 return 1;
1544 } else if (token_is(tokens, DAVQL_TOKEN_OPERATOR)
1545 && tokenvalue_is(tokens, "/")) {
1546 stmt->path = token_sstr(tokens);
1547 tokens = tokens->next;
1548 int consumed = 1;
1549 while (!token_is(tokens, DAVQL_TOKEN_KEYWORD) &&
1550 !token_is(tokens, DAVQL_TOKEN_END)) {
1551 sstr_t toksstr = token_sstr(tokens);
1552 stmt->path.length = toksstr.ptr-stmt->path.ptr+toksstr.length;
1553 tokens = tokens->next;
1554 consumed++;
1555 }
1556 return consumed;
1557 } else if (token_is(tokens, DAVQL_TOKEN_FMTSPEC) &&
1558 tokenvalue_is(tokens, "%s")) {
1559 stmt->path = token_sstr(tokens);
1560 tokens = tokens->next;
1561 return 1;
1562 } else {
1563 dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
1564 _error_missing_path, stmt, tokens);
1565 return 0;
1566 }
1567 }
1568
1465 /** 1569 /**
1466 * Parser of a select statement. 1570 * Parser of a select statement.
1467 * @param stmt the statement object that shall contain the syntax tree 1571 * @param stmt the statement object that shall contain the syntax tree
1468 * @param tokens the token list 1572 * @param tokens the token list
1469 */ 1573 */
1474 tokens = ucx_list_get(tokens, dav_parse_fieldlist(stmt, tokens)); 1578 tokens = ucx_list_get(tokens, dav_parse_fieldlist(stmt, tokens));
1475 if (stmt->errorcode) { 1579 if (stmt->errorcode) {
1476 return; 1580 return;
1477 } 1581 }
1478 1582
1479 // Consume from keyword 1583 // Consume FROM keyword
1480 if (token_is(tokens, DAVQL_TOKEN_KEYWORD) 1584 if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
1481 && tokenvalue_is(tokens, "from")) { 1585 && tokenvalue_is(tokens, "from")) {
1482 tokens = tokens->next; 1586 tokens = tokens->next;
1483 } else { 1587 } else {
1484 dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN, 1588 dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
1485 _error_missing_from, stmt, tokens); 1589 _error_missing_from, stmt, tokens);
1486 return; 1590 return;
1487 } 1591 }
1488 1592
1489 // Consume path 1593 // Consume path
1490 if (token_is(tokens, DAVQL_TOKEN_STRING)) { 1594 tokens = ucx_list_get(tokens, dav_parse_path(stmt, tokens));
1491 stmt->path = token_sstr(tokens); 1595 if (stmt->errorcode) {
1492 tokens = tokens->next;
1493 } else if (token_is(tokens, DAVQL_TOKEN_OPERATOR)
1494 && tokenvalue_is(tokens, "/")) {
1495 stmt->path = token_sstr(tokens);
1496 tokens = tokens->next;
1497 while (!token_is(tokens, DAVQL_TOKEN_KEYWORD) &&
1498 !token_is(tokens, DAVQL_TOKEN_END)) {
1499 sstr_t toksstr = token_sstr(tokens);
1500 stmt->path.length = toksstr.ptr-stmt->path.ptr+toksstr.length;
1501 tokens = tokens->next;
1502 }
1503 } else if (token_is(tokens, DAVQL_TOKEN_FMTSPEC) &&
1504 tokenvalue_is(tokens, "%s")) {
1505 stmt->path = token_sstr(tokens);
1506 tokens = tokens->next;
1507 } else {
1508 dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
1509 _error_missing_path, stmt, tokens);
1510 return; 1596 return;
1511 } 1597 }
1512 1598
1513 // Consume with clause (if any) 1599 // Consume with clause (if any)
1514 if (token_is(tokens, DAVQL_TOKEN_KEYWORD) 1600 if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
1525 if (token_is(tokens, DAVQL_TOKEN_KEYWORD) 1611 if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
1526 && tokenvalue_is(tokens, "where")) { 1612 && tokenvalue_is(tokens, "where")) {
1527 tokens = tokens->next; 1613 tokens = tokens->next;
1528 tokens = ucx_list_get(tokens, 1614 tokens = ucx_list_get(tokens,
1529 dav_parse_where_clause(stmt, tokens)); 1615 dav_parse_where_clause(stmt, tokens));
1616 } else if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
1617 && tokenvalue_is(tokens, "anywhere")) {
1618 // useless, but the user may want to explicitly express his intent
1619 tokens = tokens->next;
1620 stmt->where = NULL;
1530 } 1621 }
1531 if (stmt->errorcode) { 1622 if (stmt->errorcode) {
1532 return; 1623 return;
1533 } 1624 }
1534 1625
1564 } 1655 }
1565 1656
1566 static void dav_parse_set_statement(DavQLStatement *stmt, UcxList *tokens) { 1657 static void dav_parse_set_statement(DavQLStatement *stmt, UcxList *tokens) {
1567 stmt->type = DAVQL_SET; 1658 stmt->type = DAVQL_SET;
1568 1659
1569 // TODO: make it so 1660 // Consume assignments
1661 tokens = ucx_list_get(tokens, dav_parse_assignments(stmt, tokens));
1662 if (stmt->errorcode) {
1663 return;
1664 }
1665
1666 // Consume AT keyword
1667 if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
1668 && tokenvalue_is(tokens, "at")) {
1669 tokens = tokens->next;
1670 } else {
1671 dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
1672 _error_missing_at, stmt, tokens);
1673 return;
1674 }
1675
1676 // Consume path
1677 tokens = ucx_list_get(tokens, dav_parse_path(stmt, tokens));
1678 if (stmt->errorcode) {
1679 return;
1680 }
1681
1682 // Consume with clause (if any)
1683 if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
1684 && tokenvalue_is(tokens, "with")) {
1685 tokens = tokens->next;
1686 tokens = ucx_list_get(tokens,
1687 dav_parse_with_clause(stmt, tokens));
1688 }
1689 if (stmt->errorcode) {
1690 return;
1691 }
1692
1693 // Consume mandatory where clause (or anywhere keyword)
1694 if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
1695 && tokenvalue_is(tokens, "where")) {
1696 tokens = tokens->next;
1697 tokens = ucx_list_get(tokens,
1698 dav_parse_where_clause(stmt, tokens));
1699 } else if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
1700 && tokenvalue_is(tokens, "anywhere")) {
1701 // no-op, but we want the user to be explicit about this
1702 tokens = tokens->next;
1703 stmt->where = NULL;
1704 } else {
1705 dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
1706 _error_missing_where, stmt, tokens);
1707 return;
1708 }
1570 } 1709 }
1571 1710
1572 DavQLStatement* dav_parse_statement(sstr_t srctext) { 1711 DavQLStatement* dav_parse_statement(sstr_t srctext) {
1573 DavQLStatement *stmt = calloc(1, sizeof(DavQLStatement)); 1712 DavQLStatement *stmt = calloc(1, sizeof(DavQLStatement));
1574 1713

mercurial