parsed -> parse
[protos/libecoli.git] / lib / ecoli_node_expr.c
index 5aa8a2e..8a0d319 100644 (file)
@@ -1,28 +1,5 @@
-/*
- * Copyright (c) 2016-2017, Olivier MATZ <zer0@droids-corp.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the University of California, Berkeley nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2016, Olivier MATZ <zer0@droids-corp.org>
  */
 
 #include <stdio.h>
 #include <ecoli_test.h>
 #include <ecoli_strvec.h>
 #include <ecoli_node.h>
-#include <ecoli_parsed.h>
-#include <ecoli_completed.h>
+#include <ecoli_parse.h>
+#include <ecoli_complete.h>
 #include <ecoli_node_seq.h>
 #include <ecoli_node_many.h>
 #include <ecoli_node_or.h>
 #include <ecoli_node_weakref.h>
 #include <ecoli_node_expr.h>
 
+EC_LOG_TYPE_REGISTER(node_expr);
+
 struct ec_node_expr {
        struct ec_node gen;
 
@@ -67,20 +46,26 @@ struct ec_node_expr {
 };
 
 static int ec_node_expr_parse(const struct ec_node *gen_node,
-                       struct ec_parsed *state,
+                       struct ec_parse *state,
                        const struct ec_strvec *strvec)
 {
        struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
 
+       if (node->child == NULL)
+               return -ENOENT;
        return ec_node_parse_child(node->child, state, strvec);
 }
 
-static struct ec_completed *ec_node_expr_complete(const struct ec_node *gen_node,
-       const struct ec_strvec *strvec)
+static int
+ec_node_expr_complete(const struct ec_node *gen_node,
+               struct ec_comp *comp,
+               const struct ec_strvec *strvec)
 {
        struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
 
-       return ec_node_complete_strvec(node->child, strvec);
+       if (node->child == NULL)
+               return -ENOENT;
+       return ec_node_complete_child(node->child, comp, strvec);
 }
 
 static void ec_node_expr_free_priv(struct ec_node *gen_node)
@@ -88,7 +73,7 @@ static void ec_node_expr_free_priv(struct ec_node *gen_node)
        struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
        unsigned int i;
 
-       ec_log(EC_LOG_DEBUG, "free %p %p %p\n", node, node->child, node->val_node);
+       EC_LOG(EC_LOG_DEBUG, "free %p %p %p\n", node, node->child, node->val_node);
        ec_node_free(node->val_node);
 
        for (i = 0; i < node->bin_ops_len; i++)
@@ -110,21 +95,37 @@ static void ec_node_expr_free_priv(struct ec_node *gen_node)
        ec_node_free(node->child);
 }
 
