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.

read_turtle.adb
Turtle_Parsers.Feed
  (Parser, Chunk, Sink);

Status :=
  Turtle_Parsers.Finish
    (Parser, Sink);
--  One event per statement.
Invalid terms are unrepresentableA predicate is typed as an IRI, so a literal in predicate position is a compile error.
Parsing is chunk-fedInput may be split mid-escape or mid-literal, and the result does not depend on where.
Failures are typedA code, the grammar production, and a span with byte, line and column at both ends.

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.

01 / RDF

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 writing
bytesone statementyour sink
02 / N3

Notation3, 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 rules
formulaimpliesformula
03 / SPARQL

Queries 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 serializing
query textsyntax treequery text

Conformance

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.

Counts per suite.
SuiteExaminedRejectedAcceptedWrongWriter
RDF 1.1 and 1.2
w3c/rdf-tests at 12774b0e
1,0500000
RDFC-1.0
w3c/rdf-canon at 15619df2
86——0—
Notation3
w3c/N3 at b975fc59
1,07000—0
SPARQL 1.1 syntax
w3c/rdf-tests at 12774b0e
48800—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
  1. 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.

  2. 02

    Handle each statement

    On_Quad runs once per statement as it closes. Collect them, stream them onward, or count them and keep nothing.

  3. 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.