fix cmd node
[protos/libecoli.git] / lib / ecoli_node_cmd.c
index f479c3f..743f3b9 100644 (file)
@@ -85,7 +85,6 @@ ec_node_cmd_eval_var(void **result, void *userctx,
 
        for (i = 0; i < node->len; i++) {
                id = ec_node_id(node->table[i]);
-               //printf("i=%d id=%s\n", i, id);
                if (id == NULL)
                        continue;
                if (strcmp(str, id))
@@ -104,7 +103,6 @@ ec_node_cmd_eval_var(void **result, void *userctx,
                        return -ENOMEM;
        }
 
-       //printf("eval var %s %p\n", str, eval);
        *result = eval;
 
        return 0;
@@ -165,22 +163,55 @@ ec_node_cmd_eval_bin_op(void **result, void *userctx, void *operand1,
 
        /* get parsed string vector, it should contain only one str */
        vec = ec_parsed_strvec(operator);
-       if (ec_strvec_len(vec) != 1)
+       if (ec_strvec_len(vec) > 1)
                return -EINVAL;
 
-       if (!strcmp(ec_strvec_val(vec, 0), "|")) {
-               out = EC_NODE_OR(EC_NO_ID, ec_node_clone(in1), ec_node_clone(in2));
-               if (out == NULL)
-                       return -EINVAL;
-               ec_node_free(in1);
-               ec_node_free(in2);
-               *result = out;
+       if (ec_strvec_len(vec) == 0) {
+               if (!strcmp(in1->type->name, "seq")) {
+                       if (ec_node_seq_add(in1, ec_node_clone(in2)) < 0)
+                               return -EINVAL;
+                       ec_node_free(in2);
+                       *result = in1;
+               } else {
+                       out = EC_NODE_SEQ(EC_NO_ID, ec_node_clone(in1),
+                                       ec_node_clone(in2));
+                       if (out == NULL)
+                               return -EINVAL;
+                       ec_node_free(in1);
+                       ec_node_free(in2);
+                       *result = out;
+               }
+       } else if (!strcmp(ec_strvec_val(vec, 0), "|")) {
+               if (!strcmp(in2->type->name, "or")) {
+                       if (ec_node_or_add(in2, ec_node_clone(in1)) < 0)
+                               return -EINVAL;
+                       ec_node_free(in1);
+                       *result = in2;
+               } else if (!strcmp(in1->type->name, "or")) {
+                       if (ec_node_or_add(in1, ec_node_clone(in2)) < 0)
+                               return -EINVAL;
+                       ec_node_free(in2);
+                       *result = in1;
+               } else {
+                       out = EC_NODE_OR(EC_NO_ID, ec_node_clone(in1),
+                                       ec_node_clone(in2));
+                       if (out == NULL)
+                               return -EINVAL;
+                       ec_node_free(in1);
+                       ec_node_free(in2);
+                       *result = out;
+               }
        } else if (!strcmp(ec_strvec_val(vec, 0), ",")) {
                if (!strcmp(in2->type->name, "subset")) {
                        if (ec_node_subset_add(in2, ec_node_clone(in1)) < 0)
                                return -EINVAL;
                        ec_node_free(in1);
                        *result = in2;
+               } else if (!strcmp(in1->type->name, "subset")) {
+                       if (ec_node_subset_add(in1, ec_node_clone(in2)) < 0)
+                               return -EINVAL;
+                       ec_node_free(in2);
+                       *result = in1;
                } else {
                        out = EC_NODE_SUBSET(EC_NO_ID, ec_node_clone(in1),
                                        ec_node_clone(in2));
@@ -250,7 +281,7 @@ static const struct ec_node_expr_eval_ops test_ops = {
 static int ec_node_cmd_build(struct ec_node_cmd *node)
 {
        struct ec_node *expr = NULL, *lex = NULL, *cmd = NULL;
-       struct ec_parsed *p = NULL, *child;
+       struct ec_parsed *p = NULL;
        void *result;
        int ret;
 
@@ -273,6 +304,9 @@ static int ec_node_cmd_build(struct ec_node_cmd *node)
        if (ret < 0)
                goto fail;
        ret = ec_node_expr_add_bin_op(expr, ec_node_str(EC_NO_ID, "|"));
+       if (ret < 0)
+               goto fail;
+       ret = ec_node_expr_add_bin_op(expr, ec_node("empty", EC_NO_ID));
        if (ret < 0)
                goto fail;
        ret = ec_node_expr_add_post_op(expr, ec_node_str(EC_NO_ID, "+"));
@@ -290,10 +324,9 @@ static int ec_node_cmd_build(struct ec_node_cmd *node)
        if (ret < 0)
                goto fail;
 
-       /* prepend a lexer and a "many" to the expression node */
+       /* prepend a lexer to the expression node */
        ret = -ENOMEM;
-       lex = ec_node_re_lex(EC_NO_ID,
-               ec_node_many(EC_NO_ID, ec_node_clone(expr), 1, 0));
+       lex = ec_node_re_lex(EC_NO_ID, ec_node_clone(expr));
        if (lex == NULL)
                goto fail;
 
@@ -324,29 +357,18 @@ static int ec_node_cmd_build(struct ec_node_cmd *node)
                goto fail;
        if (!ec_parsed_has_child(p))
                goto fail;
-       if (!ec_parsed_has_child(ec_parsed_get_first_child(p)))
-               goto fail;
 
-       ret = -ENOMEM;
-       cmd = ec_node("seq", EC_NO_ID);
-       if (cmd == NULL)
+       ret = ec_node_expr_eval(&result, expr, ec_parsed_get_first_child(p),
+                               &test_ops, node);
+       if (ret < 0)
                goto fail;
 
-       EC_PARSED_FOREACH_CHILD(child, ec_parsed_get_first_child(p)) {
-               ret = ec_node_expr_eval(&result, expr, child,
-                       &test_ops, node);
-               if (ret < 0)
-                       goto fail;
-               ret = ec_node_seq_add(cmd, result);
-               if (ret < 0)
-                       goto fail;
-       }
        ec_parsed_free(p);
        p = NULL;
 
        node->expr = expr;
        node->lex = lex;
-       node->cmd = cmd;
+       node->cmd = result;
 
        return 0;
 
@@ -507,7 +529,7 @@ static int ec_node_cmd_testcase(void)
        int ret = 0;
 
        node = EC_NODE_CMD(EC_NO_ID,
-               "command [option] (subset1, subset2, subset3) x|y z*",
+               "command [option] (subset1, subset2, subset3, subset4) x|y z*",
                ec_node_int("x", 0, 10, 10),
                ec_node_int("y", 20, 30, 10)
        );
@@ -516,6 +538,13 @@ static int ec_node_cmd_testcase(void)
                return -1;
        }
        ret |= EC_TEST_CHECK_PARSE(node, 2, "command", "1");
+       ret |= EC_TEST_CHECK_PARSE(node, 3, "command", "subset1", "1");
+       ret |= EC_TEST_CHECK_PARSE(node, 4, "command", "subset3", "subset2",
+                               "1");
+       ret |= EC_TEST_CHECK_PARSE(node, 5, "command", "subset2", "subset3",
+                               "subset1", "1");
+       ret |= EC_TEST_CHECK_PARSE(node, 6, "command", "subset3", "subset1",
+                               "subset4", "subset2", "4");
        ret |= EC_TEST_CHECK_PARSE(node, 2, "command", "23");
        ret |= EC_TEST_CHECK_PARSE(node, 3, "command", "option", "23");
        ret |= EC_TEST_CHECK_PARSE(node, 5, "command", "option", "23",
@@ -544,6 +573,17 @@ static int ec_node_cmd_testcase(void)
 
        ec_node_free(node);
 
+       node = EC_NODE_CMD(EC_NO_ID, "[foo [bar]]");
+       if (node == NULL) {
+               EC_LOG(EC_LOG_ERR, "cannot create node\n");
+               return -1;
+       }
+       ret |= EC_TEST_CHECK_PARSE(node, 0);
+       ret |= EC_TEST_CHECK_PARSE(node, 1, "foo");
+       ret |= EC_TEST_CHECK_PARSE(node, 2, "foo", "bar");
+       ret |= EC_TEST_CHECK_PARSE(node, 0, "x");
+       ec_node_free(node);
+
        return ret;
 }
 /* LCOV_EXCL_STOP */