|
Libecoli 0.11.1
Extensible COmmand LIne library
|
Libecoli is written in C and provides an API for building interactive command line interfaces. The library consists of several components:
Nodes are organized into a directed graph that defines the grammar. Although this structure is typically a tree, loops are permitted in certain cases. The grammar graph describes how input is parsed and completed.
Consider the following example:
The same structure can be represented textually as:
This grammar matches:
It does not match:
When libecoli parses input, it traverses the grammar graph using depth-first search and constructs a parse tree. The following example illustrates the process when ec_parse_strvec() is called:
When a node fails to match, it returns EC_PARSE_NOMATCH to its parent. This value propagates up the tree until a node handles the failure. For example, the or node tries each child in sequence until one matches.
Consider another example grammar:
Without a lexer node, the input must already be tokenized. This grammar matches:
It does not match:
During parsing, a parse tree is constructed. When parsing succeeds, the tree describes which grammar nodes matched and what input each node consumed.
Parsing ["bar", "1"] produces the following parse tree:
Each parse tree node references the grammar node that matched and stores the corresponding input tokens:
Not all grammar nodes appear in the parse tree. In this example, str("foo") was not matched and therefore does not appear. Conversely, a single grammar node may appear multiple times in the parse tree. Consider this grammar that matches zero or more occurrences of foo:
Parsing [foo, foo, foo] produces:
Each grammar node may have an optional string identifier. This identifier enables locating specific nodes in the parse tree after parsing completes. For example, a node created with ec_node_int("COUNT", 0, 100, 10) can be found using ec_pnode_find(parse_tree, "COUNT").
Identifiers need not be unique within the grammar graph. When multiple nodes share the same identifier, ec_pnode_find() returns the first match. Use ec_pnode_find_next() to iterate through additional matches.
The completion mechanism operates similarly to parsing but collects possible continuations instead of validating input. When the user requests completion, libecoli traverses the grammar graph and queries each node for tokens that could follow the current partial input.
Completions are grouped by the grammar node that produced them. Each completion item has one of three types:
Grammar nodes support arbitrary key-value attributes. The interactive layer uses these attributes to store:
Use ec_node_attrs() to access the attribute dictionary and manipulate it with ec_dict_set() and ec_dict_get(). The Interactive command line API provides convenience functions such as ec_interact_set_help() and ec_interact_set_callback().
Nodes support a generic configuration system for setting parameters after creation. Each node type defines a schema describing its configuration options. The YAML parser uses this system to instantiate nodes from configuration files.
See Node configuration for details.