#include <stdio.h>
#include <stdlib.h>
+#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <ecoli_node.h>
#include <ecoli_parsed.h>
+int ec_node_parse_child(struct ec_node *node, struct ec_parsed *state,
+ const struct ec_strvec *strvec)
+{
+ struct ec_strvec *match_strvec;
+ struct ec_parsed *child;
+ int ret;
+
+ assert(state != NULL);
+
+ /* build the node if required */
+ if (node->type->build != NULL) {
+ if ((node->flags & EC_NODE_F_BUILT) == 0) {
+ ret = node->type->build(node);
+ if (ret < 0)
+ return ret;
+ }
+ }
+ node->flags |= EC_NODE_F_BUILT;
+
+ if (node->type->parse == NULL)
+ return -ENOTSUP;
+
+ child = ec_parsed();
+ if (child == NULL)
+ return -ENOMEM;
+
+ child->node = node;
+ ec_parsed_add_child(state, child);
+ ret = node->type->parse(node, child, strvec);
+ if (ret == EC_PARSED_NOMATCH) {
+ ec_parsed_del_child(state, child);
+ assert(TAILQ_EMPTY(&child->children));
+ ec_parsed_free(child);
+ return ret;
+ } else if (ret < 0) {
+ return ret;
+ }
+
+ match_strvec = ec_strvec_ndup(strvec, 0, ret);
+ if (match_strvec == NULL)
+ return -ENOMEM;
+
+ child->strvec = match_strvec;
+
+ return ret;
+}
+
+struct ec_parsed *ec_node_parse_strvec(struct ec_node *node,
+ const struct ec_strvec *strvec)
+{
+ struct ec_parsed *parsed = ec_parsed();
+ struct ec_parsed *child_parsed;
+ int ret;
+
+ if (parsed == NULL)
+ return NULL;
+
+ ret = ec_node_parse_child(node, parsed, strvec);
+ if (ret < 0 && ret != EC_PARSED_NOMATCH) {
+ ec_parsed_free(parsed);
+ parsed = NULL;
+ } else if (ret != EC_PARSED_NOMATCH) {
+ /* remove dummy root node */
+ child_parsed = ec_parsed_get_last_child(parsed);
+ ec_parsed_del_child(parsed, child_parsed);
+ ec_parsed_free(parsed);
+ parsed = child_parsed;
+ }
+
+ return parsed;
+}
+
struct ec_parsed *ec_node_parse(struct ec_node *node, const char *str)
{
struct ec_strvec *strvec = NULL;
- struct ec_parsed *parsed;
+ struct ec_parsed *parsed = NULL;
errno = ENOMEM;
strvec = ec_strvec();
fail:
ec_strvec_free(strvec);
+ ec_parsed_free(parsed);
return NULL;
}
-struct ec_parsed *ec_node_parse_strvec(struct ec_node *node,
- const struct ec_strvec *strvec)
-{
- struct ec_parsed *parsed;
- int ret;
-
- /* build the node if required */
- if (node->type->build != NULL) {
- if ((node->flags & EC_NODE_F_BUILT) == 0) {
- ret = node->type->build(node);
- if (ret < 0) {
- errno = -ret;
- return NULL;
- }
- }
- }
- node->flags |= EC_NODE_F_BUILT;
-
- if (node->type->parse == NULL) {
- errno = ENOTSUP;
- return NULL;
- }
-
- parsed = node->type->parse(node, strvec);
-
- return parsed;
-}
-
-
struct ec_parsed *ec_parsed(void)
{
struct ec_parsed *parsed = NULL;
return NULL;
}
-void ec_parsed_set_match(struct ec_parsed *parsed,
- const struct ec_node *node, struct ec_strvec *strvec)
-{
- parsed->node = node;
- parsed->strvec = strvec;
-}
-
void ec_parsed_free_children(struct ec_parsed *parsed)
{
struct ec_parsed *child;
struct ec_parsed *child;
const struct ec_strvec *vec;
size_t i;
- const char *id = "None", *typename = "None";
+ const char *id = "none", *typename = "none";
if (parsed->node != NULL) {
if (parsed->node->id != NULL)
fprintf(out, "|");
}
- fprintf(out, "node_type=%s id=%s vec=[", typename, id);
+ fprintf(out, "node_type=%s id=%s vec=", typename, id);
vec = ec_parsed_strvec(parsed);
- for (i = 0; i < ec_strvec_len(vec); i++)
- fprintf(out, "%s<%s>",
- i == 0 ? "" : ",",
- ec_strvec_val(vec, i));
- fprintf(out, "]\n");
+ ec_strvec_dump(out, vec);
TAILQ_FOREACH(child, &parsed->children, next)
__ec_parsed_dump(out, child, indent + 2);
struct ec_parsed *child)
{
TAILQ_INSERT_TAIL(&parsed->children, child, next);
+ child->parent = parsed;
}
-void ec_parsed_del_child(struct ec_parsed *parsed,
+void ec_parsed_del_child(struct ec_parsed *parsed, // XXX rename del in unlink?
struct ec_parsed *child)
{
TAILQ_REMOVE(&parsed->children, child, next);
+ child->parent = NULL;
+}
+
+struct ec_parsed *
+ec_parsed_get_last_child(struct ec_parsed *parsed)
+{
+ return TAILQ_LAST(&parsed->children, ec_parsed_list);
+}
+
+void ec_parsed_del_last_child(struct ec_parsed *parsed) // rename in free
+{
+ struct ec_parsed *child;
+
+ child = ec_parsed_get_last_child(parsed);
+ ec_parsed_del_child(parsed, child);
+ ec_parsed_free(child);
+}
+
+struct ec_parsed *ec_parsed_get_root(struct ec_parsed *parsed)
+{
+ if (parsed == NULL)
+ return NULL;
+
+ while (parsed->parent != NULL)
+ parsed = parsed->parent;
+
+ return parsed;
+}
+
+struct ec_parsed *ec_parsed_get_parent(struct ec_parsed *parsed)
+{
+ if (parsed == NULL)
+ return NULL;
+
+ return parsed->parent;
}
struct ec_parsed *ec_parsed_find_first(struct ec_parsed *parsed,
return NULL;
}
-const struct ec_strvec *ec_parsed_strvec(
- const struct ec_parsed *parsed)
+const struct ec_strvec *ec_parsed_strvec(const struct ec_parsed *parsed)
{
if (parsed == NULL || parsed->strvec == NULL)
return NULL;
if (parsed == NULL)
return 0;
- if (parsed->node == NULL && TAILQ_EMPTY(&parsed->children))
+ if (parsed->node == NULL && TAILQ_EMPTY(&parsed->children)) // XXX both needed?
return 0;
return 1;