Sat, 02 May 2015 18:32:50 +0200
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"