2. Foundations
Contents of FBL 0.14
An FBL document is a JSON document (RFC 8259) encoded in UTF-8, validated by fbl.schema.json#/$defs/Document:
| Property | Type | Description |
|---|---|---|
$schema |
URI | Optional; the schema's $id with #/$defs/Document. |
fbl |
"0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "0.10", "0.11", "0.12", "0.13", "0.14" |
Required. The FBL version the document is written in. |
doc |
Doc | Documentation, as in DISL §2.4. |
bindings |
map Name → Binding | Required, at least one. Each binding is described in section 3. |
A document MUST NOT contain duplicate keys. Properties whose names start with x- are extension properties and are ignored by hosts that do not know them, as in DISL §2.8.
A binding name and a rule name is a Name: a letter or underscore followed by letters, digits, underscores, dots or hyphens (^[A-Za-z_][A-Za-z0-9_.-]*$). Rule names are unique within their binding. Attribute names and type references are DISL's (SimpleId, TypeRef).
A binding is referenced as <document>#<name>: a URI reference to an FBL document, resolved against the referring document's own location, followed by # and the binding's name. #<name> alone refers to a binding in the same document. A DISL specification refers to a binding the same way from persistence.binding (DISL §11.2), or embeds a Binding object there; a DESL specification lists one binding per format family in persistence.bindings (DESL section 5).
Wherever FBL needs a condition or a computed value it uses CEL, as DISL does (DISL §2.5, §12), with the cost limits DISL sets. The variables available depend on where an expression appears:
| Variable | Type | Available in | Meaning |
|---|---|---|---|
entry |
map | rule when, slot value, sidecar key |
The entry the rule matched, as CEL values (section 4.1.4). |
text |
map | same, yaml and json (FBL 0.5) | The same entry with every scalar as its written text (section 4.1.5): text.label is "yes" where entry.label is true. |
style |
map | same, yaml and json (FBL 0.5) | The same entry with every scalar as the name of the style it is written in: plain, single, double, literal or folded; json strings are double, other json scalars plain. |
parent |
map or null | same | The nearest enclosing entry matched by any rule of the binding, or null. |
path |
map string → string | tree and xml rules | The values of the selector's {capture} segments (section 4.2). |
groups |
map string → string | lines, blocks and bullets rules | The named groups of the rule's line that took part in the match; a group that did not is absent, so has(groups.x) tests it. |
line |
int | every rule | The 1-based line on which the entry starts. |
registration |
map string → string | every rule | The headers of the registration the body was opened through (section 8), empty without one. |
attributes |
map | insert.when |
The attribute values of the element being added. |
A CEL expression MUST compile against these variables; a validator reports one that does not.
lines, blocks and bullets rules, sections, markers, headers and comments use regular expressions in the common subset of RE2, .NET, Java and ECMAScript syntax, which all four hosts' languages and CEL's matches read alike:
- literals,
., character classes[…]and[^…], the escapes\d \D \s \S \w \W \t \n \r \\and escaped punctuation; - anchors
^and$(a line never contains its line ending, so both refer to the line); - groups
(…), non-capturing groups(?:…)and named groups(?<name>…), names being SimpleIds; - alternation
|and the quantifiers* + ? {n} {n,} {n,m}and their lazy forms.
Backreferences, lookaround, atomic groups, possessive quantifiers, inline flags and Unicode property classes are not in the subset, and a validator MUST reject an expression that uses them. Case-insensitive matching of ASCII letters is requested with a rule's caseInsensitive. Matching is against the whole line unless the expression says otherwise with anchors, except that (FBL 0.7) a bullets rule with within is matched against the item's text and a section against the heading's text (section 4.8); a match that could succeed in several ways takes the one the leftmost-first semantics of RE2 gives, which the other engines agree with for this subset.
A body file is UTF-8, with or without a byte-order mark. A byte-order mark, if present, is kept and belongs to no node; offsets in this document and in fixtures are UTF-8 byte offsets into the file including it. A file that is not valid UTF-8 is an unreadable body (section 7.5). A line is a maximal run of bytes without CR or LF; its line ending is the CRLF, LF or lone CR that follows it, if any. Line and column numbers in findings are 1-based; columns count Unicode code points, as DISL §8.6 requires.
fbl names the version of FBL a document is written in: "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "0.10", "0.11", "0.12", "0.13" or "0.14". Each is a superset of the one before, and a host MUST read a document of an earlier minor version with its meaning. While 0.14 is a draft, its schema is published at the 0.1 address (https://etalii.net/adp/fbl/schema/0.1/fbl.schema.json), which accepts every 0.1 document unchanged. A host MUST refuse a document whose major version it does not support, and SHOULD read a document of a newer minor version, ignoring what it does not know, with a warning. Before 1.0 any construct may change (constitution principle IV).