Skip to content

Commit

Permalink
frontend: Let scanner/parser know about object types and field names.
Browse files Browse the repository at this point in the history
This allows to handle all known objects and fields as part of the grammar
rather than manually parsing them and generating custom error messages.
  • Loading branch information
tokkee committed Oct 26, 2014
1 parent a5b906e commit ffd344c
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 80 deletions.
117 changes: 53 additions & 64 deletions src/frontend/grammar.y
Expand Up @@ -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);

/*
Expand Down Expand Up @@ -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;
Expand All @@ -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 */
Expand Down Expand Up @@ -153,6 +158,10 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg);

%type <expr> expression

%type <integer> object_type_plural
%type <integer> iterable
%type <integer> field

%type <sstr> cmp

%type <data> data
Expand Down Expand Up @@ -272,27 +281,16 @@ 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));
CONN_FETCH($$)->type = SDB_HOST;
CONN_FETCH($$)->name = $3;
CONN_FETCH($$)->filter = CONN_MATCHER($4);
$$->cmd = CONNECTION_FETCH;
free($2); $2 = NULL;
}
;

Expand All @@ -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;
}
;

Expand All @@ -330,27 +316,16 @@ list_statement:
* Returns detailed information about <type> 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));
CONN_LOOKUP($$)->type = SDB_HOST;
CONN_LOOKUP($$)->matcher = CONN_MATCHER($3);
CONN_LOOKUP($$)->filter = CONN_MATCHER($4);
$$->cmd = CONNECTION_LOOKUP;
free($2); $2 = NULL;
}
;

Expand Down Expand Up @@ -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));
}
|
Expand Down Expand Up @@ -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;
}
|
Expand All @@ -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 { $$ = "="; }
|
Expand Down Expand Up @@ -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;
Expand Down
48 changes: 32 additions & 16 deletions src/frontend/scanner.l
Expand Up @@ -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
Expand Down

0 comments on commit ffd344c

Please sign in to comment.