added order by clause to grammar + moved with clause right after the from clause

Mon, 13 Apr 2015 19:04:46 +0200

author
Mike Becker <universe@uap-core.de>
date
Mon, 13 Apr 2015 19:04:46 +0200
changeset 92
e073cf4afc6a
parent 91
838b427267bb
child 93
2176ffbf1346

added order by clause to grammar + moved with clause right after the from clause

libidav/davqlparser.c file | annotate | diff | comparison | revisions
libidav/davqlparser.h file | annotate | diff | comparison | revisions
--- 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);
     }
--- a/libidav/davqlparser.h	Sat Apr 04 22:20:39 2015 +0200
+++ b/libidav/davqlparser.h	Mon Apr 13 19:04:46 2015 +0200
@@ -54,12 +54,12 @@
  * Enumeration of possible expression operators.
  */
 typedef enum {
-    DAVQL_NOOP,
+    DAVQL_NOOP, DAVQL_CALL, DAVQL_ARGLIST, // internal representations
     DAVQL_ADD, DAVQL_SUB, DAVQL_MUL, DAVQL_DIV,
-    DAVQL_AND, DAVQL_OR, DAVQL_XOR, DAVQL_NEG,
-    DAVQL_NOT, DAVQL_LAND, DAVQL_LOR, DAVQL_LXOR,
+    DAVQL_AND, DAVQL_OR, DAVQL_XOR, DAVQL_NEG,  // airthmetic
+    DAVQL_NOT, DAVQL_LAND, DAVQL_LOR, DAVQL_LXOR, // logical
     DAVQL_EQ, DAVQL_NEQ, DAVQL_LT, DAVQL_GT, DAVQL_LE, DAVQL_GE,
-    DAVQL_LIKE, DAVQL_UNLIKE
+    DAVQL_LIKE, DAVQL_UNLIKE // comparisons
 } davqloperator_t;
 
 /**
@@ -110,7 +110,8 @@
  *            | FunctionCall | Identifier | Literal
  *            | "(", Expression, ")";
  * 
- * FunctionCall    = Identifier, "(", Expression, ")";
+ * FunctionCall    = Identifier, "(", ArgumentList, ")";
+ * ArgumentList    = Expression, {",", Expression};
  * Identifier      = IdentifierChar - ?Digit?, {IdentifierChar}
  *                 | "`", ?Character?, {?Character?}, "`";
  * IdentifierChar  = ?Character - (" "|",")?;
@@ -134,11 +135,14 @@
  *                  | "-";
  * FieldExpression  = Identifier
  *                  | Expression, " as ", String;
- * SetExpressions   = SetExpression, {",", {SetExpressions};
+ * SetExpressions   = SetExpression, {",", SetExpressions};
  * SetExpression    = Identifier, "=", Expression;
  * 
  * WithClause = "depth", "=", (Number | "infinity");
  * 
+ * OrderByClause    = OrderByCriterion, {",", OrderByCriterion};
+ * OrderByCriterion = (Identifier | Number), [" asc"|" desc"];
+ * 
  * </pre>
  * 
  * Note: mandatory spaces are part of the grammar. But you may also insert an
@@ -149,16 +153,17 @@
  * <pre>
  * GetStatement = "get ", FieldExpressions,
  * " from ", Identifier,
+ * [" with ", WithClause],
  * [" where ", LogicalExpression],
- * [" with ", WithClause];
+ * [" order by ", OrderByClause];
   * </pre>
  * 
  * <b>SET:</b>
  * <pre>
  * "set ",SetExpressions,
  * " at ", Identifier,
- * (" where ", LogicalExpression) | " anywhere",
- * [" with ", WithClause];
+ * [" with ", WithClause],
+ * (" where ", LogicalExpression) | " anywhere";
  * </pre>
  * 
  */

mercurial