X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=blobdiff_plain;f=src%2Ffrontend%2Fgrammar.y;h=92bfd1f5c60d2ab24d5e0b6f82b90e7e4ce73c71;hp=858c766b698aa124308a292f8ddcf90250127120;hb=3f0db5bd32f136de9e7cfa8250f0c20469261241;hpb=0503c3cea098a1ec25c35b4fb261039406d02d09 diff --git a/src/frontend/grammar.y b/src/frontend/grammar.y index 858c766..92bfd1f 100644 --- a/src/frontend/grammar.y +++ b/src/frontend/grammar.y @@ -63,34 +63,50 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); %locations %error-verbose %expect 0 -%name-prefix="sdb_fe_yy" +%name-prefix "sdb_fe_yy" %union { + const char *sstr; /* static string */ char *str; + sdb_data_t data; + sdb_llist_t *list; sdb_conn_node_t *node; sdb_store_matcher_t *m; + sdb_store_expr_t *expr; } %start statements %token SCANNER_ERROR -%token AND OR NOT WHERE - +%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 CONCAT + +/* NULL token */ +%token NULL_T + +%token FETCH LIST LOOKUP %token IDENTIFIER STRING -%token FETCH LIST LOOKUP + +%token INTEGER FLOAT /* Precedence (lowest first): */ %left OR %left AND -%left NOT +%right NOT %left CMP_EQUAL CMP_NEQUAL -%left CMP_REGEX CMP_NREGEX +%left CMP_LT CMP_LE CMP_GE CMP_GT +%nonassoc CMP_REGEX CMP_NREGEX +%left CONCAT +%nonassoc IS +%left '+' '-' +%left '*' '/' '%' %left '(' ')' %left '.' @@ -99,11 +115,21 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); fetch_statement list_statement lookup_statement - expression + condition %type matcher compare_matcher +%type expression + +%type op + +%type data + interval interval_elem + +%destructor { free($$); } +%destructor { sdb_object_deref(SDB_OBJ($$)); } + %% statements: @@ -113,7 +139,7 @@ statements: if (parser_mode != SDB_PARSE_DEFAULT) { sdb_fe_yyerror(&yylloc, scanner, YY_("syntax error, unexpected statement, " - "expecting expression")); + "expecting condition")); sdb_object_deref(SDB_OBJ($3)); YYABORT; } @@ -130,7 +156,7 @@ statements: if (parser_mode != SDB_PARSE_DEFAULT) { sdb_fe_yyerror(&yylloc, scanner, YY_("syntax error, unexpected statement, " - "expecting expression")); + "expecting condition")); sdb_object_deref(SDB_OBJ($1)); YYABORT; } @@ -141,12 +167,12 @@ statements: } } | - expression + condition { - /* only accept this in expression parse mode */ - if (! (parser_mode & SDB_PARSE_EXPR)) { + /* only accept this in condition parse mode */ + if (! (parser_mode & SDB_PARSE_COND)) { sdb_fe_yyerror(&yylloc, scanner, - YY_("syntax error, unexpected expression, " + YY_("syntax error, unexpected condition, " "expecting statement")); sdb_object_deref(SDB_OBJ($1)); YYABORT; @@ -203,12 +229,12 @@ list_statement: ; /* - * LOOKUP WHERE ; + * LOOKUP MATCHING [FILTER ]; * - * Returns detailed information about matching expression. + * Returns detailed information about matching condition. */ lookup_statement: - LOOKUP IDENTIFIER WHERE expression + LOOKUP IDENTIFIER MATCHING condition { /* TODO: support other types as well */ if (strcasecmp($2, "hosts")) { @@ -227,44 +253,43 @@ lookup_statement: $$->cmd = CONNECTION_LOOKUP; free($2); $2 = NULL; } + | + LOOKUP IDENTIFIER MATCHING condition FILTER condition + { + /* TODO: support other types as well */ + if (strcasecmp($2, "hosts")) { + char errmsg[strlen($2) + 32]; + snprintf(errmsg, sizeof(errmsg), + YY_("unknown table %s"), $2); + sdb_fe_yyerror(&yylloc, scanner, errmsg); + free($2); $2 = NULL; + sdb_object_deref(SDB_OBJ($4)); + YYABORT; + } + + $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, + conn_lookup_t, conn_lookup_destroy)); + CONN_LOOKUP($$)->matcher = CONN_MATCHER($4); + CONN_LOOKUP($$)->filter = CONN_MATCHER($6); + $$->cmd = CONNECTION_LOOKUP; + free($2); $2 = NULL; + } ; -expression: +condition: matcher { - sdb_store_matcher_t *m = $1; - if (! m) { + if (! $1) { /* TODO: improve error reporting */ sdb_fe_yyerror(&yylloc, scanner, - YY_("syntax error, invalid expression")); + YY_("syntax error, invalid condition")); YYABORT; } $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, - conn_node_matcher_t, conn_matcher_destroy)); + conn_matcher_t, conn_matcher_destroy)); $$->cmd = CONNECTION_EXPR; - - if ((M(m)->type == MATCHER_HOST) - || (M(m)->type == MATCHER_AND) - || (M(m)->type == MATCHER_OR)) - CONN_MATCHER($$)->matcher = m; - else if (M(m)->type == MATCHER_SERVICE) - CONN_MATCHER($$)->matcher = sdb_store_host_matcher(NULL, - /* name_re = */ NULL, /* service = */ m, - /* attr = */ NULL); - else if (M(m)->type == MATCHER_ATTR) - CONN_MATCHER($$)->matcher = sdb_store_host_matcher(NULL, - /* name_re = */ NULL, /* service = */ NULL, - /* attr = */ m); - else { - char errbuf[1024]; - snprintf(errbuf, sizeof(errbuf), - YY_("syntax error, unexpected matcher type %d"), - M(m)->type); - sdb_object_deref(SDB_OBJ($$)); - sdb_fe_yyerror(&yylloc, scanner, errbuf); - YYABORT; - } + CONN_MATCHER($$)->matcher = $1; } ; @@ -277,16 +302,21 @@ matcher: matcher AND matcher { $$ = sdb_store_con_matcher($1, $3); + sdb_object_deref(SDB_OBJ($1)); + sdb_object_deref(SDB_OBJ($3)); } | matcher OR matcher { $$ = sdb_store_dis_matcher($1, $3); + sdb_object_deref(SDB_OBJ($1)); + sdb_object_deref(SDB_OBJ($3)); } | NOT matcher { $$ = sdb_store_inv_matcher($2); + sdb_object_deref(SDB_OBJ($2)); } | compare_matcher @@ -301,38 +331,157 @@ matcher: * Parse matchers comparing object attributes with a value. */ compare_matcher: - IDENTIFIER '.' IDENTIFIER CMP_EQUAL STRING + ':' IDENTIFIER op expression + { + $$ = sdb_store_matcher_parse_field_cmp($2, $3, $4); + free($2); $2 = NULL; + sdb_object_deref(SDB_OBJ($4)); + } + | + IDENTIFIER op expression { - $$ = sdb_store_matcher_parse_cmp($1, $3, "=", $5); - /* TODO: simplify memory management in the parser */ + $$ = sdb_store_matcher_parse_cmp($1, NULL, $2, $3); free($1); $1 = NULL; - free($3); $3 = NULL; - free($5); $5 = NULL; + sdb_object_deref(SDB_OBJ($3)); } | - IDENTIFIER '.' IDENTIFIER CMP_NEQUAL STRING + IDENTIFIER '.' IDENTIFIER op expression { - $$ = sdb_store_matcher_parse_cmp($1, $3, "!=", $5); - /* TODO: simplify memory management in the parser */ + $$ = sdb_store_matcher_parse_cmp($1, $3, $4, $5); free($1); $1 = NULL; free($3); $3 = NULL; - free($5); $5 = NULL; + sdb_object_deref(SDB_OBJ($5)); } | - IDENTIFIER '.' IDENTIFIER CMP_REGEX STRING + IDENTIFIER '.' IDENTIFIER IS NULL_T { - $$ = sdb_store_matcher_parse_cmp($1, $3, "=~", $5); + $$ = sdb_store_matcher_parse_cmp($1, $3, "IS", NULL); free($1); $1 = NULL; free($3); $3 = NULL; - free($5); $5 = NULL; } | - IDENTIFIER '.' IDENTIFIER CMP_NREGEX STRING + IDENTIFIER '.' IDENTIFIER IS NOT NULL_T { - $$ = sdb_store_matcher_parse_cmp($1, $3, "!~", $5); + sdb_store_matcher_t *m; + m = sdb_store_matcher_parse_cmp($1, $3, "IS", NULL); free($1); $1 = NULL; free($3); $3 = NULL; - free($5); $5 = NULL; + + /* sdb_store_inv_matcher return NULL if m==NULL */ + $$ = sdb_store_inv_matcher(m); + sdb_object_deref(SDB_OBJ(m)); + } + ; + +expression: + '(' expression ')' + { + $$ = $2; + } + | + expression '+' expression + { + $$ = sdb_store_expr_create(SDB_DATA_ADD, $1, $3); + sdb_object_deref(SDB_OBJ($1)); $1 = NULL; + sdb_object_deref(SDB_OBJ($3)); $3 = NULL; + } + | + expression '-' expression + { + $$ = sdb_store_expr_create(SDB_DATA_SUB, $1, $3); + sdb_object_deref(SDB_OBJ($1)); $1 = NULL; + sdb_object_deref(SDB_OBJ($3)); $3 = NULL; + } + | + expression '*' expression + { + $$ = sdb_store_expr_create(SDB_DATA_MUL, $1, $3); + sdb_object_deref(SDB_OBJ($1)); $1 = NULL; + sdb_object_deref(SDB_OBJ($3)); $3 = NULL; + } + | + expression '/' expression + { + $$ = sdb_store_expr_create(SDB_DATA_DIV, $1, $3); + sdb_object_deref(SDB_OBJ($1)); $1 = NULL; + sdb_object_deref(SDB_OBJ($3)); $3 = NULL; + } + | + expression '%' expression + { + $$ = sdb_store_expr_create(SDB_DATA_MOD, $1, $3); + sdb_object_deref(SDB_OBJ($1)); $1 = NULL; + sdb_object_deref(SDB_OBJ($3)); $3 = NULL; + } + | + data + { + $$ = sdb_store_expr_constvalue(&$1); + sdb_data_free_datum(&$1); + } + ; + +op: + CMP_EQUAL { $$ = "="; } + | + CMP_NEQUAL { $$ = "!="; } + | + CMP_REGEX { $$ = "=~"; } + | + CMP_NREGEX { $$ = "!~"; } + | + CMP_LT { $$ = "<"; } + | + CMP_LE { $$ = "<="; } + | + CMP_GE { $$ = ">="; } + | + CMP_GT { $$ = ">"; } + ; + +data: + STRING { $$.type = SDB_TYPE_STRING; $$.data.string = $1; } + | + INTEGER { $$ = $1; } + | + FLOAT { $$ = $1; } + | + interval { $$ = $1; } + ; + +interval: + interval interval_elem + { + $$.data.datetime = $1.data.datetime + $2.data.datetime; + } + | + interval_elem { $$ = $1; } + ; + +interval_elem: + INTEGER IDENTIFIER + { + sdb_time_t unit = 1; + + unit = sdb_strpunit($2); + if (! unit) { + char errmsg[strlen($2) + 32]; + snprintf(errmsg, sizeof(errmsg), + YY_("invalid time unit %s"), $2); + sdb_fe_yyerror(&yylloc, scanner, errmsg); + free($2); $2 = NULL; + YYABORT; + } + free($2); $2 = NULL; + + $$.type = SDB_TYPE_DATETIME; + $$.data.datetime = (sdb_time_t)$1.data.integer * unit; + + if ($1.data.integer < 0) { + sdb_fe_yyerror(&yylloc, scanner, + YY_("syntax error, negative intervals not supported")); + YYABORT; + } } ;