book/protocols/preserves/path
Preserves Path schema
Preserves Path is a language for selecting and filtering portions of a Preserves value. It has an associated schema describing the various kinds of Path expressions as abstract syntax.
The schema source below is taken from path/path.prs in the Preserves source code repository.
Preserves Path expressions come in several flavours: selectors, steps (axes and filters), and predicates. Each is described below along with its abstract syntax definitions.
Selectors and Steps
Selectors are a sequence of steps, applied one after the other to the currently-selected value. Each step transforms an input into zero or more outputs. A step is an axis or a filter.
Selector = [Step ...] .
Step = Axis / Filter .
Axes: selecting portions of the input
Each axis step generally selects some sub-portion or
-portions of the current document. An axis may also have a secondary
filtering effect: for example, label only applies to
Records, and will yield an empty result set when applied to any other
kind of input.
Axis =
/ <values> # yields the immediate subvalues of the input nonrecursively
/ <descendants> # recurses through all descendant subvalues of the input
/ <at @key any> # extracts a subvalue named by the given key, if any
/ <label> # extracts a Record's label, if any
/ <keys> # extracts all keys (for subvalues) of the input, nonrecursively
/ <length> # extracts the length/size of the input, if any
/ <annotations> # extracts all annotations attached to the input
/ <embedded> # moves into the representation of an embedded value, if any
/ <parse @module [symbol ...] @name symbol> # parses using Preserves Schema
/ <unparse @module [symbol ...] @name symbol> # unparses using Preserves Schema
.
The parse and unparse variants name Schema definitions, to be
resolved by the eventual surrounding context in which the expression
will be executed. A parse axis parses the input using a
Schema definition; if the parse succeeds, the axis moves into the parse
result. Similarly, unparse expects an abstract parse
result, transforming it back into a concrete value according to the
Schema definition.
Filters: rejecting inputs
Each filter step generally applies some test to the current document as a whole, either emitting it unchanged (with exceptions, detailed below) or emitting no outputs at all.
Filter =
/ <nop> # Always emit the input
/ <compare @op Comparison @literal any> # Emit iff the comparison holds
/ <regex @regex string> # Emit iff input is String and regex matches
/ <test @pred Predicate> # Apply complex predicate
/ <real> # Emit iff input is Double, or Integer
/ <int> # TRUNCATE and emit iff Double or Integer
/ <kind @kind ValueKind> # Emit iff input kind matches
.
Complex predicates
The complex predicates in a test filter are built up
from logical connectives over selectors. A Selector
predicate evaluates to true whenever, applied to its input, it results
in a non-empty output set.
Predicate =
/ Selector
/ <not @pred Predicate>
/ <or @preds [Predicate ...]>
/ <and @preds [Predicate ...]>
.
Comparison against a literal
Each compare filter includes a Comparison
and a literal value to compare the input against. For example,
<compare eq 3> only produces an output if the input
is equal (according to the Preserves
semantic model) to 3.
Comparison = =eq / =ne / =lt / =ge / =gt / =le .
NB. For inequalities
(lt/ge/gt/le),
comparison between values of different kinds is undefined in the current
draft specification.
Filtering by value kind
Each kind filter selects only values from one of the
kinds of Preserves value:
ValueKind =
/ =Boolean / =Double / =SignedInteger / =String / =ByteString / =Symbol
/ =Record / =Sequence / =Set / =Dictionary
/ =Embedded
.
Copyright © 2021–2023 Tony Garnock-Jones, CC BY 4.0
