added syntax tree display to debugger + expression parser saves source text in every node

Wed, 13 May 2015 21:12:41 +0200

author
Mike Becker <universe@uap-core.de>
date
Wed, 13 May 2015 21:12:41 +0200
changeset 109
020a5b5aa510
parent 108
0199f13c7fe2
child 110
53895e9a4bbb

added syntax tree display to debugger + expression parser saves source text in every node

libidav/davqlparser.c file | annotate | diff | comparison | revisions
--- a/libidav/davqlparser.c	Wed May 13 20:29:11 2015 +0200
+++ b/libidav/davqlparser.c	Wed May 13 21:12:41 2015 +0200
@@ -181,10 +181,26 @@
     }
 }
 
+static void dav_debug_ql_tree_print(DavQLExpression *expr, int depth) {
+    if (expr) {
+        if (expr->left) {
+            printf("%*c%s\n", depth, ' ', _map_operator(expr->op));
+            dav_debug_ql_tree_print(expr->left, depth+1);
+            dav_debug_ql_tree_print(expr->right, depth+1);
+        } else if (expr->type == DAVQL_UNARY) {
+            printf("%*c%s %.*s\n", depth, ' ', _map_operator(expr->op),
+                sfmtarg(expr->srctext));
+        } else {
+            printf("%*c%.*s\n", depth, ' ', sfmtarg(expr->srctext));
+        }
+    }
+}
+
 #define DQLD_CMD_Q     0
 #define DQLD_CMD_PS    1
 #define DQLD_CMD_PE    2
 #define DQLD_CMD_PF    3
+#define DQLD_CMD_PT    4
 #define DQLD_CMD_F    10
 #define DQLD_CMD_W    11
 #define DQLD_CMD_O    12
@@ -213,6 +229,8 @@
         return DQLD_CMD_PE;
     } else if (!strcmp(buffer, "pf\n")) {
         return DQLD_CMD_PF;
+    } else if (!strcmp(buffer, "pt\n")) {
+        return DQLD_CMD_PT;
     } else if (!strcmp(buffer, "l\n")) {
         return DQLD_CMD_L;
     } else if (!strcmp(buffer, "r\n")) {
@@ -257,6 +275,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_PT: dav_debug_ql_tree_print(examineexpr, 1); break;
         case DQLD_CMD_PF: dav_debug_ql_fnames_print(stmt); break;
         case DQLD_CMD_F:
             if (examineclause != DQLD_CMD_F) {
@@ -339,6 +358,7 @@
                 "q:   quit\n\n"
                 "\nExpression examination:\n"
                 "pe:  print expression information\n"
+                "pt:  print full syntax tree of current (sub-)expression\n"
                 "l:   enter left subtree\n"
                 "r:   enter right subtree\n");
             break;
@@ -584,6 +604,11 @@
         memcpy(expr->left, &left, sizeof(DavQLExpression));
         expr->right = malloc(sizeof(DavQLExpression));
         memcpy(expr->right, &right, sizeof(DavQLExpression));
+        
+        expr->srctext.ptr = expr->left->srctext.ptr;
+        expr->srctext.length = 
+            expr->right->srctext.ptr -
+            expr->left->srctext.ptr + expr->right->srctext.length;
     }
     
     return total_consumed;
@@ -627,6 +652,9 @@
 static int dav_parse_unary_expr(DavQLStatement* stmt, UcxList* token,
         DavQLExpression* expr) {
     
+    DavQLExpression* atom = expr;
+    expr->srctext.ptr = token_sstr(token).ptr;
+    
     int total_consumed = 0;
    
     // optional unary operator
@@ -640,7 +668,7 @@
             case '~': expr->op = DAVQL_NEG; break;
             }
             expr->left = calloc(sizeof(DavQLExpression), 1);
-            expr = expr->left;
+            atom = expr->left;
             total_consumed++;
             token = token->next;
         } else {
@@ -655,20 +683,26 @@
         // TODO: make it so (and don't forget CLOSEP)
     } else {
         // RULE:    FunctionCall
-        int consumed = dav_parse_funccall(stmt, token, expr);
+        int consumed = dav_parse_funccall(stmt, token, atom);
         if (consumed) {
             total_consumed += consumed;
         } else if (token_is(token, DAVQL_TOKEN_IDENTIFIER)) {
             // RULE:    Identifier
             total_consumed++;
-            expr->type = DAVQL_IDENTIFIER;
-            expr->srctext = token_sstr(token);
+            atom->type = DAVQL_IDENTIFIER;
+            atom->srctext = token_sstr(token);
         } else {
             // RULE:    Literal
-            total_consumed += dav_parse_literal(stmt, token, expr);
+            total_consumed += dav_parse_literal(stmt, token, atom);
         }
     }
     
+    // recover source text
+    if (atom != expr) {
+        expr->srctext.length =
+            atom->srctext.ptr - expr->srctext.ptr + atom->srctext.length;
+    }
+    
     
     return total_consumed;
 }
@@ -694,8 +728,6 @@
 static int dav_parse_expression(DavQLStatement* stmt, UcxList* token,
         DavQLExpression* expr) {
     
-    // TODO: save source text
-    
     return dav_parse_binary_expr(stmt, token, expr,
         dav_parse_multexpr,
         "+-", (int[]){DAVQL_ADD, DAVQL_SUB},

mercurial