X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=include%2Fecoli_node.h;h=129ca4dc495c525905d11745b3f21cca830f1aad;hb=70ebe6bd8740d8cb32cd0b0a21ca28a4fa74a2a5;hp=acd1daa455a2e29f8ee824934b8dcfd55227ea62;hpb=41bf1ba66e15c00f38375d05e49b31aa70f92349;p=protos%2Flibecoli.git diff --git a/include/ecoli_node.h b/include/ecoli_node.h index acd1daa..129ca4d 100644 --- a/include/ecoli_node.h +++ b/include/ecoli_node.h @@ -3,10 +3,13 @@ */ /** - * Interface to manage the ecoli nodes. + * @defgroup grammar_tree Grammar Tree + * @{ * - * A node is a main structure of the ecoli library, used to define how - * to match and complete the input tokens. A node is a generic object + * @brief Libecoli grammar nodes. + * + * The grammar node is a main structure of the ecoli library, used to define + * how to match and complete the input tokens. A node is a generic object * that implements: * - a parse(node, input) method: check if an input matches * - a complete(node, input) method: return possible completions for @@ -46,18 +49,28 @@ #include #include +/** + * Node has no identifier. + */ #define EC_NO_ID "no-id" -#define EC_NODE_ENDLIST ((void *)1) - struct ec_node; -struct ec_parse; +struct ec_pnode; struct ec_comp; struct ec_strvec; struct ec_dict; struct ec_config; struct ec_config_schema; +/** + * Register a node type at library load. + * + * The node type is registered in a function that has the the + * constructor attribute: the function is called at library load. + * + * @param t + * The name of the ec_node_type structure variable. + */ #define EC_NODE_TYPE_REGISTER(t) \ static void ec_node_init_##t(void); \ static void __attribute__((constructor, used)) \ @@ -69,16 +82,100 @@ struct ec_config_schema; t.name); \ } +/** + * A list of node types. + */ TAILQ_HEAD(ec_node_type_list, ec_node_type); +/** + * Function type used to configure a node. + * + * The function pointer is not called directly, the helper + * @ec_node_set_config() should be used instead. + * + * @param node + * The node to configure. + * @param config + * The configuration to apply to the node. + * @return + * 0 on success, negative on error (errno is set). + */ typedef int (*ec_node_set_config_t)(struct ec_node *node, const struct ec_config *config); -typedef int (*ec_node_parse_t)(const struct ec_node *node, - struct ec_parse *state, + +/** + * Parse a string vector using the given grammar tree. + * + * The function pointer is not called directly, the helpers @ec_parse(), + * ec_parse_strvec() or ec_parse_child() should be used instead. + * + * The implementation of this method for a node that manages children + * will call ec_parse_child(child, state, child_strvec). + * + * @param node + * The root node of the grammar tree. + * @param state + * A pointer to the leaf being parsed in the parsing tree. It can be + * used by a node to retrieve information from the current parsing + * tree. To get the root of the tree, @ec_pnode_get_root(state) should + * be used. + * @param strvec + * The string vector to be parsed. + * @return + * On success, return the number of consumed items in the string vector + * (can be 0) or EC_PARSE_NOMATCH if the node cannot parse the string + * vector. On error, a negative value is returned and errno is set. + */ +typedef int (*ec_parse_t)(const struct ec_node *node, + struct ec_pnode *state, const struct ec_strvec *strvec); -typedef int (*ec_node_complete_t)(const struct ec_node *node, - struct ec_comp *comp_state, + +/** + * Get completion items using the given grammar tree. + * + * The function pointer is not called directly, the helpers @ec_complete(), + * ec_complete_strvec() or ec_complete_child() should be used instead. + * + * This function completes the last element of the string vector. + * For instance, node.type->complete(node, comp, ["ls"]) will + * list all commands that starts with "ls", while + * node.type->complete(node, comp, ["ls", ""]) will list all + * possible values for the next argument. + + * The implementation of this function is supposed to either: + * - call @ec_comp_add_item(node, comp, ...) for each completion item + * that should be added to the list. This is done in terminal nodes, + * for example in ec_node_str or ec_node_file. + * - call @ec_complete_child(child, comp, child_strvec) to let + * the children nodes add their own completion. This is the + * case of ec_node_or which trivially calls @ec_complete_child() + * on all its children, and of ec_node_seq, which has to + * do a more complex job (parsing strvec). + * + * A node that does not provide any method for the completion + * will fallback to ec_complete_unknown(): this helper returns + * a completion item of type EC_COMP_UNKNOWN, just to indicate + * that everything before the last element of the string vector + * has been parsed successfully, but we don't know how to + * complete the last element. + * + * @param node + * The root node of the grammar tree. + * @param comp + * The current list of completion items, to be filled by the + * node.type->complete() method. + * @param strvec + * The string vector to be completed. + * @return + * 0 on success, or a negative value on error (errno is set). + */ +typedef int (*ec_complete_t)(const struct ec_node *node, + struct ec_comp *comp, const struct ec_strvec *strvec); + +/** + * + */ typedef const char * (*ec_node_desc_t)(const struct ec_node *); typedef int (*ec_node_init_priv_t)(struct ec_node *); typedef void (*ec_node_free_priv_t)(struct ec_node *); @@ -96,8 +193,8 @@ struct ec_node_type { * (.type = EC_CONFIG_TYPE_NONE). */ const struct ec_config_schema *schema; ec_node_set_config_t set_config; /* validate/ack a config change */ - ec_node_parse_t parse; - ec_node_complete_t complete; + ec_parse_t parse; + ec_complete_t complete; ec_node_desc_t desc; size_t size; ec_node_init_priv_t init_priv; @@ -152,20 +249,6 @@ enum ec_node_free_state { EC_NODE_FREE_STATE_FREEING, }; -struct ec_node { - const struct ec_node_type *type; - struct ec_config *config; /**< Generic configuration. */ - char *id; - char *desc; - struct ec_dict *attrs; - unsigned int refcnt; - struct { - enum ec_node_free_state state; /**< State of loop detection */ - unsigned int refcnt; /**< Number of reachable references - * starting from node beeing freed */ - } free; /**< Freeing state: used for loop detection */ -}; - /* create a new node when the type is known, typically called from the node * code */ struct ec_node *ec_node_from_type(const struct ec_node_type *type, const char *id); @@ -203,4 +286,18 @@ struct ec_node *ec_node_find(struct ec_node *node, const char *id); int ec_node_check_type(const struct ec_node *node, const struct ec_node_type *type); +const char *ec_node_get_type_name(const struct ec_node *node); + +/** + * Get the pointer to the node private area. + * + * @param node + * The grammar node. + * @return + * The pointer to the node private area. + */ +void *ec_node_priv(const struct ec_node *node); + #endif + + /** @} */