# HG changeset patch # User Mike Becker # Date 1430584370 -7200 # Node ID e9ae1318a5591d2f8e45a394860df61a53acc6b9 # Parent 95a215337b53c9ec81138065d4020c2332296e3f reworked expression grammar (removed left recursion) + added field names to debugger + fixed bug when WITH-clause was the last clause in a statement diff -r 95a215337b53 -r e9ae1318a559 libidav/davqlparser.c --- 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); + } } } diff -r 95a215337b53 -r e9ae1318a559 libidav/davqlparser.h --- 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: * *
- * 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"