An HML (Hica Markup Language) parser library written in hica.
HML is a structured configuration and document language that combines the semantic strength of XML (elements with identity/metadata) with the readability of TOML/YAML. See HML-Specification for the full v0.3 spec.
- Full HML v0.3 compliance
- Dotted keys with automatic merging (
database.host: "x") - Namespaced element names (
@k8s.deployment) #includedirective with nested and circular detection#namespacedirective for URI bindings#textdirective for text content mode (mixed text + inline elements)- Merge rule validation (dotted keys vs explicit elements)
- Date-time, duration, hex/octal/binary integer support
- Pretty-printing and compact display
Add as a git submodule to your hica project:
git submodule add https://github.com/cladam/hml.git lib/hmlThen import the library:
import "./lib/hml/src/hml"
// config.hml
@server(port: 8080, public) {
host: "localhost"
name: "api"
timeout: 30s
}
@database(driver: "postgres") {
host: "db.internal"
port: 5432
pool_size: 10
}
import "src/hml"
fun main() {
match read_file("config.hml") {
Ok(content) => {
match hml_parse(content) {
Ok(nodes) => {
match hml_elem(nodes, "server") {
Some(srv) => {
println("port: " + show(hml_attr(srv, "port")))
match hml_body(srv) {
Some(body) => println("host: " + show(at(body, "host") |> as_str)),
None => ()
}
},
None => ()
}
},
Err(e) => println("Parse error: " + e)
}
},
Err(e) => println("File error: " + e)
}
}
| Function | Signature | Description |
|---|---|---|
hml_parse |
string -> result<list<HmlNode>, string> |
Parse an HML document |
hml_parse_file |
string -> result<list<HmlNode>, string> |
Parse a file with #include support |
hml_parse_file_content |
(string, string) -> result<list<HmlNode>, string> |
Parse content with a base path for includes |
| Function | Description |
|---|---|
hml_elem(nodes, name) |
Find first element by name |
hml_elems(nodes, name) |
Collect all elements with given name |
hml_get(nodes, key) |
Find property value by key |
hml_body(elem) |
Get element body (child nodes) |
hml_attrs(elem) |
Get element attribute list |
hml_attr(elem, key) |
Get specific attribute value |
| Function | Description |
|---|---|
hml_str(v) |
Extract string from Hml value |
hml_int(v) |
Extract integer |
hml_bool(v) |
Extract boolean |
hml_float(v) |
Extract float |
hml_duration(v) |
Extract (amount, unit) tuple |
hml_datetime(v) |
Extract datetime string |
hml_list(v) |
Extract array items |
| Function | Description |
|---|---|
hml_namespaces(nodes) |
Get all (prefix, uri) bindings |
hml_namespace(nodes, prefix) |
Look up URI for a namespace prefix |
| Function | Description |
|---|---|
at(nodes, key) |
Alias for hml_get |
elem_at(nodes, name) |
Alias for hml_elem |
as_str(maybe_val) |
Pipe-friendly string extractor |
as_int(maybe_val) |
Pipe-friendly int extractor |
as_bool(maybe_val) |
Pipe-friendly bool extractor |
as_datetime(maybe_val) |
Pipe-friendly datetime extractor |
hml_ok(result) |
Convert result to maybe |
| Function | Description |
|---|---|
hml_show(v) |
Compact single-line display |
hml_pretty(nodes, indent) |
Pretty-print with indentation |
type Hml {
HStr(value: string),
HInt(value: int),
HFloat(value: float),
HBool(value: bool),
HDuration(amount: int, unit: string),
HDatetime(value: string),
HNull,
HArray(items: list<Hml>),
HElement(name: string, attrs: list<(string, Hml)>, body: list<HmlNode>)
}
type HmlNode {
NProp(key: string, value: Hml),
NElem(element: Hml),
NText(content: string),
NComment(text: string),
NNamespace(ns_prefix: string, uri: string)
}
hica test tests/test_values.hc
hica test tests/test_elements.hc
hica test tests/test_document.hc
hica test tests/test_api.hc
hica test tests/test_errors.hc
hica test tests/test_include.hc
hica test tests/test_text.hcSee the examples/ directory:
basic.hc: Parse HML from a string literalread_config.hc: Read and parse an external.hmlfilenested.hc: Navigate deeply nested elementsrepeated.hc: Work with repeated elements (implicit arrays)include.hc: Compose configs from multiple files with#include
MIT