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_parse.h>
20 #include <ecoli_complete.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_parse *state,
50 const struct ec_strvec *strvec)
52 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
54 if (node->child == NULL) {
59 return ec_node_parse_child(node->child, state, strvec);
63 ec_node_expr_complete(const struct ec_node *gen_node,
65 const struct ec_strvec *strvec)
67 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
69 if (node->child == NULL) {
74 return ec_node_complete_child(node->child, comp, strvec);
77 static void ec_node_expr_free_priv(struct ec_node *gen_node)
79 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
82 EC_LOG(EC_LOG_DEBUG, "free %p %p %p\n", node, node->child, node->val_node);
83 ec_node_free(node->val_node);
85 for (i = 0; i < node->bin_ops_len; i++)
86 ec_node_free(node->bin_ops[i]);
87 ec_free(node->bin_ops);
88 for (i = 0; i < node->pre_ops_len; i++)
89 ec_node_free(node->pre_ops[i]);
90 ec_free(node->pre_ops);
91 for (i = 0; i < node->post_ops_len; i++)
92 ec_node_free(node->post_ops[i]);
93 ec_free(node->post_ops);
94 for (i = 0; i < node->paren_len; i++) {
95 ec_node_free(node->open_ops[i]);
96 ec_node_free(node->close_ops[i]);
98 ec_free(node->open_ops);
99 ec_free(node->close_ops);
101 ec_node_free(node->child);
104 static int ec_node_expr_build(struct ec_node_expr *node)
106 struct ec_node *term = NULL, *expr = NULL, *next = NULL,
107 *pre_op = NULL, *post_op = NULL,
108 *post = NULL, *weak = NULL;
111 ec_node_free(node->child);
114 if (node->val_node == NULL) {
119 if (node->bin_ops_len == 0 && node->pre_ops_len == 0 &&
120 node->post_ops_len == 0) {
126 * Example of created grammar:
133 * term = post post_op*
134 * prod = term ( "*" term )*
135 * sum = prod ( "+" prod )*
139 /* create the object, we will initialize it later: this is
140 * needed because we have a circular dependency */
141 weak = ec_node("weakref", "weak");
145 /* prefix unary operators */
146 pre_op = ec_node("or", "pre-op");
149 for (i = 0; i < node->pre_ops_len; i++) {
150 if (ec_node_or_add(pre_op, ec_node_clone(node->pre_ops[i])) < 0)
154 /* suffix unary operators */
155 post_op = ec_node("or", "post-op");
158 for (i = 0; i < node->post_ops_len; i++) {
159 if (ec_node_or_add(post_op, ec_node_clone(node->post_ops[i])) < 0)
163 post = ec_node("or", "post");
166 if (ec_node_or_add(post, ec_node_clone(node->val_node)) < 0)
168 if (ec_node_or_add(post,
169 EC_NODE_SEQ(EC_NO_ID,
170 ec_node_clone(pre_op),
171 ec_node_clone(weak))) < 0)
173 for (i = 0; i < node->paren_len; i++) {
174 if (ec_node_or_add(post, EC_NODE_SEQ(EC_NO_ID,
175 ec_node_clone(node->open_ops[i]),
177 ec_node_clone(node->close_ops[i]))) < 0)
180 term = EC_NODE_SEQ("term",
182 ec_node_many(EC_NO_ID, ec_node_clone(post_op), 0, 0)
187 for (i = 0; i < node->bin_ops_len; i++) {
188 next = EC_NODE_SEQ("next",
190 ec_node_many(EC_NO_ID,
191 EC_NODE_SEQ(EC_NO_ID,
192 ec_node_clone(node->bin_ops[i]),
206 /* free the initial references */
207 ec_node_free(pre_op);
209 ec_node_free(post_op);
214 /* no need to clone here, the node is not consumed */
215 if (ec_node_weakref_set(weak, expr) < 0)
227 ec_node_free(pre_op);
228 ec_node_free(post_op);
235 static struct ec_node_type ec_node_expr_type = {
237 .parse = ec_node_expr_parse,
238 .complete = ec_node_expr_complete,
239 .size = sizeof(struct ec_node_expr),
240 .free_priv = ec_node_expr_free_priv,
243 EC_NODE_TYPE_REGISTER(ec_node_expr_type);
245 int ec_node_expr_set_val_node(struct ec_node *gen_node, struct ec_node *val_node)
247 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
249 if (ec_node_check_type(gen_node, &ec_node_expr_type) < 0)
252 if (val_node == NULL) {
257 ec_node_free(node->val_node);
258 node->val_node = val_node;
259 ec_node_expr_build(node);
264 ec_node_free(val_node);
268 /* add a binary operator */
269 int ec_node_expr_add_bin_op(struct ec_node *gen_node, struct ec_node *op)
271 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
272 struct ec_node **bin_ops;
274 if (ec_node_check_type(gen_node, &ec_node_expr_type) < 0)
277 if (node == NULL || op == NULL) {
282 bin_ops = ec_realloc(node->bin_ops,
283 (node->bin_ops_len + 1) * sizeof(*node->bin_ops));
287 node->bin_ops = bin_ops;
288 bin_ops[node->bin_ops_len] = op;
290 ec_node_expr_build(node);
299 /* add a unary pre-operator */
300 int ec_node_expr_add_pre_op(struct ec_node *gen_node, struct ec_node *op)
302 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
303 struct ec_node **pre_ops;
305 if (ec_node_check_type(gen_node, &ec_node_expr_type) < 0)
308 if (node == NULL || op == NULL) {
313 pre_ops = ec_realloc(node->pre_ops,
314 (node->pre_ops_len + 1) * sizeof(*node->pre_ops));
318 node->pre_ops = pre_ops;
319 pre_ops[node->pre_ops_len] = op;
321 ec_node_expr_build(node);
330 /* add a unary post-operator */
331 int ec_node_expr_add_post_op(struct ec_node *gen_node, struct ec_node *op)
333 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
334 struct ec_node **post_ops;
336 if (ec_node_check_type(gen_node, &ec_node_expr_type) < 0)
339 if (node == NULL || op == NULL) {
344 post_ops = ec_realloc(node->post_ops,
345 (node->post_ops_len + 1) * sizeof(*node->post_ops));
346 if (post_ops == NULL)
349 node->post_ops = post_ops;
350 post_ops[node->post_ops_len] = op;
351 node->post_ops_len++;
352 ec_node_expr_build(node);
361 /* add parenthesis symbols */
362 int ec_node_expr_add_parenthesis(struct ec_node *gen_node,
363 struct ec_node *open, struct ec_node *close)
365 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
366 struct ec_node **open_ops, **close_ops;
368 if (ec_node_check_type(gen_node, &ec_node_expr_type) < 0)
371 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_parse *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)
456 if (y->has_val == 0 && y->op == NULL)
458 if (x->has_val == 0 && x->op == NULL) {
463 if (x->has_val && y->has_val && y->op != NULL) {
464 if (y->op_type == BIN_OP) {
465 if (ops->eval_bin_op(&x->val, userctx, x->val,
473 if (x->has_val == 0 && x->op != NULL && y->has_val && y->op == NULL) {
474 if (x->op_type == PRE_OP) {
475 if (ops->eval_pre_op(&x->val, userctx, y->val,
482 } else if (x->op_type == BIN_OP) {
489 if (x->has_val && x->op == NULL && y->has_val == 0 && y->op != NULL) {
490 if (ops->eval_post_op(&x->val, userctx, x->val, y->op) < 0)
496 assert(false); /* we should not get here */
500 static int eval_expression(struct result *result,
502 const struct ec_node_expr_eval_ops *ops,
503 const struct ec_node *expr_gen_node,
504 const struct ec_parse *parse)
507 struct ec_parse *open = NULL, *close = NULL;
508 struct result child_result;
509 struct ec_parse *child;
510 enum expr_node_type type;
512 memset(result, 0, sizeof(*result));
513 memset(&child_result, 0, sizeof(child_result));
515 type = get_node_type(expr_gen_node, ec_parse_get_node(parse));
517 if (ops->eval_var(&result->val, userctx, parse) < 0)
520 } else if (type == PRE_OP || type == POST_OP || type == BIN_OP) {
522 result->op_type = type;
525 EC_PARSE_FOREACH_CHILD(child, parse) {
527 type = get_node_type(expr_gen_node, ec_parse_get_node(child));
528 if (type == PAREN_OPEN) {
531 } else if (type == PAREN_CLOSE) {
536 if (eval_expression(&child_result, userctx, ops,
537 expr_gen_node, child) < 0)
540 if (merge_results(userctx, ops, result, &child_result) < 0)
543 memset(&child_result, 0, sizeof(child_result));
546 if (open != NULL && close != NULL) {
547 if (ops->eval_parenthesis(&result->val, userctx, open, close,
556 ops->eval_free(result->val, userctx);
557 if (child_result.has_val)
558 ops->eval_free(child_result.val, userctx);
559 memset(result, 0, sizeof(*result));
564 int ec_node_expr_eval(void **user_result, const struct ec_node *node,
565 struct ec_parse *parse, const struct ec_node_expr_eval_ops *ops,
568 struct result result;
570 if (ops == NULL || ops->eval_var == NULL || ops->eval_pre_op == NULL ||
571 ops->eval_post_op == NULL || ops->eval_bin_op == NULL ||
572 ops->eval_parenthesis == NULL ||
573 ops->eval_free == NULL) {
578 if (ec_node_check_type(node, &ec_node_expr_type) < 0)
581 if (!ec_parse_matches(parse)) {
586 if (eval_expression(&result, userctx, ops, node, parse) < 0)
589 assert(result.has_val);
590 assert(result.op == NULL);
591 *user_result = result.val;
596 /* the test case is in a separate file ecoli_node_expr_test.c */