RDF 1.2 for Ada
RDF, Notation3 and SPARQL libraries.
Turtle, TriG, N-Triples and N-Quads arrive as statements rather than as a document in memory, and input may be split at any byte. Notation3 and SPARQL are separate crates because their models are separate.
Turtle_Parsers.Feed
(Parser, Chunk, Sink);
Status :=
Turtle_Parsers.Finish
(Parser, Sink);
-- One event per statement.
Rule : constant Model.Term :=
N3_Parsers.Parse
("{ ?who :wrote ?what }"
& " => "
& "{ ?what :by ?who } .",
Base);
-- A formula is a term.
Q : constant Syntax.Query :=
SPARQL_Parsers.Parse (Text);
Written :=
SPARQL_Writers.To_SPARQL (Q);
-- Parsed, never evaluated.
Three crates
Separate crates for separate models.
Not merely because they are large. A formula is a term N3 can nest and RDF cannot express; a query is a document rather than data.
The model and its serializations
Turtle, TriG, N-Triples and N-Quads, a dataset with set semantics, RDFC-1.0 canonicalization with either digest it admits, and a self-delimiting binary term encoding.
Reading and writingNotation3, beyond what RDF can express
Quoted graphs, variables, paths, the "is … of" inverse, and the quantifiers. A formula is a term, so nesting is ordinary rather than special.
Formulas and rulesQueries as documents, not as data
The four query forms, patterns and expressions, property paths as far as sequence, alternative, inverse and the three cardinality operators, subqueries, aggregates and the RDF 1.2 term syntax. Read and written back, never evaluated.
Parsing and serializingConformance
What each harness examined.
A harness reads the W3C manifests with this library's own Turtle parser. It reports counts, not a verdict. Corpora are pinned by commit.
| Suite | Examined | Rejected | Accepted | Wrong | Writer |
|---|---|---|---|---|---|
| RDF 1.1 and 1.2 w3c/rdf-tests at 12774b0e | 1,050 | 0 | 0 | 0 | 0 |
| RDFC-1.0 w3c/rdf-canon at 15619df2 | 86 | — | — | 0 | — |
| Notation3 w3c/N3 at b975fc59 | 1,070 | 0 | 0 | — | 0 |
| SPARQL 1.1 syntax w3c/rdf-tests at 12774b0e | 488 | 0 | 0 | — | 0 |
Rejected counts valid documents refused. Accepted counts invalid documents admitted. Wrong counts results that differ from the expected graph. Writer counts documents whose own serialization did not read back. A dash marks a column the suite does not measure.
- Skipped
- The RDFC-1.0 suite is run whole. 811 SPARQL entries need a query engine and 83 are Update rather than queries; 193 Notation3 entries need a reasoner. RDF evaluation entries are run, and compared by canonical form.
- Withdrawn
- The Notation3 suite carries 123 further entries marked
rdft:approval rdft:Rejected. They are run and counted apart. Twelve diverge. Each is reported with the reason this library rejected it. - Writers
- Every accepted document is written out and read again by this library's own parser. 692 RDF entries are compared by canonical form, 1,160 Notation3 documents and 317 SPARQL queries by their own output. The 358 RDF entries outside that count are the ones the suite expects to be rejected.
- Other implementations
- 2,443 documents are read, 2,081 accepted, 2,049 compared. The other 32 state nothing. Each compared document goes to Jena and to Oxigraph. Each is asked two questions. Does it read the document as this library does? Does it read this library's serialization as the same graph? Jena answered both for all 2,049. Oxigraph answered 1,758 and 1,766; it declined the rest or answered RDF-star. Neither differed. Five oracle departures are recorded with citations. Nothing is unsettled.
Reading
The parser holds one statement at a time.
A sink receives one event per statement as the parser reads it, which is what lets a document larger than memory be read at all.
Read the guide- 01
Feed what arrives
Bytes may be split at any boundary, including inside an escape or a literal. The Notation3 and SPARQL suites parse every document they accept twice, whole and one byte at a time, and require the two to agree; the RDF parser's own tests parse each of their documents both ways.
- 02
Handle each statement
On_Quadruns once per statement as it closes. Collect them, stream them onward, or count them and keep nothing. - 03
Decide what a failure was
A diagnostic carries a code, the grammar production that failed, and a source span with byte, line and column at both ends, rather than a message to match on.