libidav/davqlparser.c

changeset 92
e073cf4afc6a
parent 91
838b427267bb
child 93
2176ffbf1346
--- a/libidav/davqlparser.c	Sat Apr 04 22:20:39 2015 +0200
+++ b/libidav/davqlparser.c	Mon Apr 13 19:04:46 2015 +0200
@@ -246,6 +246,7 @@
 #define _invalid_msg "invalid statement"
 #define _unexpected_token "unexpected token (%.*s [->]%.*s %.*s)"
 #define _expected_token "expected token '%s' before '%.*s'"
+#define _expected_by "expected by after order (order [->]%.*s)"
 #define _missing_quote "missing closing quote symbol (%.*s)"
 #define _parser_state "parser reached invalid state"
 #define _unknown_attribute "unknown attribute '%.*s'"
@@ -483,18 +484,19 @@
 static void dav_parse_get_statement(DavQLStatement *stmt, UcxList *tokens) {
     stmt->type = DAVQL_GET;
     
-    /*
-     *   10: field list
-     *   20: FROM clause
-     *  530: expecting WHERE or WITH clause
-     *   30: WHERE clause
-     *  540: expecting WITH clause
-     *  541: expecting comma for WITH clause
-     *   40: WITH clause
-     *  500: expect end
-     * 
-     */
-    int step = 10;
+#define _step_fieldlist_    10 // field list
+#define _step_FROM_         20 // FROM clause
+#define _step_expect_WWO_  530 // expecting WITH, WHERE or ORDER BY clause
+#define _step_comma_WITH_  531 // expecting comma for WITH clause
+#define _step_WITH_         30 // WITH clause
+#define _step_expect_WO    540 // expecting WHERE or ORDER BY clause
+#define _step_WHERE_        40 // WHERE clause
+#define _step_expect_O     550 // expecting ORDER BY clause
+#define _step_expect_BY    551 // expecting the BY token for the ORDER BY clause
+#define _step_ORDER_BY_     50 // ORDER BY clause
+#define _step_end_         500 // expect end
+
+    int step = _step_fieldlist_;
     
     // Variables for token sublists for expressions
     UcxList *exprstart = NULL;
@@ -510,33 +512,57 @@
         
         switch (step) {
         // too much input data
-        case 500:
+        case _step_end_:
             dav_parse_unexpected_token(stmt, token);
             goto ultrabreak;
         // optional clauses
-        case 530:
-            if (!sstrcasecmp(tokendata, S("where"))) {
-                step = 30;
+        case _step_expect_WWO_:
+            if (!sstrcasecmp(tokendata, S("with"))) {
+                step = _step_WITH_;
+                continue;
             }
             /* no break and no else*/
-        case 540:
-            if (!sstrcasecmp(tokendata, S("with"))) {
-                step = 40;
-            } else {
+        case _step_expect_WO:
+            if (!sstrcasecmp(tokendata, S("where"))) {
+                step = _step_WHERE_;
+                continue;
+            }
+            /* no break and no else*/
+        case _step_expect_O:
+            if (!sstrcasecmp(tokendata, S("order"))) {
+                step = _step_expect_BY;
+                continue;
+            } else { // last possible clause checked and not present
                 dav_parse_unexpected_token(stmt, token);
                 goto ultrabreak;
             }
             break;
-        case 541:
+        case _step_expect_BY:
+            if (!sstrcasecmp(tokendata, S("by"))) {
+                step = _step_ORDER_BY_;
+            } else {
+                stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN;
+                stmt->errormessage = ucx_sprintf(_expected_by,
+                    sfmtarg(tokendata)).ptr;
+                goto ultrabreak;
+            }
+            break;
+        case _step_comma_WITH_:
+            // a with clause may be continued with a comma
+            // or another clause may follow
             if (!sstrcmp(tokendata, S(","))) {
-                step = 40;
+                step = _step_WITH_;
+            } if (!sstrcasecmp(tokendata, S("where"))) {
+                step = _step_WHERE_;
+            } else if (!sstrcasecmp(tokendata, S("order"))) {
+                step = _step_expect_BY;
             } else {
                 dav_parse_unexpected_token(stmt, token);
                 goto ultrabreak;
             }
             break;
         // field list
-        case 10: {
+        case _step_fieldlist_: {
             _Bool fromkeyword = !sstrcasecmp(tokendata, S("from"));
             if (fromkeyword || !sstrcmp(tokendata, S(","))) {
                 if (exprstart) {
@@ -549,7 +575,7 @@
                 }
                 
                 if (fromkeyword) {
-                    step = 20;
+                    step = _step_FROM_;
                 }
             } else {
                 // collect tokens for field expression
@@ -563,7 +589,7 @@
             break;
         }
         // from clause
-        case 20: {
+        case _step_FROM_: {
             DavQLExpression *expr = dav_parse_expression(stmt, token, 1);
             stmt->path = expr->srctext;
             int exprtype = expr->type;
@@ -573,31 +599,37 @@
                 stmt->errormessage = ucx_sprintf(_identifier_expected,
                     sfmtarg(tokendata)).ptr;
             }
-            step = 530;
+            step = _step_expect_WWO_;
             break;
         }
-        // where clause
-        case 30:
-            step = 540;
-            break;
         // with clause
-        case 40: {
+        case _step_WITH_: {
             int withclause_result = dav_parse_with_clause(stmt, token);
             if (withclause_result < 0) {
                 stmt->errorcode = DAVQL_ERROR_INVALID;
                 stmt->errormessage = strdup(_parser_state);
             } else if (withclause_result > 0) {
-                step = 541;
+                step = _step_comma_WITH_;
             }
             break;
         }
+        // where clause
+        case _step_WHERE_:
+            // TODO: implement
+            step = _step_end_;
+            break;
+        // order by clause
+        case _step_ORDER_BY_:
+            // TODO: implement
+            step = _step_end_;
+            break;
         default:
             stmt->errorcode = DAVQL_ERROR_INVALID;
             stmt->errormessage = strdup(_parser_state);
         }
     }
     
-    if (!stmt->errorcode && step < 500) {
+    if (!stmt->errorcode && step < _step_end_) {
         stmt->errorcode = DAVQL_ERROR_UNEXPECTED_END;
         stmt->errormessage = strdup(_unexpected_end_msg);
     }

mercurial