1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2016, Olivier MATZ <zer0@droids-corp.org>
14 #include <ecoli_malloc.h>
15 #include <ecoli_log.h>
16 #include <ecoli_test.h>
17 #include <ecoli_strvec.h>
18 #include <ecoli_node.h>
19 #include <ecoli_parsed.h>
20 #include <ecoli_completed.h>
21 #include <ecoli_node_seq.h>
22 #include <ecoli_node_many.h>
23 #include <ecoli_node_or.h>
24 #include <ecoli_node_weakref.h>
25 #include <ecoli_node_expr.h>
27 EC_LOG_TYPE_REGISTER(node_expr);
33 struct ec_node *child;
35 /* the configuration nodes */
36 struct ec_node *val_node;
37 struct ec_node **bin_ops;
38 unsigned int bin_ops_len;
39 struct ec_node **pre_ops;
40 unsigned int pre_ops_len;
41 struct ec_node **post_ops;
42 unsigned int post_ops_len;
43 struct ec_node **open_ops;
44 struct ec_node **close_ops;
45 unsigned int paren_len;
48 static int ec_node_expr_parse(const struct ec_node *gen_node,
49 struct ec_parsed *state,
50 const struct ec_strvec *strvec)
52 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
54 if (node->child == NULL)
56 return ec_node_parse_child(node->child, state, strvec);
60 ec_node_expr_complete(const struct ec_node *gen_node,
61 struct ec_completed *completed,
62 const struct ec_strvec *strvec)
64 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
66 if (node->child == NULL)
68 return ec_node_complete_child(node->child, completed, strvec);
71 static void ec_node_expr_free_priv(struct ec_node *gen_node)
73 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
76 EC_LOG(EC_LOG_DEBUG, "free %p %p %p\n", node, node->child, node->val_node);
77 ec_node_free(node->val_node);
79 for (i = 0; i < node->bin_ops_len; i++)
80 ec_node_free(node->bin_ops[i]);
81 ec_free(node->bin_ops);
82 for (i = 0; i < node->pre_ops_len; i++)
83 ec_node_free(node->pre_ops[i]);
84 ec_free(node->pre_ops);
85 for (i = 0; i < node->post_ops_len; i++)
86 ec_node_free(node->post_ops[i]);
87 ec_free(node->post_ops);
88 for (i = 0; i < node->paren_len; i++) {
89 ec_node_free(node->open_ops[i]);
90 ec_node_free(node->close_ops[i]);
92 ec_free(node->open_ops);
93 ec_free(node->close_ops);
95 ec_node_free(node->child);
98 static int ec_node_expr_build(struct ec_node_expr *node)
100 struct ec_node *term = NULL, *expr = NULL, *next = NULL,
101 *pre_op = NULL, *post_op = NULL,
102 *post = NULL, *weak = NULL;
106 ec_node_free(node->child);
109 if (node->val_node == NULL)
111 if (node->bin_ops_len == 0 && node->pre_ops_len == 0 &&
112 node->post_ops_len == 0)
116 * Example of created grammar:
123 * term = post post_op*
124 * prod = term ( "*" term )*
125 * sum = prod ( "+" prod )*
129 /* create the object, we will initialize it later: this is
130 * needed because we have a circular dependency */
132 weak = ec_node("weakref", "weak");
136 /* prefix unary operators */
137 pre_op = ec_node("or", "pre-op");
140 for (i = 0; i < node->pre_ops_len; i++) {
141 if (ec_node_or_add(pre_op, ec_node_clone(node->pre_ops[i])) < 0)
145 /* suffix unary operators */
146 post_op = ec_node("or", "post-op");
149 for (i = 0; i < node->post_ops_len; i++) {
150 if (ec_node_or_add(post_op, ec_node_clone(node->post_ops[i])) < 0)
154 post = ec_node("or", "post");
157 if (ec_node_or_add(post, ec_node_clone(node->val_node)) < 0)
159 if (ec_node_or_add(post,
160 EC_NODE_SEQ(EC_NO_ID,
161 ec_node_clone(pre_op),
162 ec_node_clone(weak))) < 0)
164 for (i = 0; i < node->paren_len; i++) {
165 if (ec_node_or_add(post, EC_NODE_SEQ(EC_NO_ID,
166 ec_node_clone(node->open_ops[i]),
168 ec_node_clone(node->close_ops[i]))) < 0)
171 term = EC_NODE_SEQ("term",
173 ec_node_many(EC_NO_ID, ec_node_clone(post_op), 0, 0)
178 for (i = 0; i < node->bin_ops_len; i++) {
179 next = EC_NODE_SEQ("next",
181 ec_node_many(EC_NO_ID,
182 EC_NODE_SEQ(EC_NO_ID,
183 ec_node_clone(node->bin_ops[i]),
197 /* free the initial references */
198 ec_node_free(pre_op);
200 ec_node_free(post_op);
205 /* no need to clone here, the node is not consumed */
206 if (ec_node_weakref_set(weak, expr) < 0)
218 ec_node_free(pre_op);
219 ec_node_free(post_op);
226 static struct ec_node_type ec_node_expr_type = {
228 .parse = ec_node_expr_parse,
229 .complete = ec_node_expr_complete,
230 .size = sizeof(struct ec_node_expr),
231 .free_priv = ec_node_expr_free_priv,
234 EC_NODE_TYPE_REGISTER(ec_node_expr_type);
236 int ec_node_expr_set_val_node(struct ec_node *gen_node, struct ec_node *val_node)
238 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
241 ret = ec_node_check_type(gen_node, &ec_node_expr_type);
246 if (val_node == NULL)
249 ec_node_free(node->val_node);
250 node->val_node = val_node;
251 ec_node_expr_build(node);
256 ec_node_free(val_node);
260 /* add a binary operator */
261 int ec_node_expr_add_bin_op(struct ec_node *gen_node, struct ec_node *op)
263 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
264 struct ec_node **bin_ops;
267 ret = ec_node_check_type(gen_node, &ec_node_expr_type);
272 if (node == NULL || op == NULL)
276 bin_ops = ec_realloc(node->bin_ops,
277 (node->bin_ops_len + 1) * sizeof(*node->bin_ops));
281 node->bin_ops = bin_ops;
282 bin_ops[node->bin_ops_len] = op;
284 ec_node_expr_build(node);
293 /* add a unary pre-operator */
294 int ec_node_expr_add_pre_op(struct ec_node *gen_node, struct ec_node *op)
296 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
297 struct ec_node **pre_ops;
300 ret = ec_node_check_type(gen_node, &ec_node_expr_type);
305 if (node == NULL || op == NULL)
309 pre_ops = ec_realloc(node->pre_ops,
310 (node->pre_ops_len + 1) * sizeof(*node->pre_ops));
314 node->pre_ops = pre_ops;
315 pre_ops[node->pre_ops_len] = op;
317 ec_node_expr_build(node);
326 /* add a unary post-operator */
327 int ec_node_expr_add_post_op(struct ec_node *gen_node, struct ec_node *op)
329 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
330 struct ec_node **post_ops;
333 ret = ec_node_check_type(gen_node, &ec_node_expr_type);
338 if (node == NULL || op == NULL)
342 post_ops = ec_realloc(node->post_ops,
343 (node->post_ops_len + 1) * sizeof(*node->post_ops));
344 if (post_ops == NULL)
347 node->post_ops = post_ops;
348 post_ops[node->post_ops_len] = op;
349 node->post_ops_len++;
350 ec_node_expr_build(node);
359 /* add parenthesis symbols */
360 int ec_node_expr_add_parenthesis(struct ec_node *gen_node,
361 struct ec_node *open, struct ec_node *close)
363 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
364 struct ec_node **open_ops, **close_ops;
367 ret = ec_node_check_type(gen_node, &ec_node_expr_type);
372 if (node == NULL || open == NULL || close == NULL)
376 open_ops = ec_realloc(node->open_ops,
377 (node->paren_len + 1) * sizeof(*node->open_ops));
378 if (open_ops == NULL)
380 close_ops = ec_realloc(node->close_ops,
381 (node->paren_len + 1) * sizeof(*node->close_ops));
382 if (close_ops == NULL)
385 node->open_ops = open_ops;
386 node->close_ops = close_ops;
387 open_ops[node->paren_len] = open;
388 close_ops[node->paren_len] = close;
390 ec_node_expr_build(node);
400 enum expr_node_type {
410 static enum expr_node_type get_node_type(const struct ec_node *expr_gen_node,
411 const struct ec_node *check)
413 struct ec_node_expr *expr_node = (struct ec_node_expr *)expr_gen_node;
416 if (check == expr_node->val_node)
419 for (i = 0; i < expr_node->bin_ops_len; i++) {
420 if (check == expr_node->bin_ops[i])
423 for (i = 0; i < expr_node->pre_ops_len; i++) {
424 if (check == expr_node->pre_ops[i])
427 for (i = 0; i < expr_node->post_ops_len; i++) {
428 if (check == expr_node->post_ops[i])
432 for (i = 0; i < expr_node->paren_len; i++) {
433 if (check == expr_node->open_ops[i])
436 for (i = 0; i < expr_node->paren_len; i++) {
437 if (check == expr_node->close_ops[i])
447 const struct ec_parsed *op;
448 enum expr_node_type op_type;
451 /* merge x and y results in x */
452 static int merge_results(void *userctx,
453 const struct ec_node_expr_eval_ops *ops,
454 struct result *x, const struct result *y)
458 if (y->has_val == 0 && y->op == NULL)
460 if (x->has_val == 0 && x->op == NULL) {
465 if (x->has_val && y->has_val && y->op != NULL) {
466 if (y->op_type == BIN_OP) {
467 ret = ops->eval_bin_op(&x->val, userctx, x->val,
476 if (x->has_val == 0 && x->op != NULL && y->has_val && y->op == NULL) {
477 if (x->op_type == PRE_OP) {
478 ret = ops->eval_pre_op(&x->val, userctx, y->val, x->op);
485 } else if (x->op_type == BIN_OP) {
492 if (x->has_val && x->op == NULL && y->has_val == 0 && y->op != NULL) {
493 ret = ops->eval_post_op(&x->val, userctx, x->val, y->op);
500 assert(false); /* we should not get here */
504 static int eval_expression(struct result *result,
506 const struct ec_node_expr_eval_ops *ops,
507 const struct ec_node *expr_gen_node,
508 const struct ec_parsed *parsed)
511 struct ec_parsed *open = NULL, *close = NULL;
512 struct result child_result;
513 struct ec_parsed *child;
514 enum expr_node_type type;
517 memset(result, 0, sizeof(*result));
518 memset(&child_result, 0, sizeof(child_result));
520 type = get_node_type(expr_gen_node, ec_parsed_get_node(parsed));
522 ret = ops->eval_var(&result->val, userctx, parsed);
526 } else if (type == PRE_OP || type == POST_OP || type == BIN_OP) {
528 result->op_type = type;
531 EC_PARSED_FOREACH_CHILD(child, parsed) {
533 type = get_node_type(expr_gen_node, ec_parsed_get_node(child));
534 if (type == PAREN_OPEN) {
537 } else if (type == PAREN_CLOSE) {
542 ret = eval_expression(&child_result, userctx, ops,
543 expr_gen_node, child);
547 ret = merge_results(userctx, ops, result, &child_result);
551 memset(&child_result, 0, sizeof(child_result));
554 if (open != NULL && close != NULL) {
555 ret = ops->eval_parenthesis(&result->val, userctx, open, close,
565 ops->eval_free(result->val, userctx);
566 if (child_result.has_val)
567 ops->eval_free(child_result.val, userctx);
568 memset(result, 0, sizeof(*result));
573 int ec_node_expr_eval(void **user_result, const struct ec_node *node,
574 struct ec_parsed *parsed, const struct ec_node_expr_eval_ops *ops,
577 struct result result;
580 if (ops == NULL || ops->eval_var == NULL || ops->eval_pre_op == NULL ||
581 ops->eval_post_op == NULL || ops->eval_bin_op == NULL ||
582 ops->eval_parenthesis == NULL || ops->eval_free == NULL)
585 ret = ec_node_check_type(node, &ec_node_expr_type);
589 if (!ec_parsed_matches(parsed))
592 ret = eval_expression(&result, userctx, ops, node, parsed);
596 assert(result.has_val);
597 assert(result.op == NULL);
598 *user_result = result.val;
603 /* the test case is in a separate file ecoli_node_expr_test.c */