Thu, 21 Dec 2017 16:48:58 +0100
implements parser for Assignments (previously called SetExpressions) + improves davql debugger regarding DavQLField
Note: we renamed SetExpressions to Assignments so that they are not confused with expressions on sets of elements
libidav/davqlparser.c | file | annotate | diff | comparison | revisions | |
libidav/davqlparser.h | file | annotate | diff | comparison | revisions |
--- a/libidav/davqlparser.c Thu Dec 21 15:55:19 2017 +0100 +++ b/libidav/davqlparser.c Thu Dec 21 16:48:58 2017 +0100 @@ -182,6 +182,19 @@ } } +static void dav_debug_ql_field_print(DavQLField *field) { + if (field) { + printf("Name: %.*s\n", sfmtarg(field->name)); + if (field->expr) { + dav_debug_ql_expr_print(field->expr); + } else { + printf("No expression.\n"); + } + } else { + printf("No field selected.\n"); + } +} + static void dav_debug_ql_tree_print(DavQLExpression *expr, int depth) { if (expr) { if (expr->left) { @@ -281,9 +294,13 @@ case DQLD_CMD_F: examineclause = DQLD_CMD_F; examineelem = stmt->fields; - examineexpr = stmt->fields ? - ((DavQLField*)stmt->fields->data)->expr : NULL; - dav_debug_ql_expr_print(examineexpr); + if (stmt->fields) { + DavQLField* field = ((DavQLField*)stmt->fields->data); + examineexpr = field->expr; + dav_debug_ql_field_print(field); + } else { + examineexpr = NULL; + } break; case DQLD_CMD_W: examineclause = 0; examineelem = NULL; @@ -307,12 +324,14 @@ if (examineclause == DQLD_CMD_O) { examineexpr = ((DavQLOrderCriterion*) examineelem->data)->column; + dav_debug_ql_expr_print(examineexpr); } else if (examineclause == DQLD_CMD_F) { - examineexpr = ((DavQLField*)examineelem->data)->expr; + DavQLField* field = (DavQLField*)examineelem->data; + examineexpr = field->expr; + dav_debug_ql_field_print(field); } else { printf("Examining unknown clause type."); } - dav_debug_ql_expr_print(examineexpr); } else { printf("Reached end of list.\n"); } @@ -379,6 +398,7 @@ #define _error_missing_as "expecting alias ('as <identifier>') " _error_context #define _error_missing_identifier "expecting identifier " _error_context #define _error_missing_par "missing closed parenthesis " _error_context +#define _error_missing_assign "expecting assignment ('=') " _error_context #define _error_invalid_depth "invalid depth " _error_context #define _error_missing_expr "missing expression " _error_context #define _error_invalid_expr "invalid expression " _error_context @@ -1458,6 +1478,61 @@ return total_consumed; } + +static int dav_parse_assignments(DavQLStatement *stmt, UcxList *token) { + + // RULE: Assignment, {",", Assignment} + int total_consumed = 0, consumed; + do { + // RULE: Identifier, "=", Expression + if (token_is(token, DAVQL_TOKEN_IDENTIFIER)) { + + // Identifier + DavQLField *field; + dqlsec_malloc(stmt, field, DavQLField); + field->name = token_sstr(token); + total_consumed++; + token = token->next; + + // "=" + if (!token_is(token, DAVQL_TOKEN_OPERATOR) + || !tokenvalue_is(token, "=")) { + dav_free_field(field); + + dav_error_in_context(DAVQL_ERROR_MISSING_ASSIGN, + _error_missing_assign, stmt, token); + return total_consumed; + } + total_consumed++; + token = token->next; + + // Expression + dqlsec_mallocz(stmt, field->expr, DavQLExpression); + consumed = dav_parse_expression(stmt, token, field->expr); + if (stmt->errorcode) { + dav_free_field(field); + return total_consumed; + } + token = ucx_list_get(token, consumed); + total_consumed += consumed; + + // Add assignment to list and check if there's another one + dqlsec_list_append_or_free(stmt, stmt->fields, field); + consumed = token_is(token, DAVQL_TOKEN_COMMA) ? 1 : 0; + if (consumed) { + token = token->next; + total_consumed++; + } + } else { + dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN, + _error_missing_identifier, stmt, token); + return total_consumed; + } + } while (consumed); + + return total_consumed; +} + /** * Parser of a select statement. * @param stmt the statement object that shall contain the syntax tree @@ -1562,6 +1637,12 @@ static void dav_parse_set_statement(DavQLStatement *stmt, UcxList *tokens) { stmt->type = DAVQL_SET; + // Consume assignments + tokens = ucx_list_get(tokens, dav_parse_assignments(stmt, tokens)); + if (stmt->errorcode) { + return; + } + // TODO: make it so }
--- a/libidav/davqlparser.h Thu Dec 21 15:55:19 2017 +0100 +++ b/libidav/davqlparser.h Thu Dec 21 16:48:58 2017 +0100 @@ -200,10 +200,10 @@ * | "*", {",", NamedField} * | FieldExpression, {",", FieldExpression}; * FieldExpression = NamedField | Identifier; - * NamedField = Expression, " as ", Identifier; + * NamedField = Expression, " as ", Identifier; * - * SetExpressions = SetExpression, {",", SetExpression}; - * SetExpression = Identifier, "=", Expression; + * Assignments = Assignment, {",", Assignment}; + * Assignment = Identifier, "=", Expression; * * Path = String * | "/", [PathNode, {"/", PathNode}], ["/"]; @@ -231,7 +231,7 @@ * * <b>SET:</b> * <pre> - * SetStatement = "set ",SetExpressions, + * SetStatement = "set ",Assignments, * " at ", Path, * [" with ", WithClause], * (" where ", LogicalExpression) | " anywhere"; @@ -304,6 +304,9 @@ /** A closed parenthesis ')' is missing. */ #define DAVQL_ERROR_MISSING_PAR 13 +/** An assignment operator '=' is missing. */ +#define DAVQL_ERROR_MISSING_ASSIGN 14 + /** The type of the expression could not be determined. */ #define DAVQL_ERROR_INVALID_EXPR 21