UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2018 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #ifndef DAVQLPARSER_H 30 #define DAVQLPARSER_H 31 32 #ifdef __cplusplus 33 extern "C" { 34 #endif 35 36 #include <stdint.h> 37 #include <cx/string.h> 38 #include <cx/list.h> 39 40 /** 41 * Enumeration of possible statement types. 42 */ 43 typedef enum {DAVQL_ERROR, DAVQL_SELECT, DAVQL_SET} davqltype_t; 44 45 /** 46 * Enumeration of possible token classes. 47 */ 48 typedef enum { 49 DAVQL_TOKEN_INVALID, DAVQL_TOKEN_KEYWORD, 50 DAVQL_TOKEN_IDENTIFIER, DAVQL_TOKEN_FMTSPEC, 51 DAVQL_TOKEN_STRING, DAVQL_TOKEN_NUMBER, DAVQL_TOKEN_TIMESTAMP, 52 DAVQL_TOKEN_COMMA, DAVQL_TOKEN_OPENP, DAVQL_TOKEN_CLOSEP, 53 DAVQL_TOKEN_OPERATOR, DAVQL_TOKEN_END 54 } davqltokenclass_t; 55 56 /** 57 * Enumeration of possible expression types. 58 */ 59 typedef enum { 60 DAVQL_UNDEFINED_TYPE, 61 DAVQL_NUMBER, DAVQL_STRING, DAVQL_TIMESTAMP, DAVQL_IDENTIFIER, 62 DAVQL_UNARY, DAVQL_BINARY, DAVQL_LOGICAL, DAVQL_FUNCCALL 63 } davqlexprtype_t; 64 65 /** 66 * Enumeration of possible expression operators. 67 */ 68 typedef enum { 69 DAVQL_NOOP, DAVQL_CALL, DAVQL_ARGLIST, // internal representations 70 DAVQL_ADD, DAVQL_SUB, DAVQL_MUL, DAVQL_DIV, 71 DAVQL_AND, DAVQL_OR, DAVQL_XOR, DAVQL_NEG, // airthmetic 72 DAVQL_NOT, DAVQL_LAND, DAVQL_LOR, DAVQL_LXOR, // logical 73 DAVQL_EQ, DAVQL_NEQ, DAVQL_LT, DAVQL_GT, DAVQL_LE, DAVQL_GE, 74 DAVQL_LIKE, DAVQL_UNLIKE // comparisons 75 } davqloperator_t; 76 77 typedef struct DavQLToken DavQLToken; 78 struct DavQLToken { 79 davqltokenclass_t tokenclass; 80 cxstring value; 81 DavQLToken *prev; 82 DavQLToken *next; 83 }; 84 85 /** 86 * An expression within a DAVQL query. 87 */ 88 typedef struct _davqlexpr DavQLExpression; 89 90 /** 91 * The structure for type DavQLExpression. 92 */ 93 struct _davqlexpr { 94 /** 95 * The original expression text. 96 * Contains the literal value, if type is LITERAL. 97 */ 98 cxstring srctext; 99 /** 100 * The expression type. 101 */ 102 davqlexprtype_t type; 103 /** 104 * Operator. 105 */ 106 davqloperator_t op; 107 /** 108 * Left or single operand. 109 * <code>NULL</code> for literals or identifiers. 110 */ 111 DavQLExpression *left; 112 /** 113 * Right operand. 114 * <code>NULL</code> for literals, identifiers or unary expressions. 115 */ 116 DavQLExpression *right; 117 }; 118 119 /** 120 * A tuple representing an order criterion. 121 */ 122 typedef struct { 123 /** 124 * The column. 125 */ 126 DavQLExpression *column; 127 /** 128 * True, if the result shall be sorted descending, false otherwise. 129 * Default is false (ascending). 130 */ 131 _Bool descending; 132 } DavQLOrderCriterion; 133 134 /** 135 * A tuple representing a field. 136 */ 137 typedef struct { 138 /** 139 * The field name. 140 * <ul> 141 * <li>SELECT: the identifier or an alias name</li> 142 * <li>SET: the identifier</li> 143 * </ul> 144 */ 145 cxstring name; 146 /** 147 * The field expression. 148 * <ul> 149 * <li>SELECT: the queried property (identifier) or an expression</li> 150 * <li>SET: the expression for the value to be set</li> 151 * </ul> 152 */ 153 DavQLExpression *expr; 154 } DavQLField; 155 156 /** 157 * Query statement object. 158 * Contains the binary information about the parsed query. 159 * 160 * The grammar for a DavQLStatement is: 161 * 162 * <pre> 163 * Keyword = "select" | "set" | "from" | "at" | "as" 164 * | "where" | "anywhere" | "like" | "unlike" 165 * | "and" | "or" | "not" | "xor" | "with" | "infinity" 166 * | "order" | "by" | "asc" | "desc"; 167 * 168 * Expression = AddExpression; 169 * AddExpression = MultExpression, [AddOperator, AddExpression]; 170 * MultExpression = BitwiseExpression, [MultOperator, MultExpression]; 171 * BitwiseExpression = UnaryExpression, [BitwiseOperator, BitwiseExpression]; 172 * UnaryExpression = [UnaryOperator], (ParExpression | AtomicExpression); 173 * AtomicExpression = FunctionCall | Identifier | Literal; 174 * ParExpression = "(", Expression, ")"; 175 * 176 * BitwiseOperator = "&" | "|" | "^"; 177 * MultOperator = "*" | "/"; 178 * AddOperator = "+" | "-"; 179 * UnaryOperator = "+" | "-" | "~"; 180 * 181 * FunctionCall = Identifier, "(", [ArgumentList], ")"; 182 * ArgumentList = Expression, {",", Expression}; 183 * Identifier = IdentifierChar - ?Digit?, {IdentifierChar} 184 * | "`", ?Character? - "`", {?Character? - "`"}, "`"; 185 * IdentifierChar = ?Character? - (" "|","); 186 * Literal = Number | String | Timestamp; 187 * Number = ?Digit?, {?Digit?} | "%d"; 188 * String = "'", {?Character? - "'" | "'''"} , "'" | "%s"; 189 * Timestamp = "%t"; // TODO: maybe introduce a real literal 190 * 191 * LogicalExpression = BooleanExpression, [LogicalOperator, LogicalExpression]; 192 * BooleanExpression = "not ", BooleanExpression 193 * | "(", LogicalExpression, ")" 194 * | BooleanPrimary; 195 * BooleanPrimary = Expression, (" like " | " unlike "), String 196 * | Expression, Comparison, Expression 197 * | FunctionCall | Identifier; 198 * 199 * LogicalOperator = " and " | " or " | " xor "; 200 * Comparison = | "=" | "<" | ">" | "<=" | ">=" | "!="; 201 * 202 * FieldExpressions = "-" 203 * | "*", {",", NamedField} 204 * | FieldExpression, {",", FieldExpression}; 205 * FieldExpression = NamedField | Identifier; 206 * NamedField = Expression, " as ", Identifier; 207 * 208 * Assignments = Assignment, {",", Assignment}; 209 * Assignment = Identifier, "=", Expression; 210 * 211 * Path = String 212 * | "/", [PathNode, {"/", PathNode}], ["/"]; 213 * PathNode = {{?Character? - "/"} - Keyword}; 214 * 215 * WithClause = "depth", "=", (Number | "infinity"); 216 * 217 * OrderByClause = OrderByCriterion, {",", OrderByCriterion}; 218 * OrderByCriterion = (Identifier | Number), [" asc"|" desc"]; 219 * 220 * </pre> 221 * 222 * Note: mandatory spaces are part of the grammar. But you may also insert an 223 * arbitrary amount of optional spaces between two symbols if they are not part 224 * of an literal, identifier or the path. 225 * 226 * <b>SELECT:</b> 227 * <pre> 228 * SelectStatement = "select ", FieldExpressions, 229 * " from ", Path, 230 * [" with ", WithClause], 231 * [(" where ", LogicalExpression) | " anywhere"], 232 * [" order by ", OrderByClause]; 233 * </pre> 234 * 235 * <b>SET:</b> 236 * <pre> 237 * SetStatement = "set ",Assignments, 238 * " at ", Path, 239 * [" with ", WithClause], 240 * (" where ", LogicalExpression) | " anywhere"; 241 * </pre> 242 * 243 */ 244 typedef struct { 245 /** 246 * The original query text. 247 */ 248 cxstring srctext; 249 /** 250 * The statement type. 251 */ 252 davqltype_t type; 253 /** 254 * Error code, if any error occurred. Zero otherwise. 255 */ 256 int errorcode; 257 /** 258 * Error message, if any error occurred. 259 */ 260 char* errormessage; 261 /** 262 * The list of DavQLFields. 263 */ 264 CxList* fields; 265 /** 266 * A string that denotes the queried path. 267 */ 268 cxstring path; 269 /** 270 * Logical expression for selection. 271 * <code>NULL</code>, if there is no where clause. 272 */ 273 DavQLExpression* where; 274 /** 275 * The list of DavQLOrderCriterions. 276 * This is <code>NULL</code> for SET queries and may be <code>NULL</code> 277 * if the result doesn't need to be sorted. 278 */ 279 CxList* orderby; 280 /** 281 * The recursion depth for the statement. 282 * Defaults to 1. 283 * Magic numbers are DAV_DEPTH_INFINITY for infinity and 284 * DAV_DEPTH_PLACEHOLDER for a placeholder. 285 */ 286 int depth; 287 /** 288 * A list of all required arguments 289 */ 290 CxList* args; 291 } DavQLStatement; 292 293 /** Infinity recursion depth for a DavQLStatement. */ 294 #define DAV_DEPTH_INFINITY -1 295 296 /** Depth needs to be specified at runtime. */ 297 #define DAV_DEPTH_PLACEHOLDER -2 298 299 /** Unexpected token. */ 300 #define DAVQL_ERROR_UNEXPECTED_TOKEN 1 301 302 /** A token has been found, for which no token class is applicable. */ 303 #define DAVQL_ERROR_INVALID_TOKEN 2 304 305 /** A token that has been expected was not found. */ 306 #define DAVQL_ERROR_MISSING_TOKEN 11 307 308 /** An expression has been expected, but was not found. */ 309 #define DAVQL_ERROR_MISSING_EXPR 12 310 311 /** A closed parenthesis ')' is missing. */ 312 #define DAVQL_ERROR_MISSING_PAR 13 313 314 /** An assignment operator '=' is missing. */ 315 #define DAVQL_ERROR_MISSING_ASSIGN 14 316 317 /** The type of the expression could not be determined. */ 318 #define DAVQL_ERROR_INVALID_EXPR 21 319 320 /** An operator has been found for an unary expression, but it is invalid. */ 321 #define DAVQL_ERROR_INVALID_UNARY_OP 22 322 323 /** An operator has been found for a logical expression, but it is invalid. */ 324 #define DAVQL_ERROR_INVALID_LOGICAL_OP 23 325 326 /** Invalid format specifier. */ 327 #define DAVQL_ERROR_INVALID_FMTSPEC 24 328 329 /** A string has been expected. */ 330 #define DAVQL_ERROR_INVALID_STRING 25 331 332 /** The order criterion is invalid (must be an identifier or field index). */ 333 #define DAVQL_ERROR_INVALID_ORDER_CRITERION 26 334 335 /** The depth is invalid. */ 336 #define DAVQL_ERROR_INVALID_DEPTH 101 337 338 /** Nothing about the statement seems legit. */ 339 #define DAVQL_ERROR_INVALID -1 340 341 /** A call to malloc or calloc failed. */ 342 #define DAVQL_ERROR_OUT_OF_MEMORY -2 343 344 /** 345 * Starts an interactive debugger for a DavQLStatement. 346 * 347 * @param stmt the statement to debug 348 */ 349 void dav_debug_statement(DavQLStatement *stmt); 350 351 /** 352 * Parses a statement. 353 * @param stmt the sstr_t containing the statement 354 * @return a DavQLStatement object 355 */ 356 DavQLStatement* dav_parse_statement(cxstring stmt); 357 358 /** 359 * Implicitly converts a cstr to a sstr_t and calls dav_parse_statement. 360 */ 361 #define dav_parse_cstr_statement(stmt) dav_parse_statement(cx_str(stmt)) 362 363 /** 364 * Frees a DavQLStatement. 365 * @param stmt the statement object to free 366 */ 367 void dav_free_statement(DavQLStatement *stmt); 368 369 #ifdef __cplusplus 370 } 371 #endif 372 373 #endif /* DAVQLPARSER_H */ 374 375