* strings) matches the node tree. On success, the result is stored in a
* tree that describes which part of the input matches which node.
*
+ * The parsing tree is sometimes referenced by another node than the
+ * root node. Use ec_pnode_get_root() to get the root node in that case.
* @}
*/
struct ec_pnode;
/**
- * Create an empty parse tree.
+ * Create an empty parsing tree.
*
+ * This function is used internally when parsing an input using
+ * a grammar tree.
+ *
+ * @param node
+ * The grammar node.
* @return
* The empty parse tree.
*/
struct ec_pnode *ec_pnode(const struct ec_node *node);
/**
+ * Free a parsing tree.
*
- *
- *
+ * @param pnode
+ * The root of the parsing tree to be freed. It must not have
+ * any parent.
*/
void ec_pnode_free(struct ec_pnode *pnode);
/**
+ * Remove and free all the children of a parsing tree node.
*
- *
- *
+ * @param pnode
+ * Node whose children will be freed.
*/
void ec_pnode_free_children(struct ec_pnode *pnode);
/**
+ * Duplicate a parsing tree.
*
- *
- *
+ * @param pnode
+ * A node inside a parsing tree.
+ * @return
+ * A pointer to the copy of the input node, at the same place in the
+ * copy of the parsing tree. Return NULL on error (errno is set).
*/
struct ec_pnode *ec_pnode_dup(const struct ec_pnode *pnode);
/**
+ * Get the string vector associated to a parsing node.
*
+ * When an input is parsed successfully (i.e. the input string vector
+ * matches the grammar tree), the matching string vector is copied
+ * inside the associated parsing node.
*
+ * For instance, parsing the input ["foo", "bar"] on a grammar which is
+ * a sequence of strings, the attached string vector will be ["foo",
+ * "bar"] on the root pnode, ["foo"] on the first leaf, and ["bar"] on
+ * the second leaf.
*
+ * If the parsing tree does not match (see ec_pnode_matches()), it
+ * the associated string vector is NULL.
+ *
+ * @param pnode
+ * The parsing node. If NULL, the function returns NULL.
+ * @return
+ * The string vector associated to the parsing node, or NULL
+ * if the node is not yet parsed (this happens when building the
+ * parsing tree), or if the parsing tree does not match the
+ * input.
*/
-// _get_ XXX
-const struct ec_strvec *ec_pnode_strvec(const struct ec_pnode *pnode);
+const struct ec_strvec *ec_pnode_get_strvec(const struct ec_pnode *pnode);
-/* a NULL return value is an error, with errno set
- ENOTSUP: no ->parse() operation
-*/
/**
+ * Parse a string using a grammar tree.
*
+ * This is equivalent to calling ec_parse_strvec() on the same
+ * node, with a string vector containing only the argument string str.
*
- *
+ * @param node
+ * The grammar node.
+ * @param str
+ * The input string.
+ * @return
+ * A parsing tree, or NULL on error (errno is set).
*/
struct ec_pnode *ec_parse(const struct ec_node *node, const char *str);
/**
+ * Parse a string vector using a grammar tree.
*
+ * Generate a parsing tree by parsing the input string vector using the
+ * given grammar tree.
*
+ * The parsing tree is composed of struct ec_pnode, and each of them is
+ * associated to a struct ec_node (the grammar node), to the string vector
+ * that matched the subtree, and to optional attributes.
*
+ * When the input matches the grammar tree, the string vector associated
+ * to the root node of the returned parsing tree is the same than the
+ * strvec argument. Calling ec_pnode_matches() on this tree returns true.
+ *
+ * If the input does not match the grammar tree, the returned parsing
+ * tree only contains one root node, with no associated string vector.
+ * Calling ec_pnode_matches() on this tree returns false.
+ *
+ * @param node
+ * The grammar node.
+ * @param str
+ * The input string vector.
+ * @return
+ * A parsing tree, or NULL on error (errno is set).
*/
struct ec_pnode *ec_parse_strvec(const struct ec_node *node,
const struct ec_strvec *strvec);
return __ec_parse_child(node, pstate, false, strvec);
}
-// XXX what is returned if no match ??
struct ec_pnode *ec_parse_strvec(const struct ec_node *node,
const struct ec_strvec *strvec)
{
- struct ec_pnode *parse = ec_pnode(node);
+ struct ec_pnode *pnode = ec_pnode(node);
int ret;
- if (parse == NULL)
+ if (pnode == NULL)
return NULL;
- ret = __ec_parse_child(node, parse, true, strvec);
+ ret = __ec_parse_child(node, pnode, true, strvec);
if (ret < 0) {
- ec_pnode_free(parse);
+ ec_pnode_free(pnode);
return NULL;
}
- return parse;
+ return pnode;
}
struct ec_pnode *ec_parse(const struct ec_node *node, const char *str)
{
struct ec_strvec *strvec = NULL;
- struct ec_pnode *parse = NULL;
+ struct ec_pnode *pnode = NULL;
errno = ENOMEM;
strvec = ec_strvec();
if (ec_strvec_add(strvec, str) < 0)
goto fail;
- parse = ec_parse_strvec(node, strvec);
- if (parse == NULL)
+ pnode = ec_parse_strvec(node, strvec);
+ if (pnode == NULL)
goto fail;
ec_strvec_free(strvec);
- return parse;
+ return pnode;
fail:
ec_strvec_free(strvec);
- ec_pnode_free(parse);
+ ec_pnode_free(pnode);
return NULL;
}
struct ec_pnode *ec_pnode(const struct ec_node *node)
{
- struct ec_pnode *parse = NULL;
+ struct ec_pnode *pnode = NULL;
- parse = ec_calloc(1, sizeof(*parse));
- if (parse == NULL)
+ pnode = ec_calloc(1, sizeof(*pnode));
+ if (pnode == NULL)
goto fail;
- TAILQ_INIT(&parse->children);
+ TAILQ_INIT(&pnode->children);
- parse->node = node;
- parse->attrs = ec_dict();
- if (parse->attrs == NULL)
+ pnode->node = node;
+ pnode->attrs = ec_dict();
+ if (pnode->attrs == NULL)
goto fail;
- return parse;
+ return pnode;
fail:
- if (parse != NULL)
- ec_dict_free(parse->attrs);
- ec_free(parse);
+ if (pnode != NULL)
+ ec_dict_free(pnode->attrs);
+ ec_free(pnode);
return NULL;
}
return NULL;
}
-struct ec_pnode *ec_pnode_dup(const struct ec_pnode *parse)
+struct ec_pnode *ec_pnode_dup(const struct ec_pnode *pnode)
{
const struct ec_pnode *root;
struct ec_pnode *dup_root, *dup = NULL;
- root = ec_pnode_get_root(parse);
- dup_root = __ec_pnode_dup(root, parse, &dup);
+ root = ec_pnode_get_root(pnode);
+ dup_root = __ec_pnode_dup(root, pnode, &dup);
if (dup_root == NULL)
return NULL;
assert(dup != NULL);
return dup;
}
-void ec_pnode_free_children(struct ec_pnode *parse)
+void ec_pnode_free_children(struct ec_pnode *pnode)
{
struct ec_pnode *child;
- if (parse == NULL)
+ if (pnode == NULL)
return;
- while (!TAILQ_EMPTY(&parse->children)) {
- child = TAILQ_FIRST(&parse->children);
- TAILQ_REMOVE(&parse->children, child, next);
+ while (!TAILQ_EMPTY(&pnode->children)) {
+ child = TAILQ_FIRST(&pnode->children);
+ TAILQ_REMOVE(&pnode->children, child, next);
child->parent = NULL;
ec_pnode_free(child);
}
}
-void ec_pnode_free(struct ec_pnode *parse)
+void ec_pnode_free(struct ec_pnode *pnode)
{
- if (parse == NULL)
+ if (pnode == NULL)
return;
- ec_assert_print(parse->parent == NULL,
+ ec_assert_print(pnode->parent == NULL,
"parent not NULL in ec_pnode_free()");
- ec_pnode_free_children(parse);
- ec_strvec_free(parse->strvec);
- ec_dict_free(parse->attrs);
- ec_free(parse);
+ ec_pnode_free_children(pnode);
+ ec_strvec_free(pnode->strvec);
+ ec_dict_free(pnode->attrs);
+ ec_free(pnode);
}
static void __ec_pnode_dump(FILE *out,
- const struct ec_pnode *parse, size_t indent)
+ const struct ec_pnode *pnode, size_t indent)
{
struct ec_pnode *child;
const struct ec_strvec *vec;
const char *id = "none", *typename = "none";
/* node can be null when parsing is incomplete */
- if (parse->node != NULL) {
- id = ec_node_id(parse->node);
- typename = ec_node_type(parse->node)->name;
+ if (pnode->node != NULL) {
+ id = ec_node_id(pnode->node);
+ typename = ec_node_type(pnode->node)->name;
}
fprintf(out, "%*s" "type=%s id=%s vec=",
(int)indent * 4, "", typename, id);
- vec = ec_pnode_strvec(parse);
+ vec = ec_pnode_get_strvec(pnode);
ec_strvec_dump(out, vec);
- TAILQ_FOREACH(child, &parse->children, next)
+ TAILQ_FOREACH(child, &pnode->children, next)
__ec_pnode_dump(out, child, indent + 1);
}
-void ec_pnode_dump(FILE *out, const struct ec_pnode *parse)
+void ec_pnode_dump(FILE *out, const struct ec_pnode *pnode)
{
fprintf(out, "------------------- parse dump:\n");
- if (parse == NULL) {
- fprintf(out, "parse is NULL\n");
+ if (pnode == NULL) {
+ fprintf(out, "pnode is NULL\n");
return;
}
- /* only exist if it does not match (strvec == NULL) and if it
- * does not have children: an incomplete parse, like those
- * generated by complete() don't match but have children that
- * may match. */
- if (!ec_pnode_matches(parse) && TAILQ_EMPTY(&parse->children)) {
+ /* Do not dump if it does not match (strvec == NULL) and if it
+ * does not have children. Note that an incomplete parsing tree,
+ * like those generated by complete(), don't match but have
+ * children that may match, and we want to dump them. */
+ if (!ec_pnode_matches(pnode) && TAILQ_EMPTY(&pnode->children)) {
fprintf(out, "no match\n");
return;
}
- __ec_pnode_dump(out, parse, 0);
+ __ec_pnode_dump(out, pnode, 0);
}
-void ec_pnode_link_child(struct ec_pnode *parse,
+void ec_pnode_link_child(struct ec_pnode *pnode,
struct ec_pnode *child)
{
- TAILQ_INSERT_TAIL(&parse->children, child, next);
- child->parent = parse;
+ TAILQ_INSERT_TAIL(&pnode->children, child, next);
+ child->parent = pnode;
}
-void ec_pnode_unlink_child(struct ec_pnode *parse,
+void ec_pnode_unlink_child(struct ec_pnode *pnode,
struct ec_pnode *child)
{
- TAILQ_REMOVE(&parse->children, child, next);
+ TAILQ_REMOVE(&pnode->children, child, next);
child->parent = NULL;
}
struct ec_pnode *
-ec_pnode_get_first_child(const struct ec_pnode *parse)
+ec_pnode_get_first_child(const struct ec_pnode *pnode)
{
- return TAILQ_FIRST(&parse->children);
+ return TAILQ_FIRST(&pnode->children);
}
struct ec_pnode *
-ec_pnode_get_last_child(const struct ec_pnode *parse)
+ec_pnode_get_last_child(const struct ec_pnode *pnode)
{
- return TAILQ_LAST(&parse->children, ec_pnode_list);
+ return TAILQ_LAST(&pnode->children, ec_pnode_list);
}
-struct ec_pnode *ec_pnode_next(const struct ec_pnode *parse)
+struct ec_pnode *ec_pnode_next(const struct ec_pnode *pnode)
{
- return TAILQ_NEXT(parse, next);
+ return TAILQ_NEXT(pnode, next);
}
-bool ec_pnode_has_child(const struct ec_pnode *parse)
+bool ec_pnode_has_child(const struct ec_pnode *pnode)
{
- return !TAILQ_EMPTY(&parse->children);
+ return !TAILQ_EMPTY(&pnode->children);
}
-const struct ec_node *ec_pnode_get_node(const struct ec_pnode *parse)
+const struct ec_node *ec_pnode_get_node(const struct ec_pnode *pnode)
{
- if (parse == NULL)
+ if (pnode == NULL)
return NULL;
- return parse->node;
+ return pnode->node;
}
-void ec_pnode_del_last_child(struct ec_pnode *parse)
+void ec_pnode_del_last_child(struct ec_pnode *pnode)
{
struct ec_pnode *child;
- child = ec_pnode_get_last_child(parse);
- ec_pnode_unlink_child(parse, child);
+ child = ec_pnode_get_last_child(pnode);
+ ec_pnode_unlink_child(pnode, child);
ec_pnode_free(child);
}
-struct ec_pnode *__ec_pnode_get_root(struct ec_pnode *parse)
+struct ec_pnode *__ec_pnode_get_root(struct ec_pnode *pnode)
{
- if (parse == NULL)
+ if (pnode == NULL)
return NULL;
- while (parse->parent != NULL)
- parse = parse->parent;
+ while (pnode->parent != NULL)
+ pnode = pnode->parent;
- return parse;
+ return pnode;
}
-struct ec_pnode *ec_pnode_get_parent(const struct ec_pnode *parse)
+struct ec_pnode *ec_pnode_get_parent(const struct ec_pnode *pnode)
{
- if (parse == NULL)
+ if (pnode == NULL)
return NULL;
- return parse->parent;
+ return pnode->parent;
}
struct ec_pnode *__ec_pnode_iter_next(const struct ec_pnode *root,
- struct ec_pnode *parse, bool iter_children)
+ struct ec_pnode *pnode, bool iter_children)
{
struct ec_pnode *child, *parent, *next;
if (iter_children) {
- child = TAILQ_FIRST(&parse->children);
+ child = TAILQ_FIRST(&pnode->children);
if (child != NULL)
return child;
}
- parent = parse->parent;
- while (parent != NULL && parse != root) {
- next = TAILQ_NEXT(parse, next);
+ parent = pnode->parent;
+ while (parent != NULL && pnode != root) {
+ next = TAILQ_NEXT(pnode, next);
if (next != NULL)
return next;
- parse = parent;
- parent = parse->parent;
+ pnode = parent;
+ parent = pnode->parent;
}
return NULL;
}
return NULL;
}
-struct ec_pnode *ec_pnode_find(struct ec_pnode *parse,
+struct ec_pnode *ec_pnode_find(struct ec_pnode *pnode,
const char *id)
{
- return ec_pnode_find_next(parse, NULL, id, 1);
+ return ec_pnode_find_next(pnode, NULL, id, 1);
}
struct ec_dict *
-ec_pnode_get_attrs(struct ec_pnode *parse)
+ec_pnode_get_attrs(struct ec_pnode *pnode)
{
- if (parse == NULL)
+ if (pnode == NULL)
return NULL;
- return parse->attrs;
+ return pnode->attrs;
}
-const struct ec_strvec *ec_pnode_strvec(const struct ec_pnode *parse)
+const struct ec_strvec *ec_pnode_get_strvec(const struct ec_pnode *pnode)
{
- if (parse == NULL || parse->strvec == NULL)
+ if (pnode == NULL)
return NULL;
- return parse->strvec;
+ return pnode->strvec;
}
-/* number of strings in the parse vector */
-size_t ec_pnode_len(const struct ec_pnode *parse)
+/* number of strings in the parsed string vector */
+size_t ec_pnode_len(const struct ec_pnode *pnode)
{
- if (parse == NULL || parse->strvec == NULL)
+ if (pnode == NULL || pnode->strvec == NULL)
return 0;
- return ec_strvec_len(parse->strvec);
+ return ec_strvec_len(pnode->strvec);
}
-size_t ec_pnode_matches(const struct ec_pnode *parse)
+size_t ec_pnode_matches(const struct ec_pnode *pnode)
{
- if (parse == NULL)
+ if (pnode == NULL)
return 0;
- if (parse->strvec == NULL)
+ if (pnode->strvec == NULL)
return 0;
return 1;