From: Sebastian Harl Date: Sun, 26 Oct 2014 09:10:21 +0000 (+0100) Subject: frontend: Let scanner/parser know about object types and field names. X-Git-Tag: sysdb-0.6.0~54 X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=commitdiff_plain;h=ffd344cb441c2700d3c679f5e4a17b8dfc97d286 frontend: Let scanner/parser know about object types and field names. This allows to handle all known objects and fields as part of the grammar rather than manually parsing them and generating custom error messages. --- diff --git a/src/frontend/grammar.y b/src/frontend/grammar.y index fed30d2..4702562 100644 --- a/src/frontend/grammar.y +++ b/src/frontend/grammar.y @@ -48,7 +48,7 @@ */ static sdb_store_matcher_t * -name_iter_matcher(int m_type, const char *type_name, const char *cmp, +name_iter_matcher(int m_type, int type, const char *cmp, sdb_store_expr_t *expr); /* @@ -89,6 +89,7 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); %union { const char *sstr; /* static string */ char *str; + int integer; sdb_data_t data; sdb_time_t datetime; @@ -109,6 +110,10 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); %token CMP_LT CMP_LE CMP_GE CMP_GT ALL ANY IN %token CONCAT +%token HOST_T HOSTS_T SERVICE_T SERVICES_T METRIC_T METRICS_T +%token ATTRIBUTE_T ATTRIBUTES_T +%token NAME_T LAST_UPDATE_T AGE_T INTERVAL_T BACKEND_T + %token START END /* NULL token */ @@ -153,6 +158,10 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); %type expression +%type object_type_plural +%type iterable +%type field + %type cmp %type data @@ -272,19 +281,9 @@ statement: * Retrieve detailed information about a single host. */ fetch_statement: - FETCH IDENTIFIER STRING filter_clause + FETCH HOST_T STRING filter_clause { /* TODO: support other types as well */ - if (strcasecmp($2, "host")) { - char errmsg[strlen($2) + 32]; - snprintf(errmsg, sizeof(errmsg), - YY_("unknown data-source %s"), $2); - sdb_fe_yyerror(&yylloc, scanner, errmsg); - free($2); $2 = NULL; - free($3); $3 = NULL; - sdb_object_deref(SDB_OBJ($4)); - YYABORT; - } $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, conn_fetch_t, conn_fetch_destroy)); @@ -292,7 +291,6 @@ fetch_statement: CONN_FETCH($$)->name = $3; CONN_FETCH($$)->filter = CONN_MATCHER($4); $$->cmd = CONNECTION_FETCH; - free($2); $2 = NULL; } ; @@ -302,25 +300,13 @@ fetch_statement: * Returns a list of all hosts in the store. */ list_statement: - LIST IDENTIFIER filter_clause + LIST object_type_plural filter_clause { - int type = sdb_store_parse_object_type_plural($2); - if ((type < 0) || (type == SDB_ATTRIBUTE)) { - char errmsg[strlen($2) + 32]; - snprintf(errmsg, sizeof(errmsg), - YY_("unknown data-source %s"), $2); - sdb_fe_yyerror(&yylloc, scanner, errmsg); - free($2); $2 = NULL; - sdb_object_deref(SDB_OBJ($3)); - YYABORT; - } - $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, conn_list_t, conn_list_destroy)); - CONN_LIST($$)->type = type; + CONN_LIST($$)->type = $2; CONN_LIST($$)->filter = CONN_MATCHER($3); $$->cmd = CONNECTION_LIST; - free($2); $2 = NULL; } ; @@ -330,19 +316,9 @@ list_statement: * Returns detailed information about matching condition. */ lookup_statement: - LOOKUP IDENTIFIER matching_clause filter_clause + LOOKUP HOSTS_T matching_clause filter_clause { /* TODO: support other types as well */ - if (strcasecmp($2, "hosts")) { - char errmsg[strlen($2) + 32]; - snprintf(errmsg, sizeof(errmsg), - YY_("unknown data-source %s"), $2); - sdb_fe_yyerror(&yylloc, scanner, errmsg); - free($2); $2 = NULL; - sdb_object_deref(SDB_OBJ($3)); - sdb_object_deref(SDB_OBJ($4)); - YYABORT; - } $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, conn_lookup_t, conn_lookup_destroy)); @@ -350,7 +326,6 @@ lookup_statement: CONN_LOOKUP($$)->matcher = CONN_MATCHER($3); CONN_LOOKUP($$)->filter = CONN_MATCHER($4); $$->cmd = CONNECTION_LOOKUP; - free($2); $2 = NULL; } ; @@ -455,17 +430,15 @@ compare_matcher: sdb_object_deref(SDB_OBJ($3)); } | - ANY IDENTIFIER cmp expression + ANY iterable cmp expression { $$ = name_iter_matcher(MATCHER_ANY, $2, $3, $4); - free($2); $2 = NULL; sdb_object_deref(SDB_OBJ($4)); } | - ALL IDENTIFIER cmp expression + ALL iterable cmp expression { $$ = name_iter_matcher(MATCHER_ALL, $2, $3, $4); - free($2); $2 = NULL; sdb_object_deref(SDB_OBJ($4)); } | @@ -537,32 +510,21 @@ expression: sdb_object_deref(SDB_OBJ($3)); $3 = NULL; } | - IDENTIFIER + HOST_T { - 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); + $$ = sdb_store_expr_fieldvalue(SDB_FIELD_NAME); } | - IDENTIFIER '[' STRING ']' + field + { + $$ = sdb_store_expr_fieldvalue($1); + } + | + ATTRIBUTE_T '[' 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; } | @@ -573,6 +535,34 @@ expression: } ; +object_type_plural: + HOSTS_T { $$ = SDB_HOST; } + | + SERVICES_T { $$ = SDB_SERVICE; } + | + METRICS_T { $$ = SDB_METRIC; } + ; + +iterable: + SERVICE_T { $$ = SDB_SERVICE; } + | + METRIC_T { $$ = SDB_METRIC; } + | + ATTRIBUTE_T { $$ = SDB_ATTRIBUTE; } + ; + +field: + NAME_T { $$ = SDB_FIELD_NAME; } + | + LAST_UPDATE_T { $$ = SDB_FIELD_LAST_UPDATE; } + | + AGE_T { $$ = SDB_FIELD_AGE; } + | + INTERVAL_T { $$ = SDB_FIELD_INTERVAL; } + | + BACKEND_T { $$ = SDB_FIELD_BACKEND; } + ; + cmp: CMP_EQUAL { $$ = "="; } | @@ -656,10 +646,9 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg) } /* sdb_fe_yyerror */ static sdb_store_matcher_t * -name_iter_matcher(int m_type, const char *type_name, const char *cmp, +name_iter_matcher(int m_type, int type, 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; diff --git a/src/frontend/scanner.l b/src/frontend/scanner.l index b581e3d..c8d0dcb 100644 --- a/src/frontend/scanner.l +++ b/src/frontend/scanner.l @@ -51,22 +51,38 @@ static struct { const char *name; int id; } reserved_words[] = { - { "ALL", ALL }, - { "AND", AND }, - { "ANY", ANY }, - { "END", END }, - { "FETCH", FETCH }, - { "FILTER", FILTER }, - { "IN", IN }, - { "IS", IS }, - { "LIST", LIST }, - { "LOOKUP", LOOKUP }, - { "MATCHING", MATCHING }, - { "NOT", NOT }, - { "NULL", NULL_T }, - { "OR", OR }, - { "START", START }, - { "TIMESERIES", TIMESERIES }, + { "ALL", ALL }, + { "AND", AND }, + { "ANY", ANY }, + { "END", END }, + { "FETCH", FETCH }, + { "FILTER", FILTER }, + { "IN", IN }, + { "IS", IS }, + { "LIST", LIST }, + { "LOOKUP", LOOKUP }, + { "MATCHING", MATCHING }, + { "NOT", NOT }, + { "NULL", NULL_T }, + { "OR", OR }, + { "START", START }, + { "TIMESERIES", TIMESERIES }, + + /* object types */ + { "host", HOST_T }, + { "hosts", HOSTS_T }, + { "service", SERVICE_T }, + { "services", SERVICES_T }, + { "metric", METRIC_T }, + { "metrics", METRICS_T }, + { "attribute", ATTRIBUTE_T }, + { "attributes", ATTRIBUTES_T }, + /* queryable fields */ + { "name", NAME_T }, + { "last_update", LAST_UPDATE_T }, + { "age", AGE_T }, + { "interval", INTERVAL_T }, + { "backend", BACKEND_T }, }; void