reworked expression grammar (removed left recursion) + added field names to debugger + fixed bug when WITH-clause was the last clause in a statement

Sat, 02 May 2015 18:32:50 +0200

author
Mike Becker <universe@uap-core.de>
date
Sat, 02 May 2015 18:32:50 +0200
changeset 102
e9ae1318a559
parent 101
95a215337b53
child 103
b29692d5f7a7

reworked expression grammar (removed left recursion) + added field names to debugger + fixed bug when WITH-clause was the last clause in a statement

libidav/davqlparser.c file | annotate | diff | comparison | revisions
libidav/davqlparser.h file | annotate | diff | comparison | revisions
--- a/libidav/davqlparser.c	Sat May 02 11:00:28 2015 +0200
+++ b/libidav/davqlparser.c	Sat May 02 18:32:50 2015 +0200
@@ -89,6 +89,15 @@
     }
 }
 
+static void dav_debug_ql_fnames_print(DavQLStatement *stmt) {
+    printf("Field names: ");
+    UCX_FOREACH(field, stmt->fields) {
+        DavQLField *f = field->data;
+        printf("%.*s, ", sfmtarg(f->name));
+    }
+    printf("\b\b  \b\b\n");
+}
+
 static void dav_debug_ql_stmt_print(DavQLStatement *stmt) {
     // Basic information
     size_t fieldcount = ucx_list_size(stmt->fields);
@@ -105,12 +114,14 @@
     if (specialfield) {
         fieldcount--;
     }
-    printf("Statement: %.*s\nType: %s\nField count: %zu %s\nPath: %.*s\n"
-        "Has where clause: %s\n",
+    printf("Statement: %.*s\nType: %s\nField count: %zu %s\n",
         sfmtarg(stmt->srctext),
         _map_querytype(stmt->type),
         fieldcount,
-        _map_specialfield(specialfield),
+        _map_specialfield(specialfield));
+    
+    dav_debug_ql_fnames_print(stmt);
+    printf("Path: %.*s\nHas where clause: %s\n",
         sfmtarg(stmt->path),
         stmt->where ? "yes" : "no");
     
@@ -171,6 +182,7 @@
 #define DQLD_CMD_Q     0
 #define DQLD_CMD_PS    1
 #define DQLD_CMD_PE    2
+#define DQLD_CMD_PF    3
 #define DQLD_CMD_F    10
 #define DQLD_CMD_W    11
 #define DQLD_CMD_O    12
@@ -197,6 +209,8 @@
         return DQLD_CMD_PS;
     } else if (!strcmp(buffer, "pe\n")) {
         return DQLD_CMD_PE;
+    } else if (!strcmp(buffer, "pf\n")) {
+        return DQLD_CMD_PF;
     } else if (!strcmp(buffer, "l\n")) {
         return DQLD_CMD_L;
     } else if (!strcmp(buffer, "r\n")) {
@@ -241,6 +255,7 @@
         case DQLD_CMD_Q: return;
         case DQLD_CMD_PS: dav_debug_ql_stmt_print(stmt); break;
         case DQLD_CMD_PE: dav_debug_ql_expr_print(examineexpr); break;
+        case DQLD_CMD_PF: dav_debug_ql_fnames_print(stmt); break;
         case DQLD_CMD_F:
             if (examineclause != DQLD_CMD_F) {
                 examineclause = DQLD_CMD_F;
@@ -313,6 +328,7 @@
                 "ps:  print statement information\n"
                 "o:   examine order by clause\n"
                 "f:   examine field list\n"
+                "pf:  print field names\n"
                 "w:   examine where clause\n"
                 "n:   examine next expression "
                     "(in order by clause or field list)\n"
@@ -536,9 +552,10 @@
 #define _step_fieldlist_    10 // field list
 #define _step_FROM_         20 // FROM clause
 #define _step_WITH_         30 // WITH clause
+#define _step_WITHopt_     530 // expecting more WITH details or end
 #define _step_WHERE_        40 // WHERE clause
-#define _step_ORDER_BYopt_ 552 // expecting more ORDER BY details or end
 #define _step_ORDER_BY_     50 // ORDER BY clause
+#define _step_ORDER_BYopt_ 550 // expecting more ORDER BY details or end
 #define _step_end_         500 // expect end
 
 struct fieldlist_parser_state {
@@ -725,7 +742,7 @@
      * 0: key
      * 1: =
      * 2: value
-     * 3: comma or new clause
+     * 3: comma or new clause or end
      */
     int step;
     /*
@@ -802,7 +819,7 @@
             break;
         }
         state->step = 3;
-        return _step_WITH_; // continue parsing WITH clause
+        return _step_WITHopt_; // continue parsing WITH clause
     case 3:
         // a with clause may be continued with a comma
         // or another clause may follow
@@ -906,6 +923,20 @@
     free(crit);
 }
 
+/**
+ * Semantic analysis of a get statement.
+ * @param stmt the statement to analyze.
+ */
+static void dav_analyze_get_statement(DavQLStatement *stmt) {
+    // TODO: make it so
+}
+
+
+/**
+ * Parser of a get statement.
+ * @param stmt the statement object that shall contain the syntax tree
+ * @param tokens the token list
+ */
 static void dav_parse_get_statement(DavQLStatement *stmt, UcxList *tokens) {
     stmt->type = DAVQL_GET;
 
@@ -937,7 +968,8 @@
             break;
         }
         // with clause
-        case _step_WITH_: {
+        case _step_WITH_:
+        case _step_WITHopt_: {
             step = dav_parse_with_clause(stmt, token, &state_with);
             break;
         }
@@ -962,9 +994,13 @@
         }
     }
     
-    if (!stmt->errorcode && step < _step_end_) {
-        stmt->errorcode = DAVQL_ERROR_UNEXPECTED_END;
-        stmt->errormessage = strdup(_unexpected_end_msg);
+    if (!stmt->errorcode) {
+        if (step < _step_end_) {
+            stmt->errorcode = DAVQL_ERROR_UNEXPECTED_END;
+            stmt->errormessage = strdup(_unexpected_end_msg);
+        } else {
+            dav_analyze_get_statement(stmt);
+        }
     }
 }
 
--- a/libidav/davqlparser.h	Sat May 02 11:00:28 2015 +0200
+++ b/libidav/davqlparser.h	Sat May 02 18:32:50 2015 +0200
@@ -141,10 +141,18 @@
  * The grammar for a DavQLStatement is:
  * 
  * <pre>
- * Expression = Expression, BinaryOperator, Expression
- *            | UnaryOperator, Expression
- *            | FunctionCall | Identifier | Literal
- *            | "(", Expression, ")";
+ * Expression        = AddExpression;
+ * AddExpression     = MultExpression, [AddOperator, AddExpression];
+ * MultExpression    = BitwiseExpression, [MultOperator, MultExpression];
+ * BitwiseExpression = UnaryExpression, [BitwiseOperator, BitwiseExpression];
+ * UnaryExpression   = [UnaryOperator], (AtomicExpression | ParExpression);
+ * AtomicExpression  = FunctionCall | Identifier | Literal;
+ * ParExpression     = "(", Expression, ")";
+ * 
+ * BitwiseOperator = "&" | "|" | "^";
+ * MultOperator    = "*" | "/";
+ * AddOperator     = "+" | "-";
+ * UnaryOperator   = "+" | "-" | "~";
  * 
  * FunctionCall    = Identifier, "(", ArgumentList, ")";
  * ArgumentList    = Expression, {",", Expression};
@@ -156,14 +164,13 @@
  * String          = "'", {?Character? - "'" | "'''"} , "'" | "%s";
  * Timestamp       = "%t"; // TODO: maybe introduce a real literal 
  * 
- * LogicalExpression = LogicalExpression, LogicalOperator, LogicalExpression
- *                   | "not ", LogicalExpression
- *                   | Expression, Comparison, Expression
+ * LogicalExpression = "not ", LogicalExpression
+ *                   | "(", LogicalExpression, ")"
+ *                   | BooleanExpression, [LogicalOperator, LogicalExpression];
+ * BooleanExpression = Expression, Comparison, Expression
  *                   | Expression, (" like " | " unlike "), String
- *                   | "(", LogicalExpression, ")";
+ *                   | FunctionCall | Identifier;
  * 
- * UnaryOperator   = "-" | "~";
- * BinaryOperator  = "+" | "-" | "*" | "/" | "&" | "|" | "^";
  * LogicalOperator = " and " | " or " | " xor ";
  * Comparison      = | "=" | "<" | ">" | "<=" | ">=" | "!=";
  * 
@@ -172,7 +179,7 @@
  *                  | "-";
  * FieldExpression  = Identifier
  *                  | Expression, " as ", Identifier;
- * SetExpressions   = SetExpression, {",", SetExpressions};
+ * SetExpressions   = SetExpression, {",", SetExpression};
  * SetExpression    = Identifier, "=", Expression;
  * 
  * Path = "%s"

mercurial