{
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);
}
{
struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
+ if (node->child == NULL)
+ return -ENOENT;
return ec_node_complete_child(node->child, completed, strvec);
}
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;
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)
}
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;
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)
),
weak = NULL;
node->child = expr;
- //ec_node_dump(stdout, node->child); //XXX
return 0;
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),
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;
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,
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;
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,
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;
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,
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;
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,
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;
ops->eval_parenthesis == NULL || ops->eval_free == NULL)
return -EINVAL;
+ ret = ec_node_check_type(node, &ec_node_expr_type);
+ if (ret < 0)
+ return ret;
+
if (!ec_parsed_matches(parsed))
return -EINVAL;
- //ec_parsed_dump(stdout, parsed); //XXX
ret = eval_expression(&result, userctx, ops, node, parsed);
if (ret < 0)
return ret;