summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: bcdab45)
raw | patch | inline | side by side (parent: bcdab45)
author | Sebastian Harl <sh@tokkee.org> | |
Sun, 27 Jul 2014 22:27:12 +0000 (00:27 +0200) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Sun, 27 Jul 2014 22:27:12 +0000 (00:27 +0200) |
For now, the expressions are used in place of a datum but the parser will
actually evaluate the expression before passing it on to the store during
lookup. Since expressions currently cover constant results only, this is not a
limitation for now.
actually evaluate the expression before passing it on to the store during
lookup. Since expressions currently cover constant results only, this is not a
limitation for now.
src/frontend/grammar.y | patch | blob | history | |
src/frontend/scanner.l | patch | blob | history | |
t/unit/frontend/parser_test.c | patch | blob | history |
diff --git a/src/frontend/grammar.y b/src/frontend/grammar.y
index e0d8e7ecc46136b01cb84546ba1d3e11d7fb9e2b..0afbd9edb32461c00eb36f2248d0259204b1d930 100644 (file)
--- a/src/frontend/grammar.y
+++ b/src/frontend/grammar.y
sdb_conn_node_t *node;
sdb_store_matcher_t *m;
+ sdb_store_expr_t *expr;
}
%start statements
%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
%left CMP_EQUAL CMP_NEQUAL
%left CMP_LT CMP_LE CMP_GE CMP_GT
%nonassoc CMP_REGEX CMP_NREGEX
+%left CONCAT
%nonassoc IS
+%left '+' '-'
+%left '*' '/' '%'
%left '(' ')'
%left '.'
%type <m> matcher
compare_matcher
+%type <expr> expression
+
%type <sstr> op
%type <data> data
%destructor { free($$); } <str>
-%destructor { sdb_object_deref(SDB_OBJ($$)); } <node> <m>
+%destructor { sdb_object_deref(SDB_OBJ($$)); } <node> <m> <expr>
%%
* Parse matchers comparing object attributes with a value.
*/
compare_matcher:
- IDENTIFIER op data
+ IDENTIFIER op expression
{
- $$ = sdb_store_matcher_parse_cmp($1, NULL, $2, &$3);
+ sdb_data_t value = SDB_DATA_INIT;
+ if (sdb_store_expr_eval($3, &value)) {
+ sdb_object_deref(SDB_OBJ($3));
+ free($1); $1 = NULL;
+ sdb_fe_yyerror(&yylloc, scanner,
+ YY_("syntax error, failed to evaluate expression"));
+ YYABORT;
+ }
+ sdb_object_deref(SDB_OBJ($3));
+ $$ = sdb_store_matcher_parse_cmp($1, NULL, $2, &value);
free($1); $1 = NULL;
- sdb_data_free_datum(&$3);
+ sdb_data_free_datum(&value);
}
|
- IDENTIFIER '.' IDENTIFIER op data
+ IDENTIFIER '.' IDENTIFIER op expression
{
- $$ = sdb_store_matcher_parse_cmp($1, $3, $4, &$5);
+ sdb_data_t value = SDB_DATA_INIT;
+ if (sdb_store_expr_eval($5, &value)) {
+ sdb_object_deref(SDB_OBJ($5));
+ free($1); $1 = NULL;
+ free($3); $3 = NULL;
+ sdb_fe_yyerror(&yylloc, scanner,
+ YY_("syntax error, failed to evaluate expression"));
+ YYABORT;
+ }
+ sdb_object_deref(SDB_OBJ($5));
+ $$ = sdb_store_matcher_parse_cmp($1, $3, $4, &value);
free($1); $1 = NULL;
free($3); $3 = NULL;
- sdb_data_free_datum(&$5);
+ sdb_data_free_datum(&value);
}
|
IDENTIFIER '.' IDENTIFIER IS NULL_T
}
;
+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 { $$ = "="; }
|
diff --git a/src/frontend/scanner.l b/src/frontend/scanner.l
index ef30682b45b837f8cb931f1e7257f7568ddd3f2b..5e80368d532872198edb7ea7bfb45dd60a9f0225 100644 (file)
--- a/src/frontend/scanner.l
+++ b/src/frontend/scanner.l
\<= { return CMP_LE; }
\>= { return CMP_GE; }
\> { return CMP_GT; }
+\|\| { return CONCAT; }
. { /* XXX: */ return yytext[0]; }
index 3ca27ba19ffb47ec637575469b398c7d85d10961..59de563f760c74e291ec47998081b03344c442c4 100644 (file)
"12.4", -1, 1, CONNECTION_LOOKUP },
{ "LOOKUP hosts MATCHING "
"attribute.foo <= "
- "12.", -1, 1, CONNECTION_LOOKUP },
+ "12. + .3", -1, 1, CONNECTION_LOOKUP },
{ "LOOKUP hosts MATCHING "
"attribute.foo >= "
".4", -1, 1, CONNECTION_LOOKUP },
"attribute.foo = "
"0x12", -1, -1, 0 },
+ /* invalid expressions */
+ { "LOOKUP hosts MATCHING "
+ "attribute.foo = "
+ "1.23 + 'foo'", -1, -1, 0 },
+
/* comments */
{ "/* some comment */", -1, 0, 0 },
{ "-- another comment", -1, 0, 0 },