2 * Copyright (c) 2016-2017, Olivier MATZ <zer0@droids-corp.org>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the University of California, Berkeley nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 #include <ecoli_malloc.h>
38 #include <ecoli_log.h>
39 #include <ecoli_test.h>
40 #include <ecoli_strvec.h>
41 #include <ecoli_node.h>
42 #include <ecoli_parsed.h>
43 #include <ecoli_completed.h>
44 #include <ecoli_node_seq.h>
45 #include <ecoli_node_many.h>
46 #include <ecoli_node_or.h>
47 #include <ecoli_node_weakref.h>
48 #include <ecoli_node_expr.h>
50 EC_LOG_TYPE_REGISTER(node_expr);
56 struct ec_node *child;
58 /* the configuration nodes */
59 struct ec_node *val_node;
60 struct ec_node **bin_ops;
61 unsigned int bin_ops_len;
62 struct ec_node **pre_ops;
63 unsigned int pre_ops_len;
64 struct ec_node **post_ops;
65 unsigned int post_ops_len;
66 struct ec_node **open_ops;
67 struct ec_node **close_ops;
68 unsigned int paren_len;
71 static int ec_node_expr_parse(const struct ec_node *gen_node,
72 struct ec_parsed *state,
73 const struct ec_strvec *strvec)
75 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
77 return ec_node_parse_child(node->child, state, strvec);
81 ec_node_expr_complete(const struct ec_node *gen_node,
82 struct ec_completed *completed,
83 const struct ec_strvec *strvec)
85 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
87 return ec_node_complete_child(node->child, completed, strvec);
90 static void ec_node_expr_free_priv(struct ec_node *gen_node)
92 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
95 EC_LOG(EC_LOG_DEBUG, "free %p %p %p\n", node, node->child, node->val_node);
96 ec_node_free(node->val_node);
98 for (i = 0; i < node->bin_ops_len; i++)
99 ec_node_free(node->bin_ops[i]);
100 ec_free(node->bin_ops);
101 for (i = 0; i < node->pre_ops_len; i++)
102 ec_node_free(node->pre_ops[i]);
103 ec_free(node->pre_ops);
104 for (i = 0; i < node->post_ops_len; i++)
105 ec_node_free(node->post_ops[i]);
106 ec_free(node->post_ops);
107 for (i = 0; i < node->paren_len; i++) {
108 ec_node_free(node->open_ops[i]);
109 ec_node_free(node->close_ops[i]);
111 ec_free(node->open_ops);
112 ec_free(node->close_ops);
114 ec_node_free(node->child);
117 static int ec_node_expr_build(struct ec_node *gen_node)
119 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
120 struct ec_node *term = NULL, *expr = NULL, *next = NULL,
121 *pre_op = NULL, *post_op = NULL,
122 *post = NULL, *weak = NULL;
126 if (node->val_node == NULL)
128 if (node->bin_ops_len == 0 && node->pre_ops_len == 0 &&
129 node->post_ops_len == 0)
132 /* create the object, we will initialize it later: this is
133 * needed because we have a circular dependency */
135 weak = ec_node("weakref", "weak");
139 /* prefix unary operators */
140 pre_op = ec_node("or", "pre-op");
143 for (i = 0; i < node->pre_ops_len; i++) {
144 if (ec_node_or_add(pre_op, ec_node_clone(node->pre_ops[i])) < 0)
148 /* suffix unary operators */
149 post_op = ec_node("or", "post-op");
152 for (i = 0; i < node->post_ops_len; i++) {
153 if (ec_node_or_add(post_op, ec_node_clone(node->post_ops[i])) < 0)
157 post = ec_node("or", "post");
160 if (ec_node_or_add(post, ec_node_clone(node->val_node)) < 0)
162 if (ec_node_or_add(post,
164 ec_node_clone(pre_op),
165 ec_node_clone(weak))) < 0)
167 for (i = 0; i < node->paren_len; i++) {
168 if (ec_node_or_add(post, EC_NODE_SEQ(NULL,
169 ec_node_clone(node->open_ops[i]),
171 ec_node_clone(node->close_ops[i]))) < 0)
174 term = EC_NODE_SEQ("term",
176 ec_node_many(NULL, ec_node_clone(post_op), 0, 0)
181 for (i = 0; i < node->bin_ops_len; i++) {
182 next = EC_NODE_SEQ("next",
186 ec_node_clone(node->bin_ops[i]),
200 /* free the initial references */
201 ec_node_free(pre_op);
203 ec_node_free(post_op);
208 /* no need to clone here, the node is not consumed */
209 if (ec_node_weakref_set(weak, expr) < 0)
215 //ec_node_dump(stdout, node->child); //XXX
222 ec_node_free(pre_op);
223 ec_node_free(post_op);
230 static struct ec_node_type ec_node_expr_type = {
232 .build = ec_node_expr_build,
233 .parse = ec_node_expr_parse,
234 .complete = ec_node_expr_complete,
235 .size = sizeof(struct ec_node_expr),
236 .free_priv = ec_node_expr_free_priv,
239 EC_NODE_TYPE_REGISTER(ec_node_expr_type);
241 int ec_node_expr_set_val_node(struct ec_node *gen_node, struct ec_node *val_node)
243 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
246 ret = ec_node_check_type(gen_node, &ec_node_expr_type);
251 if (val_node == NULL)
254 if (gen_node->flags & EC_NODE_F_BUILT)
257 if (node->val_node != NULL)
260 node->val_node = val_node;
261 gen_node->flags &= ~EC_NODE_F_BUILT;
266 ec_node_free(val_node);
270 /* add a binary operator */
271 int ec_node_expr_add_bin_op(struct ec_node *gen_node, struct ec_node *op)
273 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
274 struct ec_node **bin_ops;
277 ret = ec_node_check_type(gen_node, &ec_node_expr_type);
282 if (node == NULL || op == NULL)
285 if (gen_node->flags & EC_NODE_F_BUILT)
289 bin_ops = ec_realloc(node->bin_ops,
290 (node->bin_ops_len + 1) * sizeof(*node->bin_ops));
294 node->bin_ops = bin_ops;
295 bin_ops[node->bin_ops_len] = op;
297 gen_node->flags &= ~EC_NODE_F_BUILT;
306 /* add a unary pre-operator */
307 int ec_node_expr_add_pre_op(struct ec_node *gen_node, struct ec_node *op)
309 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
310 struct ec_node **pre_ops;
313 ret = ec_node_check_type(gen_node, &ec_node_expr_type);
318 if (node == NULL || op == NULL)
321 if (gen_node->flags & EC_NODE_F_BUILT)
325 pre_ops = ec_realloc(node->pre_ops,
326 (node->pre_ops_len + 1) * sizeof(*node->pre_ops));
330 node->pre_ops = pre_ops;
331 pre_ops[node->pre_ops_len] = op;
333 gen_node->flags &= ~EC_NODE_F_BUILT;
342 /* add a unary post-operator */
343 int ec_node_expr_add_post_op(struct ec_node *gen_node, struct ec_node *op)
345 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
346 struct ec_node **post_ops;
349 ret = ec_node_check_type(gen_node, &ec_node_expr_type);
354 if (node == NULL || op == NULL)
357 if (gen_node->flags & EC_NODE_F_BUILT)
361 post_ops = ec_realloc(node->post_ops,
362 (node->post_ops_len + 1) * sizeof(*node->post_ops));
363 if (post_ops == NULL)
366 node->post_ops = post_ops;
367 post_ops[node->post_ops_len] = op;
368 node->post_ops_len++;
369 gen_node->flags &= ~EC_NODE_F_BUILT;
378 /* add parenthesis symbols */
379 int ec_node_expr_add_parenthesis(struct ec_node *gen_node,
380 struct ec_node *open, struct ec_node *close)
382 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
383 struct ec_node **open_ops, **close_ops;
386 ret = ec_node_check_type(gen_node, &ec_node_expr_type);
391 if (node == NULL || open == NULL || close == NULL)
394 if (gen_node->flags & EC_NODE_F_BUILT)
398 open_ops = ec_realloc(node->open_ops,
399 (node->paren_len + 1) * sizeof(*node->open_ops));
400 if (open_ops == NULL)
402 close_ops = ec_realloc(node->close_ops,
403 (node->paren_len + 1) * sizeof(*node->close_ops));
404 if (close_ops == NULL)
407 node->open_ops = open_ops;
408 node->close_ops = close_ops;
409 open_ops[node->paren_len] = open;
410 close_ops[node->paren_len] = close;
412 gen_node->flags &= ~EC_NODE_F_BUILT;
422 enum expr_node_type {
432 static enum expr_node_type get_node_type(const struct ec_node *expr_gen_node,
433 const struct ec_node *check)
435 struct ec_node_expr *expr_node = (struct ec_node_expr *)expr_gen_node;
438 if (check == expr_node->val_node)
441 for (i = 0; i < expr_node->bin_ops_len; i++) {
442 if (check == expr_node->bin_ops[i])
445 for (i = 0; i < expr_node->pre_ops_len; i++) {
446 if (check == expr_node->pre_ops[i])
449 for (i = 0; i < expr_node->post_ops_len; i++) {
450 if (check == expr_node->post_ops[i])
454 for (i = 0; i < expr_node->paren_len; i++) {
455 if (check == expr_node->open_ops[i])
458 for (i = 0; i < expr_node->paren_len; i++) {
459 if (check == expr_node->close_ops[i])
469 const struct ec_parsed *op;
470 enum expr_node_type op_type;
473 /* merge x and y results in x */
474 static int merge_results(void *userctx,
475 const struct ec_node_expr_eval_ops *ops,
476 struct result *x, const struct result *y)
480 if (y->has_val == 0 && y->op == NULL)
482 if (x->has_val == 0 && x->op == NULL) {
487 if (x->has_val && y->has_val && y->op != NULL) {
488 if (y->op_type == BIN_OP) {
489 ret = ops->eval_bin_op(&x->val, userctx, x->val,
498 if (x->has_val == 0 && x->op != NULL && y->has_val && y->op == NULL) {
499 if (x->op_type == PRE_OP) {
500 ret = ops->eval_pre_op(&x->val, userctx, y->val, x->op);
507 } else if (x->op_type == BIN_OP) {
514 if (x->has_val && x->op == NULL && y->has_val == 0 && y->op != NULL) {
515 ret = ops->eval_post_op(&x->val, userctx, x->val, y->op);
522 assert(false); /* we should not get here */
526 static int eval_expression(struct result *result,
528 const struct ec_node_expr_eval_ops *ops,
529 const struct ec_node *expr_gen_node,
530 const struct ec_parsed *parsed)
533 struct ec_parsed *open = NULL, *close = NULL;
534 struct result child_result;
535 struct ec_parsed *child;
536 enum expr_node_type type;
539 memset(result, 0, sizeof(*result));
540 memset(&child_result, 0, sizeof(child_result));
542 type = get_node_type(expr_gen_node, ec_parsed_get_node(parsed));
544 ret = ops->eval_var(&result->val, userctx, parsed);
548 } else if (type == PRE_OP || type == POST_OP || type == BIN_OP) {
550 result->op_type = type;
553 EC_PARSED_FOREACH_CHILD(child, parsed) {
555 type = get_node_type(expr_gen_node, ec_parsed_get_node(child));
556 if (type == PAREN_OPEN) {
559 } else if (type == PAREN_CLOSE) {
564 ret = eval_expression(&child_result, userctx, ops,
565 expr_gen_node, child);
569 ret = merge_results(userctx, ops, result, &child_result);
573 memset(&child_result, 0, sizeof(child_result));
576 if (open != NULL && close != NULL) {
577 ret = ops->eval_parenthesis(&result->val, userctx, open, close,
587 ops->eval_free(result->val, userctx);
588 if (child_result.has_val)
589 ops->eval_free(child_result.val, userctx);
590 memset(result, 0, sizeof(*result));
595 int ec_node_expr_eval(void **user_result, const struct ec_node *node,
596 struct ec_parsed *parsed, const struct ec_node_expr_eval_ops *ops,
599 struct result result;
602 if (ops == NULL || ops->eval_var == NULL || ops->eval_pre_op == NULL ||
603 ops->eval_post_op == NULL || ops->eval_bin_op == NULL ||
604 ops->eval_parenthesis == NULL || ops->eval_free == NULL)
607 if (!ec_parsed_matches(parsed))
610 //ec_parsed_dump(stdout, parsed); //XXX
611 ret = eval_expression(&result, userctx, ops, node, parsed);
615 assert(result.has_val);
616 assert(result.op == NULL);
617 *user_result = result.val;
622 /* the test case is in a separate file ecoli_node_expr_test.c */