libidav/davqlparser.c

changeset 107
a0903d2d8e3e
parent 106
9cec78f23cbf
child 108
0199f13c7fe2
--- a/libidav/davqlparser.c	Wed May 13 12:00:54 2015 +0200
+++ b/libidav/davqlparser.c	Wed May 13 20:18:36 2015 +0200
@@ -356,11 +356,13 @@
 #define _error_unhandled "unhandled error " _error_context
 #define _error_unexpected_token "unexpected token " _error_context
 #define _error_invalid_token "invalid token " _error_context
-#define _error_missing_from "missing FROM keyword " _error_context
-#define _error_missing_by "missing BY keyword " _error_context
+#define _error_missing_path "expected path " _error_context
+#define _error_missing_from "expecting FROM keyword " _error_context
+#define _error_missing_by "expecting BY keyword " _error_context
 #define _error_invalid_depth "invalid depth " _error_context
 #define _error_missing_expr "missing expression " _error_context
 #define _error_invalid_unary_op "invalid unary operator "  _error_context
+#define _error_invalid_fmtspec "invalid format specifier " _error_context
 
 #define token_sstr(token) (((DavQLToken*)(token)->data)->value)
 
@@ -539,7 +541,11 @@
         DavQLExpression* expr, exprparser_f parseL, char* opc, int* opv,
         exprparser_f parseR) {
     
-        int total_consumed = 0, consumed;
+    if (!token) {
+        return 0;
+    }
+    
+    int total_consumed = 0, consumed;
     
     // save temporarily on stack (copy to heap later on)
     DavQLExpression left, right;
@@ -553,8 +559,9 @@
     total_consumed += consumed;
     token = ucx_list_get(token, consumed);
 
-    char *op = strchr(opc, token_sstr(token).ptr[0]); // locate operator
-    if (token_is(token, DAVQL_TOKEN_OPERATOR) && op) {
+    char *op;
+    if (token_is(token, DAVQL_TOKEN_OPERATOR) &&
+            (op = strchr(opc, token_sstr(token).ptr[0]))) {
         expr->op = opv[op-opc];
         total_consumed++;
         token = token->next;
@@ -580,13 +587,46 @@
     return total_consumed;
 }
 
+static int dav_parse_literal(DavQLStatement* stmt, UcxList* token,
+        DavQLExpression* expr) {
+    
+    expr->srctext = token_sstr(token);
+    if (token_is(token, DAVQL_TOKEN_NUMBER)) {
+        expr->type = DAVQL_NUMBER;
+    } else if (token_is(token, DAVQL_TOKEN_STRING)) {
+        expr->type = DAVQL_STRING;
+    } else if (token_is(token, DAVQL_TOKEN_TIMESTAMP)) {
+        expr->type = DAVQL_TIMESTAMP;
+    } else if (token_is(token, DAVQL_TOKEN_FMTSPEC)
+            && expr->srctext.length == 2) {
+        switch (expr->srctext.ptr[1]) {
+        case 'd': expr->type = DAVQL_NUMBER; break;
+        case 's': expr->type = DAVQL_STRING; break;
+        case 't': expr->type = DAVQL_TIMESTAMP; break;
+        default:
+            dav_error_in_context(DAVQL_ERROR_INVALID_FMTSPEC,
+                _error_invalid_fmtspec, stmt, token);
+            return 0;
+        }
+    } else {
+        return 0;
+    }
+    
+    return 1;
+}
+
+static int dav_parse_funccall(DavQLStatement* stmt, UcxList* token,
+        DavQLExpression* expr) {
+    
+    // TODO: make it so
+    return 0;
+}
 
 static int dav_parse_unary_expr(DavQLStatement* stmt, UcxList* token,
         DavQLExpression* expr) {
     
     int total_consumed = 0;
-    DavQLExpression *litexpr = expr;
-    
+   
     // optional unary operator
     if (token_is(token, DAVQL_TOKEN_OPERATOR)) {
         char *op = strchr("+-~", token_sstr(token).ptr[0]);
@@ -598,7 +638,7 @@
             case '~': expr->op = DAVQL_NEG; break;
             }
             expr->left = calloc(sizeof(DavQLExpression), 1);
-            litexpr = expr->left;
+            expr = expr->left;
             total_consumed++;
             token = token->next;
         } else {
@@ -613,17 +653,18 @@
         // TODO: make it so (and don't forget CLOSEP)
     } else {
         // RULE:    FunctionCall
-        // TODO: make it so
-        
-        // RULE:    Identifier
-        /*else*/ if (token_is(token, DAVQL_TOKEN_IDENTIFIER)) {
+        int consumed = dav_parse_funccall(stmt, token, expr);
+        if (consumed) {
+            total_consumed += consumed;
+        } else if (token_is(token, DAVQL_TOKEN_IDENTIFIER)) {
+            // RULE:    Identifier
             total_consumed++;
-            litexpr->type = DAVQL_IDENTIFIER;
-            litexpr->srctext = token_sstr(token);
+            expr->type = DAVQL_IDENTIFIER;
+            expr->srctext = token_sstr(token);
+        } else {
+            // RULE:    Literal
+            total_consumed += dav_parse_literal(stmt, token, expr);
         }
-        
-        // RULE:    Literal
-        // TODO: make it so
     }
     
     
@@ -659,11 +700,6 @@
         dav_parse_expression);
 }
 
-static int dav_parse_format_spec(DavQLStatement* stmt, UcxList* token) {
-    
-    return 0;
-}
-
 static int dav_parse_fieldlist(DavQLStatement *stmt, UcxList *token) {
     
     // RULE:    "-"
@@ -819,8 +855,14 @@
             stmt->path.length = toksstr.ptr-stmt->path.ptr+toksstr.length;
             tokens = tokens->next;
         }
-    } else if (token_is(tokens, DAVQL_TOKEN_FMTSPEC)) {
-        // TODO: make it so
+    } else if (token_is(tokens, DAVQL_TOKEN_FMTSPEC) &&
+            tokenvalue_is(tokens, "%s")) {
+        stmt->path = token_sstr(tokens);
+        tokens = tokens->next;
+    } else {
+        dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
+            _error_missing_path, stmt, tokens);
+        return;
     }
     
     // Consume with clause (if any)

mercurial