From 144efdc4345fe32e956a721c6e5f93e3a03e9e9e Mon Sep 17 00:00:00 2001 From: Olivier Matz Date: Thu, 8 Mar 2018 21:52:45 +0100 Subject: [PATCH] fix cmd node --- lib/ecoli_node_cmd.c | 53 +++++++++++++++++++++++++------------------ lib/ecoli_node_expr.c | 14 ++++++++++++ lib/ecoli_node_seq.h | 1 - lib/ecoli_parsed.c | 7 ------ lib/ecoli_test.h | 1 + lib/main.c | 7 +++--- lib/todo.txt | 22 ++++++++++++++++++ 7 files changed, 72 insertions(+), 33 deletions(-) diff --git a/lib/ecoli_node_cmd.c b/lib/ecoli_node_cmd.c index f479c3f..ba1469b 100644 --- a/lib/ecoli_node_cmd.c +++ b/lib/ecoli_node_cmd.c @@ -104,7 +104,7 @@ ec_node_cmd_eval_var(void **result, void *userctx, return -ENOMEM; } - //printf("eval var %s %p\n", str, eval); + //printf("eval var %s %p\n", str, eval); //XXX *result = eval; return 0; @@ -165,10 +165,17 @@ 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), "|")) { + if (ec_strvec_len(vec) == 0) { + 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), "|")) { out = EC_NODE_OR(EC_NO_ID, ec_node_clone(in1), ec_node_clone(in2)); if (out == NULL) return -EINVAL; @@ -250,7 +257,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 +280,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 +300,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 +333,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; @@ -544,6 +542,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 */ diff --git a/lib/ecoli_node_expr.c b/lib/ecoli_node_expr.c index 9fb48a7..2be8f55 100644 --- a/lib/ecoli_node_expr.c +++ b/lib/ecoli_node_expr.c @@ -135,6 +135,20 @@ static int ec_node_expr_build(struct ec_node_expr *node) node->post_ops_len == 0) return -EINVAL; + /* + * Example of created grammar: + * + * pre_op = "!" + * post_op = "^" + * post = val | + * pre_op expr | + * "(" expr ")" + * term = post post_op* + * prod = term ( "*" term )* + * sum = prod ( "+" prod )* + * expr = sum + */ + /* create the object, we will initialize it later: this is * needed because we have a circular dependency */ ret = -ENOMEM; diff --git a/lib/ecoli_node_seq.h b/lib/ecoli_node_seq.h index 741539c..449ffb8 100644 --- a/lib/ecoli_node_seq.h +++ b/lib/ecoli_node_seq.h @@ -41,7 +41,6 @@ struct ec_node *__ec_node_seq(const char *id, ...); struct ec_node *ec_node_seq(const char *id); /* child is consumed */ -// XXX add_child? int ec_node_seq_add(struct ec_node *node, struct ec_node *child); #endif diff --git a/lib/ecoli_parsed.c b/lib/ecoli_parsed.c index b4b59e8..5588dc6 100644 --- a/lib/ecoli_parsed.c +++ b/lib/ecoli_parsed.c @@ -42,13 +42,6 @@ TAILQ_HEAD(ec_parsed_list, ec_parsed); -/* XXX idea for parse: maintain a "cursor" ? -struct ec_parsed { - struct ec_parsed_tree *root; - stuct ec_parsed_tree *cursor; -}; -*/ - struct ec_parsed { TAILQ_ENTRY(ec_parsed) next; struct ec_parsed_list children; diff --git a/lib/ecoli_test.h b/lib/ecoli_test.h index 1cebe95..fa3fe6c 100644 --- a/lib/ecoli_test.h +++ b/lib/ecoli_test.h @@ -78,6 +78,7 @@ int ec_test_check_parse(struct ec_node *node, int expected, ...); __FILE__, __LINE__, ##__VA_ARGS__); \ /* XXX this is not an assert, it does not abort */ +// XXX use it instead of ec_log to have the file:line #define EC_TEST_ASSERT_STR(cond, fmt, ...) \ do { \ if (!(cond)) \ diff --git a/lib/main.c b/lib/main.c index 1a6a0d3..6482991 100644 --- a/lib/main.c +++ b/lib/main.c @@ -182,6 +182,7 @@ static void *debug_malloc(size_t size, const char *file, unsigned int line) size_t new_size = size + sizeof(*hdr) + sizeof(*ftr); void *ret; int r = random(); + static int seq; if (alloc_fail_proba != 0 && (r % 100) < alloc_fail_proba) hdr = NULL; @@ -203,9 +204,9 @@ static void *debug_malloc(size_t size, const char *file, unsigned int line) ftr->cookie = 0x87654321; } - EC_LOG(EC_LOG_DEBUG, "%s:%d: info: malloc(%zd) -> %p [rand=%d]\n", - file, line, size, ret, r); - if (r == 976499400) + EC_LOG(EC_LOG_DEBUG, "%s:%d: info: malloc(%zd) -> %p seq=%d\n", + file, line, size, ret, seq++); + if (seq == 100) printf("here\n"); if (ret) diff --git a/lib/todo.txt b/lib/todo.txt index 7a73930..8076ac8 100644 --- a/lib/todo.txt +++ b/lib/todo.txt @@ -377,3 +377,25 @@ int main(void) return 0; } + + +---- + + +expr expr expr + +[toto] | tutu + +[toto [titi]] + + + +pre_op = "!" +post_op = "^" +post = val | + pre_op expr | + "(" expr ")" +term = post post_op* +prod = term ( "*" term )* +sum = prod ( "+" prod )* +expr = sum -- 2.39.5