libidav/davqlparser.c

changeset 358
54dbd44ac6b0
parent 357
5dfbf7b45873
child 359
bacb54502b24
equal deleted inserted replaced
357:5dfbf7b45873 358:54dbd44ac6b0
392 #define _error_out_of_memory "out of memory" 392 #define _error_out_of_memory "out of memory"
393 #define _error_unexpected_token "unexpected token " _error_context 393 #define _error_unexpected_token "unexpected token " _error_context
394 #define _error_invalid_token "invalid token " _error_context 394 #define _error_invalid_token "invalid token " _error_context
395 #define _error_missing_path "expected path " _error_context 395 #define _error_missing_path "expected path " _error_context
396 #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
397 #define _error_missing_by "expecting BY keyword " _error_context 398 #define _error_missing_by "expecting BY keyword " _error_context
398 #define _error_missing_as "expecting alias ('as <identifier>') " _error_context 399 #define _error_missing_as "expecting alias ('as <identifier>') " _error_context
399 #define _error_missing_identifier "expecting identifier " _error_context 400 #define _error_missing_identifier "expecting identifier " _error_context
400 #define _error_missing_par "missing closed parenthesis " _error_context 401 #define _error_missing_par "missing closed parenthesis " _error_context
401 #define _error_missing_assign "expecting assignment ('=') " _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
402 #define _error_invalid_depth "invalid depth " _error_context 405 #define _error_invalid_depth "invalid depth " _error_context
403 #define _error_missing_expr "missing expression " _error_context 406 #define _error_missing_expr "missing expression " _error_context
404 #define _error_invalid_expr "invalid expression " _error_context 407 #define _error_invalid_expr "invalid expression " _error_context
405 #define _error_invalid_unary_op "invalid unary operator " _error_context 408 #define _error_invalid_unary_op "invalid unary operator " _error_context
406 #define _error_invalid_logical_op "invalid logical operator " _error_context 409 #define _error_invalid_logical_op "invalid logical operator " _error_context
1531 } while (consumed); 1534 } while (consumed);
1532 1535
1533 return total_consumed; 1536 return total_consumed;
1534 } 1537 }
1535 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
1536 /** 1569 /**
1537 * Parser of a select statement. 1570 * Parser of a select statement.
1538 * @param stmt the statement object that shall contain the syntax tree 1571 * @param stmt the statement object that shall contain the syntax tree
1539 * @param tokens the token list 1572 * @param tokens the token list
1540 */ 1573 */
1545 tokens = ucx_list_get(tokens, dav_parse_fieldlist(stmt, tokens)); 1578 tokens = ucx_list_get(tokens, dav_parse_fieldlist(stmt, tokens));
1546 if (stmt->errorcode) { 1579 if (stmt->errorcode) {
1547 return; 1580 return;
1548 } 1581 }
1549 1582
1550 // Consume from keyword 1583 // Consume FROM keyword
1551 if (token_is(tokens, DAVQL_TOKEN_KEYWORD) 1584 if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
1552 && tokenvalue_is(tokens, "from")) { 1585 && tokenvalue_is(tokens, "from")) {
1553 tokens = tokens->next; 1586 tokens = tokens->next;
1554 } else { 1587 } else {
1555 dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN, 1588 dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
1556 _error_missing_from, stmt, tokens); 1589 _error_missing_from, stmt, tokens);
1557 return; 1590 return;
1558 } 1591 }
1559 1592
1560 // Consume path 1593 // Consume path
1561 if (token_is(tokens, DAVQL_TOKEN_STRING)) { 1594 tokens = ucx_list_get(tokens, dav_parse_path(stmt, tokens));
1562 stmt->path = token_sstr(tokens); 1595 if (stmt->errorcode) {
1563 tokens = tokens->next;
1564 } else if (token_is(tokens, DAVQL_TOKEN_OPERATOR)
1565 && tokenvalue_is(tokens, "/")) {
1566 stmt->path = token_sstr(tokens);
1567 tokens = tokens->next;
1568 while (!token_is(tokens, DAVQL_TOKEN_KEYWORD) &&
1569 !token_is(tokens, DAVQL_TOKEN_END)) {
1570 sstr_t toksstr = token_sstr(tokens);
1571 stmt->path.length = toksstr.ptr-stmt->path.ptr+toksstr.length;
1572 tokens = tokens->next;
1573 }
1574 } else if (token_is(tokens, DAVQL_TOKEN_FMTSPEC) &&
1575 tokenvalue_is(tokens, "%s")) {
1576 stmt->path = token_sstr(tokens);
1577 tokens = tokens->next;
1578 } else {
1579 dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
1580 _error_missing_path, stmt, tokens);
1581 return; 1596 return;
1582 } 1597 }
1583 1598
1584 // Consume with clause (if any) 1599 // Consume with clause (if any)
1585 if (token_is(tokens, DAVQL_TOKEN_KEYWORD) 1600 if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
1641 tokens = ucx_list_get(tokens, dav_parse_assignments(stmt, tokens)); 1656 tokens = ucx_list_get(tokens, dav_parse_assignments(stmt, tokens));
1642 if (stmt->errorcode) { 1657 if (stmt->errorcode) {
1643 return; 1658 return;
1644 } 1659 }
1645 1660
1646 // TODO: make it so 1661 // Consume AT keyword
1662 if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
1663 && tokenvalue_is(tokens, "at")) {
1664 tokens = tokens->next;
1665 } else {
1666 dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
1667 _error_missing_at, stmt, tokens);
1668 return;
1669 }
1670
1671 // Consume path
1672 tokens = ucx_list_get(tokens, dav_parse_path(stmt, tokens));
1673 if (stmt->errorcode) {
1674 return;
1675 }
1676
1677 // Consume with clause (if any)
1678 if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
1679 && tokenvalue_is(tokens, "with")) {
1680 tokens = tokens->next;
1681 tokens = ucx_list_get(tokens,
1682 dav_parse_with_clause(stmt, tokens));
1683 }
1684 if (stmt->errorcode) {
1685 return;
1686 }
1687
1688 // Consume mandatory where clause (or anywhere keyword)
1689 if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
1690 && tokenvalue_is(tokens, "where")) {
1691 tokens = tokens->next;
1692 tokens = ucx_list_get(tokens,
1693 dav_parse_where_clause(stmt, tokens));
1694 } else if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
1695 && tokenvalue_is(tokens, "anywhere")) {
1696 // no-op, but we want the user to be explicit about this
1697 stmt->where = NULL;
1698 } else {
1699 dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
1700 _error_missing_where, stmt, tokens);
1701 }
1647 } 1702 }
1648 1703
1649 DavQLStatement* dav_parse_statement(sstr_t srctext) { 1704 DavQLStatement* dav_parse_statement(sstr_t srctext) {
1650 DavQLStatement *stmt = calloc(1, sizeof(DavQLStatement)); 1705 DavQLStatement *stmt = calloc(1, sizeof(DavQLStatement));
1651 1706

mercurial