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_expr.h>
26 EC_LOG_TYPE_REGISTER(node_expr);
32 struct ec_node *child;
34 /* the configuration nodes */
35 struct ec_node *val_node;
36 struct ec_node **bin_ops;
37 unsigned int bin_ops_len;
38 struct ec_node **pre_ops;
39 unsigned int pre_ops_len;
40 struct ec_node **post_ops;
41 unsigned int post_ops_len;
42 struct ec_node **open_ops;
43 struct ec_node **close_ops;
44 unsigned int paren_len;
47 static int ec_node_expr_parse(const struct ec_node *gen_node,
48 struct ec_parse *state,
49 const struct ec_strvec *strvec)
51 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
53 if (node->child == NULL) {
58 return ec_node_parse_child(node->child, state, strvec);
62 ec_node_expr_complete(const struct ec_node *gen_node,
64 const struct ec_strvec *strvec)
66 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
68 if (node->child == NULL) {
73 return ec_node_complete_child(node->child, comp, strvec);
76 static void ec_node_expr_free_priv(struct ec_node *gen_node)
78 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
81 ec_node_free(node->child);
82 ec_node_free(node->val_node);
84 for (i = 0; i < node->bin_ops_len; i++)
85 ec_node_free(node->bin_ops[i]);
86 ec_free(node->bin_ops);
87 for (i = 0; i < node->pre_ops_len; i++)
88 ec_node_free(node->pre_ops[i]);
89 ec_free(node->pre_ops);
90 for (i = 0; i < node->post_ops_len; i++)
91 ec_node_free(node->post_ops[i]);
92 ec_free(node->post_ops);
93 for (i = 0; i < node->paren_len; i++) {
94 ec_node_free(node->open_ops[i]);
95 ec_node_free(node->close_ops[i]);
97 ec_free(node->open_ops);
98 ec_free(node->close_ops);
101 static int ec_node_expr_build(struct ec_node_expr *node)
103 struct ec_node *term = NULL, *expr = NULL, *next = NULL,
104 *pre_op = NULL, *post_op = NULL, *ref = NULL,
108 ec_node_free(node->child);
111 if (node->val_node == NULL) {
116 if (node->bin_ops_len == 0 && node->pre_ops_len == 0 &&
117 node->post_ops_len == 0) {
123 * Example of created grammar:
130 * term = post post_op*
131 * prod = term ( "*" term )*
132 * sum = prod ( "+" prod )*
136 /* we use this as a ref, will be set later */
137 ref = ec_node("seq", "ref");
141 /* prefix unary operators */
142 pre_op = ec_node("or", "pre-op");
145 for (i = 0; i < node->pre_ops_len; i++) {
146 if (ec_node_or_add(pre_op, ec_node_clone(node->pre_ops[i])) < 0)
150 /* suffix unary operators */
151 post_op = ec_node("or", "post-op");
154 for (i = 0; i < node->post_ops_len; i++) {
155 if (ec_node_or_add(post_op, ec_node_clone(node->post_ops[i])) < 0)
159 post = ec_node("or", "post");
162 if (ec_node_or_add(post, ec_node_clone(node->val_node)) < 0)
164 if (ec_node_or_add(post,
165 EC_NODE_SEQ(EC_NO_ID,
166 ec_node_clone(pre_op),
167 ec_node_clone(ref))) < 0)
169 for (i = 0; i < node->paren_len; i++) {
170 if (ec_node_or_add(post, EC_NODE_SEQ(EC_NO_ID,
171 ec_node_clone(node->open_ops[i]),
173 ec_node_clone(node->close_ops[i]))) < 0)
176 term = EC_NODE_SEQ("term",
178 ec_node_many(EC_NO_ID, ec_node_clone(post_op), 0, 0)
183 for (i = 0; i < node->bin_ops_len; i++) {
184 next = EC_NODE_SEQ("next",
186 ec_node_many(EC_NO_ID,
187 EC_NODE_SEQ(EC_NO_ID,
188 ec_node_clone(node->bin_ops[i]),
202 /* free the initial references */
203 ec_node_free(pre_op);
205 ec_node_free(post_op);
210 if (ec_node_seq_add(ref, ec_node_clone(expr)) < 0)
222 ec_node_free(pre_op);
223 ec_node_free(post_op);
231 ec_node_expr_get_children_count(const struct ec_node *gen_node)
233 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
241 ec_node_expr_get_child(const struct ec_node *gen_node, size_t i,
242 struct ec_node **child, unsigned int *refs)
244 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
249 *child = node->child;
254 static struct ec_node_type ec_node_expr_type = {
256 .parse = ec_node_expr_parse,
257 .complete = ec_node_expr_complete,
258 .size = sizeof(struct ec_node_expr),
259 .free_priv = ec_node_expr_free_priv,
260 .get_children_count = ec_node_expr_get_children_count,
261 .get_child = ec_node_expr_get_child,
264 EC_NODE_TYPE_REGISTER(ec_node_expr_type);
266 int ec_node_expr_set_val_node(struct ec_node *gen_node, struct ec_node *val_node)
268 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
270 if (ec_node_check_type(gen_node, &ec_node_expr_type) < 0)
273 if (val_node == NULL) {
278 ec_node_free(node->val_node);
279 node->val_node = val_node;
280 ec_node_expr_build(node);
285 ec_node_free(val_node);
289 /* add a binary operator */
290 int ec_node_expr_add_bin_op(struct ec_node *gen_node, struct ec_node *op)
292 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
293 struct ec_node **bin_ops;
295 if (ec_node_check_type(gen_node, &ec_node_expr_type) < 0)
298 if (node == NULL || op == NULL) {
303 bin_ops = ec_realloc(node->bin_ops,
304 (node->bin_ops_len + 1) * sizeof(*node->bin_ops));
308 node->bin_ops = bin_ops;
309 bin_ops[node->bin_ops_len] = op;
311 ec_node_expr_build(node);
320 /* add a unary pre-operator */
321 int ec_node_expr_add_pre_op(struct ec_node *gen_node, struct ec_node *op)
323 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
324 struct ec_node **pre_ops;
326 if (ec_node_check_type(gen_node, &ec_node_expr_type) < 0)
329 if (node == NULL || op == NULL) {
334 pre_ops = ec_realloc(node->pre_ops,
335 (node->pre_ops_len + 1) * sizeof(*node->pre_ops));
339 node->pre_ops = pre_ops;
340 pre_ops[node->pre_ops_len] = op;
342 ec_node_expr_build(node);
351 /* add a unary post-operator */
352 int ec_node_expr_add_post_op(struct ec_node *gen_node, struct ec_node *op)
354 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
355 struct ec_node **post_ops;
357 if (ec_node_check_type(gen_node, &ec_node_expr_type) < 0)
360 if (node == NULL || op == NULL) {
365 post_ops = ec_realloc(node->post_ops,
366 (node->post_ops_len + 1) * sizeof(*node->post_ops));
367 if (post_ops == NULL)
370 node->post_ops = post_ops;
371 post_ops[node->post_ops_len] = op;
372 node->post_ops_len++;
373 ec_node_expr_build(node);
382 /* add parenthesis symbols */
383 int ec_node_expr_add_parenthesis(struct ec_node *gen_node,
384 struct ec_node *open, struct ec_node *close)
386 struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
387 struct ec_node **open_ops, **close_ops;
389 if (ec_node_check_type(gen_node, &ec_node_expr_type) < 0)
392 if (node == NULL || open == NULL || close == NULL) {
397 open_ops = ec_realloc(node->open_ops,
398 (node->paren_len + 1) * sizeof(*node->open_ops));
399 if (open_ops == NULL)
401 close_ops = ec_realloc(node->close_ops,
402 (node->paren_len + 1) * sizeof(*node->close_ops));
403 if (close_ops == NULL)
406 node->open_ops = open_ops;
407 node->close_ops = close_ops;
408 open_ops[node->paren_len] = open;
409 close_ops[node->paren_len] = close;
411 ec_node_expr_build(node);
421 enum expr_node_type {
431 static enum expr_node_type get_node_type(const struct ec_node *expr_gen_node,
432 const struct ec_node *check)
434 struct ec_node_expr *expr_node = (struct ec_node_expr *)expr_gen_node;
437 if (check == expr_node->val_node)
440 for (i = 0; i < expr_node->bin_ops_len; i++) {
441 if (check == expr_node->bin_ops[i])
444 for (i = 0; i < expr_node->pre_ops_len; i++) {
445 if (check == expr_node->pre_ops[i])
448 for (i = 0; i < expr_node->post_ops_len; i++) {
449 if (check == expr_node->post_ops[i])
453 for (i = 0; i < expr_node->paren_len; i++) {
454 if (check == expr_node->open_ops[i])
457 for (i = 0; i < expr_node->paren_len; i++) {
458 if (check == expr_node->close_ops[i])
468 const struct ec_parse *op;
469 enum expr_node_type op_type;
472 /* merge x and y results in x */
473 static int merge_results(void *userctx,
474 const struct ec_node_expr_eval_ops *ops,
475 struct result *x, const struct result *y)
477 if (y->has_val == 0 && y->op == NULL)
479 if (x->has_val == 0 && x->op == NULL) {
484 if (x->has_val && y->has_val && y->op != NULL) {
485 if (y->op_type == BIN_OP) {
486 if (ops->eval_bin_op(&x->val, userctx, x->val,
494 if (x->has_val == 0 && x->op != NULL && y->has_val && y->op == NULL) {
495 if (x->op_type == PRE_OP) {
496 if (ops->eval_pre_op(&x->val, userctx, y->val,
503 } else if (x->op_type == BIN_OP) {
510 if (x->has_val && x->op == NULL && y->has_val == 0 && y->op != NULL) {
511 if (ops->eval_post_op(&x->val, userctx, x->val, y->op) < 0)
517 assert(false); /* we should not get here */
521 static int eval_expression(struct result *result,
523 const struct ec_node_expr_eval_ops *ops,
524 const struct ec_node *expr_gen_node,
525 const struct ec_parse *parse)
528 struct ec_parse *open = NULL, *close = NULL;
529 struct result child_result;
530 struct ec_parse *child;
531 enum expr_node_type type;
533 memset(result, 0, sizeof(*result));
534 memset(&child_result, 0, sizeof(child_result));
536 type = get_node_type(expr_gen_node, ec_parse_get_node(parse));
538 if (ops->eval_var(&result->val, userctx, parse) < 0)
541 } else if (type == PRE_OP || type == POST_OP || type == BIN_OP) {
543 result->op_type = type;
546 EC_PARSE_FOREACH_CHILD(child, parse) {
548 type = get_node_type(expr_gen_node, ec_parse_get_node(child));
549 if (type == PAREN_OPEN) {
552 } else if (type == PAREN_CLOSE) {
557 if (eval_expression(&child_result, userctx, ops,
558 expr_gen_node, child) < 0)
561 if (merge_results(userctx, ops, result, &child_result) < 0)
564 memset(&child_result, 0, sizeof(child_result));
567 if (open != NULL && close != NULL) {
568 if (ops->eval_parenthesis(&result->val, userctx, open, close,
577 ops->eval_free(result->val, userctx);
578 if (child_result.has_val)
579 ops->eval_free(child_result.val, userctx);
580 memset(result, 0, sizeof(*result));
585 int ec_node_expr_eval(void **user_result, const struct ec_node *node,
586 struct ec_parse *parse, const struct ec_node_expr_eval_ops *ops,
589 struct result result;
591 if (ops == NULL || ops->eval_var == NULL || ops->eval_pre_op == NULL ||
592 ops->eval_post_op == NULL || ops->eval_bin_op == NULL ||
593 ops->eval_parenthesis == NULL ||
594 ops->eval_free == NULL) {
599 if (ec_node_check_type(node, &ec_node_expr_type) < 0)
602 if (!ec_parse_matches(parse)) {
607 if (eval_expression(&result, userctx, ops, node, parse) < 0)
610 assert(result.has_val);
611 assert(result.op == NULL);
612 *user_result = result.val;
617 /* the test case is in a separate file ecoli_node_expr_test.c */