implements parser for Assignments (previously called SetExpressions) + improves davql debugger regarding DavQLField

Thu, 21 Dec 2017 16:48:58 +0100

author
Mike Becker <universe@uap-core.de>
date
Thu, 21 Dec 2017 16:48:58 +0100
changeset 357
5dfbf7b45873
parent 356
699781a1d6fd
child 358
54dbd44ac6b0

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
 

mercurial