X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Ffrontend%2Fgrammar.y;h=450a20f34218ef1df4db9e713bb3b0247cddc0bb;hb=8e7384947ee57bbbe58e210be4f6ec04ef8ff508;hp=876f48a04a2d718864020473304e30d34ca0848a;hpb=ae32792b881853979265e41b49866be9ea2d6b2c;p=sysdb.git diff --git a/src/frontend/grammar.y b/src/frontend/grammar.y index 876f48a..450a20f 100644 --- a/src/frontend/grammar.y +++ b/src/frontend/grammar.y @@ -27,14 +27,21 @@ %{ -#include "frontend/connection.h" +#include "frontend/connection-private.h" #include "frontend/parser.h" #include "frontend/grammar.h" +#include "core/store.h" +#include "core/store-private.h" + #include "utils/error.h" #include "utils/llist.h" #include +#include + +int +sdb_fe_yylex(YYSTYPE *yylval, YYLTYPE *yylloc, sdb_fe_yyscan_t yyscanner); sdb_fe_yyextra_t * sdb_fe_yyget_extra(sdb_fe_yyscan_t scanner); @@ -45,6 +52,9 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); /* quick access to the current parse tree */ #define pt sdb_fe_yyget_extra(scanner)->parsetree +/* quick access to the parser mode */ +#define parser_mode sdb_fe_yyget_extra(scanner)->mode + %} %pure-parser @@ -56,26 +66,58 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); %name-prefix="sdb_fe_yy" %union { + char *str; + sdb_llist_t *list; sdb_conn_node_t *node; + + sdb_store_matcher_t *m; } %start statements %token SCANNER_ERROR -%token IDENTIFIER -%token LIST +%token AND OR NOT WHERE + +%token CMP_EQUAL CMP_NEQUAL CMP_REGEX CMP_NREGEX + +%token IDENTIFIER STRING +%token FETCH LIST LOOKUP + +/* Precedence (lowest first): */ +%left OR +%left AND +%left NOT +%left CMP_EQUAL CMP_NEQUAL +%left CMP_REGEX CMP_NREGEX +%left '(' ')' +%left '.' %type statements %type statement + fetch_statement list_statement + lookup_statement + expression + +%type matcher + compare_matcher %% statements: statements ';' statement { + /* only accept this in default parse mode */ + if (parser_mode != SDB_PARSE_DEFAULT) { + sdb_fe_yyerror(&yylloc, scanner, + YY_("syntax error, unexpected statement, " + "expecting expression")); + sdb_object_deref(SDB_OBJ($3)); + YYABORT; + } + if ($3) { sdb_llist_append(pt, SDB_OBJ($3)); sdb_object_deref(SDB_OBJ($3)); @@ -84,6 +126,32 @@ statements: | statement { + /* only accept this in default parse mode */ + if (parser_mode != SDB_PARSE_DEFAULT) { + sdb_fe_yyerror(&yylloc, scanner, + YY_("syntax error, unexpected statement, " + "expecting expression")); + sdb_object_deref(SDB_OBJ($1)); + YYABORT; + } + + if ($1) { + sdb_llist_append(pt, SDB_OBJ($1)); + sdb_object_deref(SDB_OBJ($1)); + } + } + | + expression + { + /* only accept this in expression parse mode */ + if (! (parser_mode & SDB_PARSE_EXPR)) { + sdb_fe_yyerror(&yylloc, scanner, + YY_("syntax error, unexpected expression, " + "expecting statement")); + sdb_object_deref(SDB_OBJ($1)); + YYABORT; + } + if ($1) { sdb_llist_append(pt, SDB_OBJ($1)); sdb_object_deref(SDB_OBJ($1)); @@ -92,24 +160,169 @@ statements: ; statement: + fetch_statement + | list_statement | + lookup_statement + | /* empty */ { $$ = NULL; } ; +/* + * FETCH ; + * + * Retrieve detailed information about a single host. + */ +fetch_statement: + FETCH STRING + { + $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, + conn_fetch_t, conn_fetch_destroy)); + CONN_FETCH($$)->name = strdup($2); + $$->cmd = CONNECTION_FETCH; + free($2); $2 = NULL; + } + ; + +/* + * LIST; + * + * Returns a list of all hosts in the store. + */ list_statement: LIST { - $$ = sdb_object_create_T(/* name = */ NULL, sdb_conn_node_t); - ((sdb_conn_node_t *)$$)->cmd = CONNECTION_LIST; + $$ = SDB_CONN_NODE(sdb_object_create_T(/* name = */ NULL, + sdb_conn_node_t)); + $$->cmd = CONNECTION_LIST; + } + ; + +/* + * LOOKUP WHERE ; + * + * Returns detailed information about matching expression. + */ +lookup_statement: + LOOKUP IDENTIFIER WHERE expression + { + /* 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); + $$->cmd = CONNECTION_LOOKUP; + free($2); $2 = NULL; + } + ; + +expression: + matcher + { + if (! $1) { + /* TODO: improve error reporting */ + sdb_fe_yyerror(&yylloc, scanner, + YY_("syntax error, invalid expression")); + YYABORT; + } + + $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, + conn_node_matcher_t, conn_matcher_destroy)); + $$->cmd = CONNECTION_EXPR; + CONN_MATCHER($$)->matcher = $1; + } + ; + +matcher: + '(' matcher ')' + { + $$ = $2; + } + | + 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 + { + $$ = $1; + } + ; + +/* + * . + * + * Parse matchers comparing object attributes with a value. + */ +compare_matcher: + IDENTIFIER '.' IDENTIFIER CMP_EQUAL STRING + { + $$ = sdb_store_matcher_parse_cmp($1, $3, "=", $5); + /* TODO: simplify memory management in the parser */ + free($1); $1 = NULL; + free($3); $3 = NULL; + free($5); $5 = NULL; + } + | + IDENTIFIER '.' IDENTIFIER CMP_NEQUAL STRING + { + $$ = sdb_store_matcher_parse_cmp($1, $3, "!=", $5); + /* TODO: simplify memory management in the parser */ + free($1); $1 = NULL; + free($3); $3 = NULL; + free($5); $5 = NULL; + } + | + IDENTIFIER '.' IDENTIFIER CMP_REGEX STRING + { + $$ = sdb_store_matcher_parse_cmp($1, $3, "=~", $5); + free($1); $1 = NULL; + free($3); $3 = NULL; + free($5); $5 = NULL; + } + | + IDENTIFIER '.' IDENTIFIER CMP_NREGEX STRING + { + $$ = sdb_store_matcher_parse_cmp($1, $3, "!~", $5); + free($1); $1 = NULL; + free($3); $3 = NULL; + free($5); $5 = NULL; } ; %% +/* XXX: on parse errors, allocated objects, strings, etc. need to be freed */ + void sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg) {