X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Ffrontend%2Fgrammar.y;h=fed30d238f613fe92f301bd3a5ae695d26a10d9f;hb=a5b906eea3f380fbd838bd6ee6599c510317a3e0;hp=3a78d2490960a4f20cbe130f34e133852c08036f;hpb=2725e5e2024c134f05fd73baccda696572a24335;p=sysdb.git diff --git a/src/frontend/grammar.y b/src/frontend/grammar.y index 3a78d24..fed30d2 100644 --- a/src/frontend/grammar.y +++ b/src/frontend/grammar.y @@ -38,9 +38,23 @@ #include "utils/error.h" #include "utils/llist.h" +#include + #include #include +/* + * private helper functions + */ + +static sdb_store_matcher_t * +name_iter_matcher(int m_type, const char *type_name, const char *cmp, + sdb_store_expr_t *expr); + +/* + * public API + */ + int sdb_fe_yylex(YYSTYPE *yylval, YYLTYPE *yylloc, sdb_fe_yyscan_t yyscanner); @@ -56,6 +70,12 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); /* quick access to the parser mode */ #define parser_mode sdb_fe_yyget_extra(scanner)->mode +#define MODE_TO_STRING(m) \ + (((m) == SDB_PARSE_DEFAULT) ? "statement" \ + : ((m) == SDB_PARSE_COND) ? "condition" \ + : ((m) == SDB_PARSE_EXPR) ? "expression" \ + : "UNKNOWN") + %} %pure-parser @@ -86,7 +106,7 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); %token AND OR IS NOT MATCHING FILTER %token CMP_EQUAL CMP_NEQUAL CMP_REGEX CMP_NREGEX -%token CMP_LT CMP_LE CMP_GE CMP_GT +%token CMP_LT CMP_LE CMP_GE CMP_GT ALL ANY IN %token CONCAT %token START END @@ -109,6 +129,7 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); %left CMP_EQUAL CMP_NEQUAL %left CMP_LT CMP_LE CMP_GE CMP_GT %nonassoc CMP_REGEX CMP_NREGEX +%nonassoc IN %left CONCAT %nonassoc IS %left '+' '-' @@ -142,17 +163,20 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); %destructor { free($$); } %destructor { sdb_object_deref(SDB_OBJ($$)); } +%destructor { sdb_data_free_datum(&$$); } %% statements: statements ';' statement { - /* only accept this in default parse mode */ + /* only accepted in default parse mode */ if (parser_mode != SDB_PARSE_DEFAULT) { - sdb_fe_yyerror(&yylloc, scanner, + char errmsg[1024]; + snprintf(errmsg, sizeof(errmsg), YY_("syntax error, unexpected statement, " - "expecting condition")); + "expecting %s"), MODE_TO_STRING(parser_mode)); + sdb_fe_yyerror(&yylloc, scanner, errmsg); sdb_object_deref(SDB_OBJ($3)); YYABORT; } @@ -165,11 +189,13 @@ statements: | statement { - /* only accept this in default parse mode */ + /* only accepted in default parse mode */ if (parser_mode != SDB_PARSE_DEFAULT) { - sdb_fe_yyerror(&yylloc, scanner, + char errmsg[1024]; + snprintf(errmsg, sizeof(errmsg), YY_("syntax error, unexpected statement, " - "expecting condition")); + "expecting %s"), MODE_TO_STRING(parser_mode)); + sdb_fe_yyerror(&yylloc, scanner, errmsg); sdb_object_deref(SDB_OBJ($1)); YYABORT; } @@ -182,11 +208,13 @@ statements: | condition { - /* only accept this in condition parse mode */ + /* only accepted in condition parse mode */ if (! (parser_mode & SDB_PARSE_COND)) { - sdb_fe_yyerror(&yylloc, scanner, + char errmsg[1024]; + snprintf(errmsg, sizeof(errmsg), YY_("syntax error, unexpected condition, " - "expecting statement")); + "expecting %s"), MODE_TO_STRING(parser_mode)); + sdb_fe_yyerror(&yylloc, scanner, errmsg); sdb_object_deref(SDB_OBJ($1)); YYABORT; } @@ -196,6 +224,31 @@ statements: sdb_object_deref(SDB_OBJ($1)); } } + | + expression + { + /* only accepted in expression parse mode */ + if (! (parser_mode & SDB_PARSE_EXPR)) { + char errmsg[1024]; + snprintf(errmsg, sizeof(errmsg), + YY_("syntax error, unexpected expression, " + "expecting %s"), MODE_TO_STRING(parser_mode)); + sdb_fe_yyerror(&yylloc, scanner, errmsg); + sdb_object_deref(SDB_OBJ($1)); + YYABORT; + } + + if ($1) { + sdb_conn_node_t *n; + n = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, + conn_expr_t, conn_expr_destroy)); + n->cmd = CONNECTION_EXPR; + CONN_EXPR(n)->expr = $1; + + sdb_llist_append(pt, SDB_OBJ(n)); + sdb_object_deref(SDB_OBJ(n)); + } + } ; statement: @@ -252,7 +305,7 @@ list_statement: LIST IDENTIFIER filter_clause { int type = sdb_store_parse_object_type_plural($2); - if (type < 0) { + if ((type < 0) || (type == SDB_ATTRIBUTE)) { char errmsg[strlen($2) + 32]; snprintf(errmsg, sizeof(errmsg), YY_("unknown data-source %s"), $2); @@ -355,7 +408,7 @@ condition: $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, conn_matcher_t, conn_matcher_destroy)); - $$->cmd = CONNECTION_EXPR; + $$->cmd = CONNECTION_MATCHER; CONN_MATCHER($$)->matcher = $1; } ; @@ -392,51 +445,47 @@ matcher: } ; -/* - * . - * - * Parse matchers comparing object attributes with a value. - */ compare_matcher: - '.' IDENTIFIER cmp expression + expression cmp expression { - $$ = sdb_store_matcher_parse_field_cmp($2, $3, $4); + sdb_store_matcher_op_cb cb = sdb_store_parse_matcher_op($2); + assert(cb); /* else, the grammar accepts invalid 'cmp' */ + $$ = cb($1, $3); + sdb_object_deref(SDB_OBJ($1)); + sdb_object_deref(SDB_OBJ($3)); + } + | + ANY IDENTIFIER cmp expression + { + $$ = name_iter_matcher(MATCHER_ANY, $2, $3, $4); free($2); $2 = NULL; sdb_object_deref(SDB_OBJ($4)); } | - IDENTIFIER cmp expression + ALL IDENTIFIER cmp expression { - $$ = sdb_store_matcher_parse_cmp($1, NULL, $2, $3); - free($1); $1 = NULL; - sdb_object_deref(SDB_OBJ($3)); + $$ = name_iter_matcher(MATCHER_ALL, $2, $3, $4); + free($2); $2 = NULL; + sdb_object_deref(SDB_OBJ($4)); } | - IDENTIFIER '[' IDENTIFIER ']' cmp expression + expression IS NULL_T { - $$ = sdb_store_matcher_parse_cmp($1, $3, $5, $6); - free($1); $1 = NULL; - free($3); $3 = NULL; - sdb_object_deref(SDB_OBJ($6)); + $$ = sdb_store_isnull_matcher($1); + sdb_object_deref(SDB_OBJ($1)); } | - IDENTIFIER '[' IDENTIFIER ']' IS NULL_T + expression IS NOT NULL_T { - $$ = sdb_store_matcher_parse_cmp($1, $3, "IS", NULL); - free($1); $1 = NULL; - free($3); $3 = NULL; + $$ = sdb_store_isnnull_matcher($1); + sdb_object_deref(SDB_OBJ($1)); } | - IDENTIFIER '[' IDENTIFIER ']' IS NOT NULL_T + expression IN expression { - sdb_store_matcher_t *m; - m = sdb_store_matcher_parse_cmp($1, $3, "IS", NULL); - free($1); $1 = NULL; - free($3); $3 = NULL; - - /* sdb_store_inv_matcher return NULL if m==NULL */ - $$ = sdb_store_inv_matcher(m); - sdb_object_deref(SDB_OBJ(m)); + $$ = sdb_store_in_matcher($1, $3); + sdb_object_deref(SDB_OBJ($1)); + sdb_object_deref(SDB_OBJ($3)); } ; @@ -481,13 +530,42 @@ expression: sdb_object_deref(SDB_OBJ($3)); $3 = NULL; } | - '.' IDENTIFIER + expression CONCAT expression { - int field = sdb_store_parse_field_name($2); - free($2); $2 = NULL; + $$ = sdb_store_expr_create(SDB_DATA_CONCAT, $1, $3); + sdb_object_deref(SDB_OBJ($1)); $1 = NULL; + sdb_object_deref(SDB_OBJ($3)); $3 = NULL; + } + | + IDENTIFIER + { + int field; + /* TODO: this only works as long as queries + * are limited to hosts */ + if (!strcasecmp($1, "host")) + field = SDB_FIELD_NAME; + else + field = sdb_store_parse_field_name($1); + free($1); $1 = NULL; $$ = sdb_store_expr_fieldvalue(field); } | + IDENTIFIER '[' STRING ']' + { + if (strcasecmp($1, "attribute")) { + char errmsg[strlen($1) + strlen($3) + 32]; + snprintf(errmsg, sizeof(errmsg), + YY_("unknown value %s[%s]"), $1, $3); + sdb_fe_yyerror(&yylloc, scanner, errmsg); + free($1); $1 = NULL; + free($3); $3 = NULL; + YYABORT; + } + $$ = sdb_store_expr_attrvalue($3); + free($1); $1 = NULL; + free($3); $3 = NULL; + } + | data { $$ = sdb_store_expr_constvalue(&$1); @@ -577,5 +655,32 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg) sdb_log(SDB_LOG_ERR, "frontend: parse error: %s", msg); } /* sdb_fe_yyerror */ +static sdb_store_matcher_t * +name_iter_matcher(int m_type, const char *type_name, const char *cmp, + sdb_store_expr_t *expr) +{ + int type = sdb_store_parse_object_type(type_name); + sdb_store_matcher_op_cb cb = sdb_store_parse_matcher_op(cmp); + sdb_store_expr_t *e; + sdb_store_matcher_t *m, *tmp = NULL; + assert(cb); + + /* TODO: this only works as long as queries + * are limited to hosts */ + if (type == SDB_HOST) { + return NULL; + } + + e = sdb_store_expr_fieldvalue(SDB_FIELD_NAME); + m = cb(e, expr); + if (m_type == MATCHER_ANY) + tmp = sdb_store_any_matcher(type, m); + else if (m_type == MATCHER_ALL) + tmp = sdb_store_all_matcher(type, m); + sdb_object_deref(SDB_OBJ(m)); + sdb_object_deref(SDB_OBJ(e)); + return tmp; +} /* name_iter_matcher */ + /* vim: set tw=78 sw=4 ts=4 noexpandtab : */