ucg 0.8.0

A configuration generation grammar.
Documentation

let schema = import "std/schema.ucg";

// Validates that a namespace is the right shape for an xml tag or document.
let validate_ns = func(ns) => schema.any{val=ns, types=["", {prefix="", uri=""}]};

// Constructs an xml namespace for use in an xml tag or document root.
// Use NULL for the uri argument to use just the prefix.
let ns = func(prefix, uri) => select (uri != NULL) => {
    true = {
        prefix = prefix,
        uri = uri,
    },
    false = prefix,
};

let tag = module{
    name = NULL,
    attrs = {},
    children = [],
    ns = NULL,
} => (result) {
    let schema = import "std/schema.ucg";
    let pkg = mod.pkg();

    (mod.name != NULL) || fail "XML Tag names must have a name";
    let base = {
        name = mod.name,
        attrs = mod.attrs,
        children = mod.children,
    };

    let result = select (mod.ns == NULL) => {
        true = base,
        false = select (pkg.validate_ns(mod.ns)) => {
           true = base{ns=mod.ns},
           false = fail "XML Tag namespaces must be a string or tuple of {prefix=, uri=} but is @" % (mod.ns),
        },
    };
};

// returns true for a valid tag.
let is_tag = func(t) => schema.shaped{val=t, shape={name=""}, partial=true};

// validates that a node is either a valid tag or a text node.
let validate_node = func(node) => schema.any{val=node, types=["", {name = ""}], partial=true};

// Make an xml doc from a root node.
//
// The root node must be a valid xml node. Either a text or an
// xml node.
let doc = func(root) => select (validate_node(root)) => {
    true = {
        root = root,
    },
    false = fail "The document root must be a valid xml tag but instead is @" % (root),
};