X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Ffrontend%2Fgrammar.y;h=ed4de830fc64cc0f091a52c43624fd325ee96e17;hb=a077fb06b0cf27ca51477c76d5520d0c814af8df;hp=26c8c1b046ddaa8df0af9c66dd2d2588a842a972;hpb=61bffa0a9775d926425c1a28bee49d341d1237b4;p=sysdb.git diff --git a/src/frontend/grammar.y b/src/frontend/grammar.y index 26c8c1b..ed4de83 100644 --- a/src/frontend/grammar.y +++ b/src/frontend/grammar.y @@ -66,31 +66,47 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); %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 %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 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,20 @@ 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 + +%destructor { free($$); } +%destructor { sdb_object_deref(SDB_OBJ($$)); } + %% statements: @@ -113,7 +138,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 +155,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 +166,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 +228,12 @@ list_statement: ; /* - * LOOKUP WHERE ; + * LOOKUP MATCHING ; * - * 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")) { @@ -229,13 +254,13 @@ lookup_statement: } ; -expression: +condition: matcher { if (! $1) { /* TODO: improve error reporting */ sdb_fe_yyerror(&yylloc, scanner, - YY_("syntax error, invalid expression")); + YY_("syntax error, invalid condition")); YYABORT; } @@ -284,44 +309,116 @@ matcher: * Parse matchers comparing object attributes with a value. */ compare_matcher: - IDENTIFIER '.' IDENTIFIER CMP_EQUAL STRING + 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; } + ; -/* 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)