-static int ec_node_expr_build(struct ec_node *gen_node)
+static int ec_node_expr_build(struct ec_node_expr *node)
 {
-       struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
        struct ec_node *term = NULL, *expr = NULL, *next = NULL,
                *pre_op = NULL, *post_op = NULL,
                *post = NULL, *weak = NULL;
        unsigned int i;
        int ret;
 
+       ec_node_free(node->child);
+       node->child = NULL;
+
        if (node->val_node == NULL)
                return -EINVAL;
        if (node->bin_ops_len == 0 && node->pre_ops_len == 0 &&
                        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;
@@ -156,12 +157,12 @@ static int ec_node_expr_build(struct ec_node *gen_node)
        if (ec_node_or_add(post, ec_node_clone(node->val_node)) < 0)
                goto fail;
        if (ec_node_or_add(post,
-               EC_NODE_SEQ(NULL,
+               EC_NODE_SEQ(EC_NO_ID,
                        ec_node_clone(pre_op),
                        ec_node_clone(weak))) < 0)
                goto fail;
        for (i = 0; i < node->paren_len; i++) {
-               if (ec_node_or_add(post, EC_NODE_SEQ(NULL,
+               if (ec_node_or_add(post, EC_NODE_SEQ(EC_NO_ID,
                                        ec_node_clone(node->open_ops[i]),
                                        ec_node_clone(weak),
                                        ec_node_clone(node->close_ops[i]))) < 0)
@@ -169,7 +170,7 @@ static int ec_node_expr_build(struct ec_node *gen_node)
        }
        term = EC_NODE_SEQ("term",
                ec_node_clone(post),
-               ec_node_many(NULL, ec_node_clone(post_op), 0, 0)
+               ec_node_many(EC_NO_ID, ec_node_clone(post_op), 0, 0)
        );
        if (term == NULL)
                goto fail;
@@ -177,8 +178,8 @@ static int ec_node_expr_build(struct ec_node *gen_node)
        for (i = 0; i < node->bin_ops_len; i++) {
                next = EC_NODE_SEQ("next",
                        ec_node_clone(term),
-                       ec_node_many(NULL,
-                               EC_NODE_SEQ(NULL,
+                       ec_node_many(EC_NO_ID,
+                               EC_NODE_SEQ(EC_NO_ID,
                                        ec_node_clone(node->bin_ops[i]),
                                        ec_node_clone(term)
                                ),
@@ -224,7 +225,6 @@ fail:
 
 static struct ec_node_type ec_node_expr_type = {
        .name = "expr",
-       .build = ec_node_expr_build,
        .parse = ec_node_expr_parse,
        .complete = ec_node_expr_complete,
        .size = sizeof(struct ec_node_expr),
@@ -238,18 +238,17 @@ int ec_node_expr_set_val_node(struct ec_node *gen_node, struct ec_node *val_node
        struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
        int ret;
 
+       ret = ec_node_check_type(gen_node, &ec_node_expr_type);
+       if (ret < 0)
+               return ret;
+
        ret = -EINVAL;
        if (val_node == NULL)
                goto fail;
-       ret = -EPERM;
-       if (gen_node->flags & EC_NODE_F_BUILT)
-               goto fail;
-       ret = -EEXIST;
-       if (node->val_node != NULL)
-               goto fail;
 
+       ec_node_free(node->val_node);
        node->val_node = val_node;
-       gen_node->flags &= ~EC_NODE_F_BUILT;
+       ec_node_expr_build(node);
 
        return 0;
 
@@ -265,14 +264,13 @@ int ec_node_expr_add_bin_op(struct ec_node *gen_node, struct ec_node *op)
        struct ec_node **bin_ops;
        int ret;
 
-       // XXX check node type
+       ret = ec_node_check_type(gen_node, &ec_node_expr_type);
+       if (ret < 0)
+               return ret;
 
        ret = -EINVAL;
        if (node == NULL || op == NULL)
                goto fail;
-       ret = -EPERM;
-       if (gen_node->flags & EC_NODE_F_BUILT)
-               goto fail;
 
        ret = -ENOMEM;
        bin_ops = ec_realloc(node->bin_ops,
@@ -283,7 +281,7 @@ int ec_node_expr_add_bin_op(struct ec_node *gen_node, struct ec_node *op)
        node->bin_ops = bin_ops;
        bin_ops[node->bin_ops_len] = op;
        node->bin_ops_len++;
-       gen_node->flags &= ~EC_NODE_F_BUILT;
+       ec_node_expr_build(node);
 
        return 0;
 
@@ -299,14 +297,13 @@ int ec_node_expr_add_pre_op(struct ec_node *gen_node, struct ec_node *op)
        struct ec_node **pre_ops;
        int ret;
 
-       // XXX check node type
+       ret = ec_node_check_type(gen_node, &ec_node_expr_type);
+       if (ret < 0)
+               return ret;
 
        ret = -EINVAL;
        if (node == NULL || op == NULL)
                goto fail;
-       ret = -EPERM;
-       if (gen_node->flags & EC_NODE_F_BUILT)
-               goto fail;
 
        ret = -ENOMEM;
        pre_ops = ec_realloc(node->pre_ops,
@@ -317,7 +314,7 @@ int ec_node_expr_add_pre_op(struct ec_node *gen_node, struct ec_node *op)
        node->pre_ops = pre_ops;
        pre_ops[node->pre_ops_len] = op;
        node->pre_ops_len++;
-       gen_node->flags &= ~EC_NODE_F_BUILT;
+       ec_node_expr_build(node);
 
        return 0;
 
@@ -333,14 +330,13 @@ int ec_node_expr_add_post_op(struct ec_node *gen_node, struct ec_node *op)
        struct ec_node **post_ops;
        int ret;
 
-       // XXX check node type
+       ret = ec_node_check_type(gen_node, &ec_node_expr_type);
+       if (ret < 0)
+               return ret;
 
        ret = -EINVAL;
        if (node == NULL || op == NULL)
                goto fail;
-       ret = -EPERM;
-       if (gen_node->flags & EC_NODE_F_BUILT)
-               goto fail;
 
        ret = -ENOMEM;
        post_ops = ec_realloc(node->post_ops,
@@ -351,7 +347,7 @@ int ec_node_expr_add_post_op(struct ec_node *gen_node, struct ec_node *op)
        node->post_ops = post_ops;
        post_ops[node->post_ops_len] = op;
        node->post_ops_len++;
-       gen_node->flags &= ~EC_NODE_F_BUILT;
+       ec_node_expr_build(node);
 
        return 0;
 
@@ -368,14 +364,13 @@ int ec_node_expr_add_parenthesis(struct ec_node *gen_node,
        struct ec_node **open_ops, **close_ops;
        int ret;
 
-       // XXX check node type
+       ret = ec_node_check_type(gen_node, &ec_node_expr_type);
+       if (ret < 0)
+               return ret;
 
        ret = -EINVAL;
        if (node == NULL || open == NULL || close == NULL)
                goto fail;
-       ret = -EPERM;
-       if (gen_node->flags & EC_NODE_F_BUILT)
-               goto fail;;
 
        ret = -ENOMEM;
        open_ops = ec_realloc(node->open_ops,
@@ -392,7 +387,7 @@ int ec_node_expr_add_parenthesis(struct ec_node *gen_node,
        open_ops[node->paren_len] = open;
        close_ops[node->paren_len] = close;
        node->paren_len++;
-       gen_node->flags &= ~EC_NODE_F_BUILT;
+       ec_node_expr_build(node);
 
        return 0;
 
@@ -411,6 +406,7 @@ enum expr_node_type {
        PAREN_OPEN,
        PAREN_CLOSE,
 };
+
 static enum expr_node_type get_node_type(const struct ec_node *expr_gen_node,
        const struct ec_node *check)
 {
@@ -448,7 +444,7 @@ static enum expr_node_type get_node_type(const struct ec_node *expr_gen_node,
 struct result {
        bool has_val;
        void *val;
-       const struct ec_parsed *op;
+       const struct ec_parse *op;
        enum expr_node_type op_type;
 };
 
@@ -509,32 +505,32 @@ static int eval_expression(struct result *result,
        void *userctx,
        const struct ec_node_expr_eval_ops *ops,
        const struct ec_node *expr_gen_node,
-       const struct ec_parsed *parsed)
+       const struct ec_parse *parse)
 
 {
-       struct ec_parsed *open = NULL, *close = NULL;
+       struct ec_parse *open = NULL, *close = NULL;
        struct result child_result;
-       struct ec_parsed *child;
+       struct ec_parse *child;
        enum expr_node_type type;
        int ret;
 
        memset(result, 0, sizeof(*result));
        memset(&child_result, 0, sizeof(child_result));
 
-       type = get_node_type(expr_gen_node, parsed->node);
+       type = get_node_type(expr_gen_node, ec_parse_get_node(parse));
        if (type == VAL) {
-               ret = ops->eval_var(&result->val, userctx, parsed);
+               ret = ops->eval_var(&result->val, userctx, parse);
                if (ret < 0)
                        goto fail;
                result->has_val = 1;
        } else if (type == PRE_OP || type == POST_OP || type == BIN_OP) {
-               result->op = parsed;
+               result->op = parse;
                result->op_type = type;
        }
 
-       TAILQ_FOREACH(child, &parsed->children, next) {
+       EC_PARSE_FOREACH_CHILD(child, parse) {
 
-               type = get_node_type(expr_gen_node, child->node);
+               type = get_node_type(expr_gen_node, ec_parse_get_node(child));
                if (type == PAREN_OPEN) {
                        open = child;
                        continue;
@@ -575,7 +571,7 @@ fail:
 }
 
 int ec_node_expr_eval(void **user_result, const struct ec_node *node,
-       struct ec_parsed *parsed, const struct ec_node_expr_eval_ops *ops,
+       struct ec_parse *parse, const struct ec_node_expr_eval_ops *ops,
        void *userctx)
 {
        struct result result;
@@ -586,11 +582,14 @@ int ec_node_expr_eval(void **user_result, const struct ec_node *node,
                        ops->eval_parenthesis == NULL || ops->eval_free == NULL)
                return -EINVAL;
 
-       if (!ec_parsed_matches(parsed))
+       ret = ec_node_check_type(node, &ec_node_expr_type);
+       if (ret < 0)
+               return ret;
+
+       if (!ec_parse_matches(parse))
                return -EINVAL;
 
-       ec_parsed_dump(stdout, parsed); //XXX
-       ret = eval_expression(&result, userctx, ops, node, parsed);
+       ret = eval_expression(&result, userctx, ops, node, parse);
        if (ret < 0)
                return ret;