Code

parser/analyzer: Migrate value expression checks.
authorSebastian Harl <sh@tokkee.org>
Wed, 6 May 2015 22:01:42 +0000 (00:01 +0200)
committerSebastian Harl <sh@tokkee.org>
Wed, 6 May 2015 22:01:42 +0000 (00:01 +0200)
The new parser and analyzer now pass the full test-suite of frontend/parser.

src/parser/analyzer.c
t/unit/parser/parser_test.c

index 2f79fc394c79dcf2f2fb65087942935db5efd59e..273463d8ce3a2037d2e7211dbb9113c9eec30676 100644 (file)
@@ -215,7 +215,7 @@ analyze_iter(int context, sdb_ast_iter_t *iter, sdb_strbuf_t *errbuf)
        if (iter->iter->type == SDB_AST_TYPE_TYPED)
                iter_context = SDB_AST_TYPED(iter->iter)->type;
 
-       if (analyze_node(context, iter->iter, errbuf))
+       if (analyze_node(iter_context, iter->iter, errbuf))
                return -1;
        if (iter->iter->data_type > 0)
                c.value.type = iter->iter->data_type & 0xff;
@@ -226,7 +226,7 @@ analyze_iter(int context, sdb_ast_iter_t *iter, sdb_strbuf_t *errbuf)
        assert((iter->expr->type == SDB_AST_TYPE_OPERATOR)
                        && (! SDB_AST_OP(iter->expr)->left));
        SDB_AST_OP(iter->expr)->left = SDB_AST_NODE(&c);
-       status = analyze_node(iter_context, iter->expr, errbuf);
+       status = analyze_node(context, iter->expr, errbuf);
        SDB_AST_OP(iter->expr)->left = NULL;
        if (status)
                return -1;
@@ -295,21 +295,62 @@ analyze_const(int __attribute__((unused)) context, sdb_ast_const_t *c,
 } /* analyze_const */
 
 static int
-analyze_value(int __attribute__((unused)) context, sdb_ast_value_t *v,
-               sdb_strbuf_t __attribute__((unused)) *errbuf)
+analyze_value(int context, sdb_ast_value_t *v, sdb_strbuf_t *errbuf)
 {
        if (v->type != SDB_ATTRIBUTE)
                SDB_AST_NODE(v)->data_type = SDB_FIELD_TYPE(v->type);
+
+       if ((v->type != SDB_ATTRIBUTE) && v->name) {
+               sdb_strbuf_sprintf(errbuf, "Invalid expression %s[%s]",
+                               SDB_FIELD_TO_NAME(v->type), v->name);
+               return -1;
+       }
+       else if ((v->type == SDB_ATTRIBUTE) && (! v->name)) {
+               sdb_strbuf_sprintf(errbuf, "Invalid expression attribute[] "
+                               "(missing name)");
+               return -1;
+       }
+
+       if ((context != SDB_ATTRIBUTE) && (v->type == SDB_FIELD_VALUE)) {
+               sdb_strbuf_sprintf(errbuf, "Invalid expression %s.value",
+                               SDB_FIELD_TO_NAME(v->type));
+               return -1;
+       }
        return 0;
 } /* analyze_value */
 
 static int
-analyze_typed(int __attribute__((unused)) context, sdb_ast_typed_t *t,
-               sdb_strbuf_t *errbuf)
+analyze_typed(int context, sdb_ast_typed_t *t, sdb_strbuf_t *errbuf)
 {
+       if ((t->expr->type != SDB_AST_TYPE_VALUE)
+                       && (t->expr->type != SDB_AST_TYPE_TYPED)) {
+               sdb_strbuf_sprintf(errbuf, "Invalid expression %s.%s",
+                               SDB_STORE_TYPE_TO_NAME(t->type),
+                               SDB_AST_TYPE_TO_STRING(t->expr));
+               return -1;
+       }
        if (analyze_node(t->type, t->expr, errbuf))
                return -1;
        SDB_AST_NODE(t)->data_type = t->expr->data_type;
+
+       if ((t->type != SDB_ATTRIBUTE) && (! VALID_OBJ_TYPE(t->type))) {
+               sdb_strbuf_sprintf(errbuf, "Invalid expression %#x.%s",
+                               t->type, SDB_AST_TYPE_TO_STRING(t->expr));
+               return -1;
+       }
+
+       /* self-references are allowed and services and metrics may reference
+        * their parent host; everything may reference attributes */
+       if ((context != t->type) && (context != UNSPEC_CONTEXT)
+                       && (((context != SDB_SERVICE) && (context != SDB_METRIC))
+                               || (t->type != SDB_HOST))
+                       && (t->type != SDB_ATTRIBUTE)) {
+               sdb_strbuf_sprintf(errbuf, "Invalid expression %s.%s in %s context",
+                               SDB_STORE_TYPE_TO_NAME(t->type),
+                               SDB_AST_TYPE_TO_STRING(t->expr),
+                               context == -1 ? "generic" : SDB_STORE_TYPE_TO_NAME(context));
+               return -1;
+       }
        return 0;
 } /* analyze_typed */
 
index d3667d1a4b5da8c40e2e0ae804736263e3f64e7c..f9049211440c513c342ce6c3769c7f160f8767bf 100644 (file)
@@ -416,14 +416,12 @@ struct {
          "field = 'a'",           -1, -1, 0, 0 },
        { "LIST metrics FILTER "
          "field = 'a'",           -1, -1, 0, 0 },
-#if 0
        { "LIST hosts FILTER "
          "value = 'a'",           -1, -1, 0, 0 },
        { "LIST services FILTER "
          "value = 'a'",           -1, -1, 0, 0 },
        { "LIST metrics FILTER "
          "value = 'a'",           -1, -1, 0, 0 },
-#endif
 
        /* type mismatches */
        { "LOOKUP hosts MATCHING "
@@ -523,7 +521,6 @@ struct {
        { "LOOKUP hosts MATCHING "
          "ANY 'patt' =~ 'p'",  -1,  -1, 0, 0 },
 
-#if 0
        /* invalid LIST commands */
        { "LIST",                -1, -1, 0, 0 },
        { "LIST foo",            -1, -1, 0, 0 },
@@ -604,7 +601,6 @@ struct {
          "2015-02-01",          -1, -1, 0, 0 },
        { "STORE metric attribute "
          "'metric'.'key' 123",  -1, -1, 0, 0 },
-#endif
 };
 
 START_TEST(test_parse)