ecoli_nodes(3)
ecoli_nodes(3) β Grammar nodes, bestie π
Bestie, this is the Libecoli grammar-node page, and itβs lowkey the whole blueprint for matching and completing input tokens. Manual name: ecoli_nodes. Vibe: iconic. Letβs go. β¨
πΈ NAME πΈ
ecoli_nodes β Grammar nodes.
Also, literally: Libecoli grammar nodes.
π¦ SYNOPSIS π¦
π Modules π
- Any node β A node that matches any single token.
- Bypass node β A pass-through node useful for building graph loops.
- Command node β A node that parses commands using a format string.
- Condition node β A node that conditionally matches based on an expression.
- Dynamic node β A node built dynamically at parse time by a callback.
- Dynamic list node β A node that matches names from a dynamic list.
- Empty node β A node that matches an empty input.
- Expression node β A node for parsing and evaluating expressions with operators.
- File node β A node that matches and completes file paths.
- Integer node β Nodes that match signed or unsigned integers.
- Many node β A node that matches its child multiple times.
- None node β A node that never matches anything.
- Once node β A node that prevents its child from being parsed more than once.
- Option node β A node that makes its child optional.
- Or node β A node that matches one of its child nodes.
- Regex node β A node that matches input against a regular expression.
- Regex lexer node β A lexer node using regular expressions for tokenization.
- Sequence node β A node that matches a sequence of child nodes in order.
- Shell lexer node β A lexer node using shell-like tokenization rules.
- Space node β A node that matches whitespace.
- String node β A node that matches a specific string.
- Subset node β A node that matches any subset of its children in any order.
π Data Structures π
struct ec_node_type
π₯ Macros π₯
#define EC_NO_ID ''#define EC_NODE_TYPE_REGISTER(t)#define EC_NODE_TYPE_REGISTER_OVERRIDE(t)
π§ Typedefs π§
typedef int(* ec_node_set_config_t) (struct ec_node *node, const struct ec_config *config)typedef int(* ec_parse_t) (const struct ec_node *node, struct ec_pnode *pstate, const struct ec_strvec *strvec)typedef int(* ec_complete_t) (const struct ec_node *node, struct ec_comp *comp, const struct ec_strvec *strvec)typedef 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 *)typedef size_t(* ec_node_get_children_count_t) (const struct ec_node *)typedef int(* ec_node_get_child_t) (const struct ec_node *, size_t i, struct ec_node **child, unsigned int *refs)
π Functions π
int ec_node_type_register (struct ec_node_type *type, bool override)const struct ec_node_type * ec_node_type_lookup (const char *name)void ec_node_type_dump (FILE *out)const struct ec_config_schema * ec_node_type_schema (const struct ec_node_type *type)const char * ec_node_type_name (const struct ec_node_type *type)struct ec_node * ec_node_from_type (const struct ec_node_type *type, const char *id)struct ec_node * ec_node (const char *typename, const char *id)struct ec_node * ec_node_clone (struct ec_node *node)void ec_node_free (struct ec_node *node)int ec_node_set_config (struct ec_node *node, struct ec_config *config)const struct ec_config * ec_node_get_config (const struct ec_node *node)size_t ec_node_get_children_count (const struct ec_node *node)int ec_node_get_child (const struct ec_node *node, size_t i, struct ec_node **child)const struct ec_node_type * ec_node_type (const struct ec_node *node)struct ec_dict * ec_node_attrs (const struct ec_node *node)const char * ec_node_id (const struct ec_node *node)char * ec_node_desc (const struct ec_node *node)void ec_node_dump (FILE *out, const struct ec_node *node)struct ec_node * ec_node_find (struct ec_node *node, const char *id)struct ec_node_iter * ec_node_iter (struct ec_node *node)struct ec_node_iter * ec_node_iter_next (struct ec_node_iter *root, struct ec_node_iter *iter, bool iter_children)void ec_node_iter_free (struct ec_node_iter *iter)struct ec_node * ec_node_iter_get_node (struct ec_node_iter *iter)struct ec_node_iter * ec_node_iter_get_parent (struct ec_node_iter *iter)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)void * ec_node_priv (const struct ec_node *node)void ec_node_schema_dump (FILE *out, const struct ec_node *node)
π Variables π
struct ec_node_type_list node_type_list
π Detailed Description π
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 a given input - some other methods to initialize, free, ...
One basic example is the string node (ec_node_str()). A node ec_node_str('foo') will match any token list starting with 'foo', for example:
['foo']['foo', 'bar', ...]
But will not match:
[]['bar', ...]
A node ec_node_str('foo') will complete with 'foo' if the input contains one token, with the same beginning as 'foo':
['']['f']['fo']['foo']
But it will not complete:
[]['bar']['f', '']['', 'f']
A node can have child nodes. For instance, a sequence node ec_node_seq(ec_node_str('foo'), ec_node_str('bar')) will match a sequence: ['foo', 'bar'].
Note: at some places in the documentation and the code, we may talk about the grammar tree, but as loops are allowed, we should instead talk about grammar graph. Periodt. π
π₯ Macro Definition Documentation π₯
π #define EC_NO_ID '' π
Node has no identifier.
Definition at line 64 of file node.h.
π¦ #define EC_NODE_TYPE_REGISTER(t) π¦
Value:
static void ec_node_init_##t(void);
static void __attribute__((constructor, used)) ec_node_init_##t(void) { if (ec_node_type_register(&t, 0) < 0) fprintf(stderr, "cannot register node type %s0, t.name); }
Register a node type at library load.
The node type is registered in a function that has the constructor attribute: the function is called at library load.
Parameters:
tβ The name of theec_node_typestructure variable.
Definition at line 88 of file node.h.
π
#define EC_NODE_TYPE_REGISTER_OVERRIDE(t) π
Value:
static void ec_node_init_##t(void);
static void __attribute__((constructor, used)) ec_node_init_##t(void) { if (ec_node_type_register(&t, 1) < 0) fprintf(stderr, "cannot register node type %s0, t.name); }
Register a node type at library load, overriding previous registration.
The node type is registered in a function that has the constructor attribute: the function is called at library load.
Bestie, be careful when using this macro, as the last type with a given name is the one that is actually registered. The call order may be hard to predict, especially within the same binary. π
Parameters:
tβ The name of theec_node_typestructure variable.
Definition at line 109 of file node.h.
π Typedef Documentation π
okay bestie, this is the typedef zone β the little function-pointer blueprints that make ecoli nodes do their thing β¨ every single one matters, so letβs go.
πΈ ec_node_set_config_t β configure a node
typedef int(* ec_node_set_config_t) (struct ec_node *node, const struct ec_config *config)
Function type used to configure a node. iconic little callback π
The function pointer is not called directly β the helper ec_node_set_config() should be used instead.
The configuration passed to this function pointer is valid, i.e. ec_config_validate() returned 0 on it.
This function provided by a node type is supposed to do additional checks on the configuration and store private data, if needed. If it returns 0, ec_node_set_config() stores the generic configuration in the node. The function can just return 0 if nothing needs to be stored in private data. no cap, sometimes βdo nothingβ is the whole assignment π«Ά
Parameters
nodeβ The node to configure.configβ The configuration to apply to the node.
Returns
0 on success, negative on error (errno is set).
Definition at line 138 of file node.h.
π¦ ec_parse_t β parse a string vector using the grammar graph
typedef int(* ec_parse_t) (const struct ec_node *node, struct ec_pnode *pstate, const struct ec_strvec *strvec)
Parse a string vector using the given grammar graph. this is the main-character parser energy fr fr π₯
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, pstate, child_strvec).
Parameters
nodeβ The grammar graph.pstateβ 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(pstate)should be used.strvecβ The string vector to be parsed.
Returns
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.
Definition at line 163 of file node.h.
π ec_complete_t β get completion items using the grammar graph
typedef int(* ec_complete_t) (const struct ec_node *node, struct ec_comp *comp, const struct ec_strvec *strvec)
Get completion items using the given grammar graph. completion slay β¨
The function pointer should not be 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 start with 'ls', while node.type->complete(node, comp, ['ls', '']) will list all possible values for the next argument.
The implementation of this function in the node is supposed to either:
- call
ec_comp_add_item()for each completion item that should be added to the list. This is typically done in terminal nodes, for example inec_node_str()orec_node_file(). - call
ec_complete_child()to let the children nodes add their own completion. This is the case ofec_node_orwhich trivially callsec_complete_child()on all its children, and ofec_node_seq, which has to do a more complex job (parsingstrvec).
A node that does not provide any method for the completion will fall back 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. iykyk π
Parameters
nodeβ The root node of the grammar graph.compβ The current list of completion items, to be filled by thenode.type->complete()method.strvecβ The string vector to be completed.
Returns
0 on success, or a negative value on error (errno is set).
Definition at line 210 of file node.h.
π ec_node_desc_t β short description of a grammar node
typedef char*(* ec_node_desc_t) (const struct ec_node *)
Get the short description of a grammar node. cute lil help text generator π
This function pointer should not be called directly. The ec_node_desc() helper should be used instead.
This callback is typically used when building a help string for a grammar graph. It is used in ecoli editline interface to generate contextual help like this (first column):
<int> An integer.
foo The foo string.
bar The bar string.
If this callback is set to NULL in the node type, the default behavior is to return the node type name inside <>, for instance <int>. The string node type implements this method to return the string value. An integer node could implement it to return its range (e.g., '1..10').
The returned value is a pointer that must be freed by the caller with free().
On error, NULL is returned and errno is set.
Definition at line 241 of file node.h.
π§ ec_node_init_priv_t β initialize the node private area
typedef int(* ec_node_init_priv_t) (struct ec_node *)
Initialize the node private area. private data goes in its own little room π
This function pointer should not be called directly. The ec_node() and ec_node_from_type() helpers, that allocate new nodes, should be used instead.
If not NULL, this function is called when a node is instantiated, to initialize the private area of a node. In any case, the private area is first zeroed.
On success, 0 is returned. On error, a negative value is returned and errno is set.
Definition at line 257 of file node.h.
π ec_node_free_priv_t β free the node private area
typedef void(* ec_node_free_priv_t) (struct ec_node *)
Free the node private area. cleanup era β¨
This function pointer should not be called directly. The ec_node_free() helper should be used instead.
When a node is deleted, this function is called to free the resources referenced in the node private area.
Definition at line 268 of file node.h.
π ec_node_get_children_count_t β count the node children
typedef size_t(* ec_node_get_children_count_t) (const struct ec_node *)
Count the number of node children. how many little grammar babies? π«Ά
This function pointer should not be called directly. The ec_node_get_children_count() helper should be used instead.
Some grammar nodes like seq, or, many, (...), reference children nodes in the grammar graph. This function returns the number of children.
Definition at line 280 of file node.h.
π ec_node_get_child_t β get the i-th child node
typedef int(* ec_node_get_child_t) (const struct ec_node *, size_t i, struct ec_node **child, unsigned int *refs)
Get the i-th child node. indexed child retrieval, very demure π
This function pointer should not be called directly. The ec_node_get_child() helper should be used instead.
Some grammar nodes like seq, or, many, (...), reference children nodes in the grammar graph. This function sets the i-th child (with i lower than the return value of ec_node_get_children_count()) in the child pointer. It also returns the number of references to the child owned by the parent. This information is used by the algorithm that frees a grammar graph taking care of loops.
On success, 0 is returned. On error, a negative value is returned and errno is set.
Definition at line 298 of file node.h.
π FUNCTION DOCUMENTATION π
Bestie, this is the part where we meet literally every function in the whole API. Grab a snack π, we're going through all of them, no skips.
π§ ec_node_type_register
int ec_node_type_register (struct ec_node_type * type, bool override)
Registers a node type. Slay, your type is now in the system β¨
The name of the type being registered is a unique identifier β that's its whole thing. But you can force the registration of a type with an existing name by setting override to true π. Heads up though: the initial type is not removed from the list β instead the new one is added before it in the list. So it's giving "new kid walks in front of you in the lunch line", not "old kid vanishes".
Parameters
typeβ the node type to be registered.overrideβ allow the registration of an existing type.
Returns
0 on success, negative value on error π
πΈ ec_node_type_lookup
const struct ec_node_type* ec_node_type_lookup (const char * name)
Looks up a node type by name. Like a search bar but for types π
Parameters
nameβ the name of the node type to search.
Returns
The (read-only) node type if found, or NULL on error. Read-only, so don't even think about touching it π«Ά
π ec_node_type_dump
void ec_node_type_dump (FILE * out)
Dumps all registered node types. A little info-dump moment, iconic behavior π
Parameters
outβ the stream where the dump is sent.
π¦ ec_node_type_schema
const struct ec_config_schema* ec_node_type_schema (const struct ec_node_type * type)
Gets the config schema of a node type.
Parameters
typeβ the node type.
Returns
The (read-only) config schema of the node type, or NULL if the node type has no config schema. Some of them just don't have one and that's valid π
β ec_node_type_name
const char* ec_node_type_name (const struct ec_node_type * type)
Gets the name of a node type. Yeah, that's it, that's the whole function.
Parameters
typeβ the node type.
Returns
The (read-only) name of the node type. Again β read-only β hands off π
π ec_node_from_type
struct ec_node* ec_node_from_type (const struct ec_node_type * type, const char * id)
Creates a new node when the type is already known. This function is typically called from the node constructor, iykyk ποΈ
Parameters
typeβ the type of the node to create.idβ the node identifier.
Returns
The new node on success, or NULL on error.
π« ec_node
struct ec_node* ec_node (const char * typename, const char * id)
Creates a new node from its type name. This one is typically called from user code, for node types that don't provide a specific constructor β so when there's no custom builder, you use this β¨
Parameters
typenameβ the type name of the node to create.idβ the node identifier.
Returns
The new node on success, or NULL on error.
π«Ά ec_node_clone
struct ec_node* ec_node_clone (struct ec_node * node)
Clones a grammar node β copy-paste but make it official π
This function takes a reference to the node. If ec_node_free() is later called on this node, it will decrease only the reference. The free is effective when the reference count reaches 0. The reference counter is initialized to 1 at node creation. That's the whole lifecycle, no cap.
Parameters
nodeβ the node to clone.
Returns
The pointer to the cloned node, which is always equal to the parameter. It returns NULL if the parameter was NULL β in that case, nothing is done. Nothing. Zero. Nada π
π§ ec_node_free
void ec_node_free (struct ec_node * node)
Decrements the node reference counter and frees the node if it's the last reference. Classic refcount ending π
Parameters
nodeβ the grammar node to free.
π¦ ec_node_set_config
int ec_node_set_config (struct ec_node * node, struct ec_config * config)
Sets node configuration. For a node that supports generic configuration, this sets its configuration.
β οΈ Okay bestie, this part matters: after a call to this function, the config is owned by the node and must not be used by the caller anymore. It's not yours, it's the node's now. Periodt.
Parameters
nodeβ the grammar node to configure.configβ the configuration to apply on the node.
Returns
0 on success, or a negative value on error β and in that error case, the config passed as parameter is freed π¬
π ec_node_get_config
const struct ec_config* ec_node_get_config (const struct ec_node * node)
Gets the current node configuration. For a node that supports generic configuration, this reads its configuration.
Parameters
nodeβ the grammar node.
Returns
The generic node configuration on success, or NULL on error.
πΈ ec_node_get_children_count
size_t ec_node_get_children_count (const struct ec_node * node)
Returns the number of children for a node. Counting the kids, basically π
Parameters
nodeβ the grammar node.
Returns
The number of children.
β ec_node_get_child
int ec_node_get_child (const struct ec_node * node, size_t i, struct ec_node ** child)
Gets the n-th child of a node.
Parameters
nodeβ the grammar node.iβ the index of the child node, that must be lower than the number of children (don't push your luck π).childβ the pointer where the child node pointer will be stored on success.
Returns
0 on success, -1 on error.
π ec_node_type
const struct ec_node_type* ec_node_type (const struct ec_node * node)
Gets the type of a node.
Parameters
nodeβ the grammar node.
Returns
The type structure of this node.
π«Ά ec_node_attrs
struct ec_dict* ec_node_attrs (const struct ec_node * node)
Gets the attributes dict of the node.
A user can add any attribute to a node π¨. But β attributes keys starting with an underscore are reserved. That's the system's turf, don't touch π«
Parameters
nodeβ the grammar node.
Returns
The attribute dictionary of this node.
π« ec_node_id
const char* ec_node_id (const struct ec_node * node)
Gets the node identifier.
Parameters
nodeβ the grammar node.
Returns
The node identifier string.
π ec_node_desc
char* ec_node_desc (const struct ec_node * node)
Gets the node short description.
Parameters
nodeβ the grammar node.
Returns
An allocated string containing the node short description that must be freed by the caller. It's yours now, you're responsible for it π₯². Return NULL on error.
π§ ec_node_dump
void ec_node_dump (FILE * out, const struct ec_node * node)
Dumps a grammar tree. Look at the whole family tree π³
Parameters
outβ the stream where the dump is sent.nodeβ the grammar tree to dump.
π ec_node_find
struct ec_node* ec_node_find (struct ec_node * node, const char * id)
Finds a node from its identifier string.
Browse the tree using pre-order depth traversal, and return the first node that matches the given identifier. First match wins, no second chances π
Parameters
nodeβ the grammar tree.idβ the identifier to match.
Returns
A node matching the identifier.
π¦ ec_node_iter
struct ec_node_iter* ec_node_iter (struct ec_node * node)
Creates an iterator on a grammar tree.
Okay so β plot twist π«’ β a grammar tree is actually not really a tree, it's an oriented graph where loops can exist. Because of that, it is not possible to iterate the grammar graph without storing somewhere the list of browsed nodes in order to break loops. Gotta keep receipts of where you've been, fr fr.
Another property of grammar graphs: the same node can appear several times at different places in the graph, having a different parent. This kind of node will be iterated only once. One appearance and done π
The typical use is:
struct ec_node_iter *iter_root, *iter;
iter_root = ec_node_iter(node);
if (iter_root == NULL)
goto fail;
for (iter = iter_root; iter != NULL;
iter = ec_node_iter_next(iter_root, iter, true)) {
do_something_with(ec_node_iter_get_node(iter));
}
ec_node_iter_free(iter_root);
Technically, this function builds a tree from the grammar graph. Each node of this tree references a node of the grammar graph π±
Parameters
nodeβ the grammar graph to iterate
Returns
The grammar graph iterator on success, that must be freed using ec_node_iter_free(). Return NULL on error.
β ec_node_iter_next
struct ec_node_iter* ec_node_iter_next (struct ec_node_iter * root, struct ec_node_iter * iter, bool iter_children)
Iterates to the next node. See ec_node_iter() above, bestie π
Parameters
rootβ the iterator returned byec_node_iter().iterβ the current node in the iterator.iter_childrenβtrueto iterate the children ofiter,falseto skip them.
Returns
The next node of the iterator, or NULL if iteration is finished.
π ec_node_iter_free
void ec_node_iter_free (struct ec_node_iter * iter)
Frees a grammar graph iterator. Cleanup era π§Ή
Parameters
iterβ the iterator returned byec_node_iter()to free.
πΈ ec_node_iter_get_node
struct ec_node* ec_node_iter_get_node (struct ec_node_iter * iter)
Gets the grammar node referenced by the iterator node.
Parameters
iterβ the iterator node.
Returns
The associated grammar node.
π ec_node_iter_get_parent
struct ec_node_iter* ec_node_iter_get_parent (struct ec_node_iter * iter)
Gets the parent of an iterator node. Family reunion π¨βπ©βπ§
Parameters
iterβ the iterator node.
Returns
The parent of the iterator node in the iterator tree. Return NULL if it's the root β root nodes have no parent, they're the main characters π
π«Ά ec_node_check_type
int ec_node_check_type (const struct ec_node * node, const struct ec_node_type * type)
Checks the type of a node. The vibe check function, lowkey π΅οΈ
Parameters
nodeβ the grammar node.typeβ the pointer to the type structure.
Returns
0 if the node is of specified type, else -1.
π« ec_node_get_type_name
const char* ec_node_get_type_name (const struct ec_node * node)
Gets the type name of a grammar node.
Parameters
nodeβ the grammar node.
Returns
The type name of the node.
π ec_node_priv
void* ec_node_priv (const struct ec_node * node)
Gets the pointer to the node private area. Private means private, don't go snooping π
Parameters
nodeβ the grammar node.
Returns
The pointer to the node private area.
π§ ec_node_schema_dump
void ec_node_schema_dump (FILE * out, const struct ec_node * node)
Dumps the node configuration schema.
Parameters
outβ the stream where the dump is sent.nodeβ the grammar node.
π VARIABLE DOCUMENTATION π
struct ec_node_type_list node_type_list [extern]
The list of registered node types. Must not be modified by user, except at initialization using the EC_NODE_TYPE_REGISTER() or EC_NODE_TYPE_REGISTER_OVERRIDE() macros. Like, that's the one exception, and only at initialization. Respect the list π«‘
β¨ AUTHOR β¨
Generated automatically by Doxygen for Libecoli from the source code. Not me, I would've added more emoji π
Okay bestie, that's the end of ecoli_nodes(3) π«Ά This diva of a manpage is Libecoli version 0.11.3, dated Thu Apr 9 2026, and she ate. Periodt π
β¨ππ¦
π¦ where this page comes from
- epel 9: libecoli-devel 0.11.3-1.el9 Β· BSD-3-Clause AND LicenseRef-Fedora-Public-Domain
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms