# HG changeset patch # User Mike Becker # Date 1431544361 -7200 # Node ID 020a5b5aa5106f027f34b43549d76ca0cba5977a # Parent 0199f13c7fe2dd287016f729abe96ea4aa84b215 added syntax tree display to debugger + expression parser saves source text in every node diff -r 0199f13c7fe2 -r 020a5b5aa510 libidav/davqlparser.c --- 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},