diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 13731990..35be34f2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,6 +48,26 @@ jobs: - run: npm run test-shexv-val - run: npm run test-shexv-err + # doc/ShExR.shex is the hand-maintained source; doc/ShExR.{json,ttl, + # ntriples} are the same schema in other syntaxes and had all drifted + # from it (ShExR.ntriples by nine years -- it predated ShapeDecl, + # abstract, imports and extends entirely, and still carried the + # sx:negated the language dropped in 2016). + # + # bin/mkShExR.js regenerates the two RDF renderings via ShExJ and + # doc/ShExJ-context.jsonld, so this also exercises the context, which is + # itself generated from vocab/vocab.csv. ShExR.json is compared as an AST + # rather than regenerated, so its hand formatting survives. + - name: doc/ShExR.{json,ttl,ntriples} match doc/ShExR.shex + run: | + npm run shexr-check || { + echo "::error::ShExR renderings are stale -- run 'npm run shexr' and commit the result" + exit 1 + } + + # the published ShEx vocabulary must define every term ShExR uses + - run: npm run vocab-check + # informational only: flags schemas referenced by validation tests # (via EXTENDS, not IMPORT) that lack their own manifest entry. # Currently reports 3 pre-existing gaps that need real ShExR (.ttl) diff --git a/README.md b/README.md index c9133c28..882ee394 100644 --- a/README.md +++ b/README.md @@ -66,4 +66,20 @@ which yields the files which include this pattern: * Same manifest layout as `validation` (`manifest.ttl`, `manifest.jsonld`) and the same `.ttl` data convention; the schemas live in `schemas-contrib/` as ShExC only (no ShExJ/ShExR trio, no representation tests). * Entries carry only `ValidationTest`/`ValidationFailure` plus traits. There are no reference results, so a validator can be checked for logic-conformance here but not result-conformance, and a conformant implementation is not required to run them at all. - +## `doc` + +Grammars for the three renderings of a ShEx schema, and the pieces that relate +them: + +* [`ShExJ.jsg`](doc/ShExJ.jsg) — ShExJ, as a JSON Schema Grammar. +* [`ShExR.shex`](doc/ShExR.shex) — ShExR: the ShEx schema that RDF renderings of + ShEx schemas are validated against. Hand-maintained, and the source for + `ShExR.ttl` and `ShExR.ntriples`, which [`bin/mkShExR.js`](bin/mkShExR.js) + derives and `npm test` keeps in sync. +* [`ShExJ-context.jsonld`](doc/ShExJ-context.jsonld) — the JSON-LD context that + turns ShExJ into ShExR. Generated from [`vocab/vocab.csv`](vocab/), which is + also the source of . +* [`syntax-deltas.html`](doc/syntax-deltas.html) — where ShExC, ShExJ and ShExR + disagree about what a schema may say, with the evidence for each. Notably, + ShExR admits a `ShapeDecl` as `start` where neither of the others can express + one. diff --git a/bin/mkShExR.js b/bin/mkShExR.js new file mode 100755 index 00000000..464f71ff --- /dev/null +++ b/bin/mkShExR.js @@ -0,0 +1,193 @@ +#!/usr/bin/env node + +// Regenerate the RDF renderings of ShExR from doc/ShExR.shex. +// +// bin/mkShExR.js rewrite doc/ShExR.ttl and doc/ShExR.ntriples +// bin/mkShExR.js --check verify all three renderings, write nothing +// +// doc/ShExR.shex is the hand-maintained source: the schema that ShExR +// documents -- RDF renderings of ShEx schemas -- are validated against. The +// other three files in doc/ are the same schema in other syntaxes and had all +// drifted from it at some point (ShExR.ntriples by nine years), so they are +// derived here instead of hand-synced. +// +// ShExC -> ShExJ is the parser; ShExJ -> RDF is plain JSON-LD expansion using +// doc/ShExJ-context.jsonld, since a ShExJ document plus that context *is* an +// ShExR document. That means this also exercises the context, which is itself +// generated from vocab/vocab.csv. +// +// doc/ShExR.json is checked but never rewritten: it is hand-formatted, and +// reformatting it would bury a real change in noise. --check compares it as an +// abstract syntax tree, so formatting is free to differ but content is not. + +'use strict'; +const fs = require('fs'); +const path = require('path'); +const N3 = require('n3'); +const jsonld = require('jsonld'); +const parser = require('@shexjs/parser'); + +const DOC = path.join(__dirname, '..', 'doc'); +const BASE = 'http://www.w3.org/ns/shex'; +const PREFIXES = { + rdf: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', + sx: 'http://www.w3.org/ns/shex#', + xsd: 'http://www.w3.org/2001/XMLSchema#', +}; + +const read = f => fs.readFileSync(path.join(DOC, f), 'utf8'); + +// Deep key-sorted stringify, so two ASTs compare regardless of key order. +const sorted = o => + Array.isArray(o) ? o.map(sorted) + : (o && typeof o === 'object') + ? Object.fromEntries(Object.keys(o).sort().map(k => [k, sorted(o[k])])) + : o; +const canon = o => JSON.stringify(sorted(JSON.parse(JSON.stringify(o))), null, 1); + +function ntriples(quads) { + return new Promise((resolve, reject) => { + const writer = new N3.Writer(null, {format: 'N-Triples'}); + quads.forEach(q => writer.addQuad(q)); + writer.end((e, result) => e ? reject(e) : resolve(result)); + }); +} + +const RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'; +const XSD = 'http://www.w3.org/2001/XMLSchema#'; + +// N3.Writer labels every blank node and spells out rdf:first/rdf:rest, which +// turns this file into 265 list triples nobody can read. The ShExR graph is a +// tree -- every blank node is referenced exactly once -- so nest them as [ ] +// and collapse the lists to ( ), the way the file was written by hand. +function turtle(quads) { + const bySubject = new Map(); // subject -> [quad] + const refs = new Map(); // bnode -> times used as an object + for (const q of quads) { + if (!bySubject.has(q.subject.value)) bySubject.set(q.subject.value, []); + bySubject.get(q.subject.value).push(q); + if (q.object.termType === 'BlankNode') + refs.set(q.object.value, (refs.get(q.object.value) || 0) + 1); + } + + const iri = v => { + for (const [p, ns] of Object.entries(PREFIXES)) + if (v.startsWith(ns) && /^[A-Za-z_][\w.-]*$/.test(v.slice(ns.length))) + return `${p}:${v.slice(ns.length)}`; + return `<${v}>`; + }; + const literal = t => { + const d = t.datatype && t.datatype.value; + if (d === XSD + 'boolean' || d === XSD + 'integer') return t.value; + if (t.language) return `${JSON.stringify(t.value)}@${t.language}`; + if (!d || d === XSD + 'string') return JSON.stringify(t.value); + return `${JSON.stringify(t.value)}^^${iri(d)}`; + }; + + const listOf = b => { // rdf:first/rdf:rest -> [terms] or null + const items = []; + let cur = b; + while (cur !== RDF + 'nil') { + const qs = bySubject.get(cur); + if (!qs) return null; + const first = qs.find(q => q.predicate.value === RDF + 'first'); + const rest = qs.find(q => q.predicate.value === RDF + 'rest'); + if (!first || !rest || qs.length !== 2) return null; + items.push(first.object); + if (rest.object.termType === 'NamedNode' && rest.object.value === RDF + 'nil') break; + if (rest.object.termType !== 'BlankNode') return null; + cur = rest.object.value; + } + return items; + }; + + const term = (t, indent) => { + if (t.termType === 'Literal') return literal(t); + if (t.termType === 'NamedNode') + return t.value === RDF + 'nil' ? '()' : iri(t.value); + // blank node: inline it if it is used exactly once, else fall back to a label + if (refs.get(t.value) !== 1 || !bySubject.has(t.value)) return `_:${t.value}`; + const items = listOf(t.value); + if (items) return `( ${items.map(i => term(i, indent)).join(' ')} )`; + return `[ ${predObjs(bySubject.get(t.value), indent + ' ')} ]`; + }; + + const predObjs = (qs, indent) => { + // rdf:type first, as `a`, then the rest in a stable order + const ordered = [...qs].sort((x, y) => { + const rank = q => q.predicate.value === RDF + 'type' ? '' : q.predicate.value; + return rank(x) < rank(y) ? -1 : rank(x) > rank(y) ? 1 : 0; + }); + return ordered.map(q => { + const p = q.predicate.value === RDF + 'type' ? 'a' : iri(q.predicate.value); + return `${p} ${term(q.object, indent)}`; + }).join(`;\n${indent}`); + }; + + // Roots are the subjects nothing points at: the anonymous Schema node and + // the named ShapeDecls. Everything else is reached by nesting. Order by the + // rendered subject, never by blank node label -- labels are assigned by + // whichever parser produced the quads, so sorting on them would make this + // output depend on where the graph came from rather than on what it says. + const label = s => + bySubject.get(s)[0].subject.termType === 'BlankNode' ? '[]' : iri(s); + const roots = [...bySubject.keys()].filter(s => !refs.get(s)) + .sort((a, b) => label(a) < label(b) ? -1 : label(a) > label(b) ? 1 : 0); + + const prefixes = Object.entries(PREFIXES) + .map(([p, ns]) => `PREFIX ${p}: <${ns}>`).join('\n'); + const body = roots.map(s => + `${label(s)} ${predObjs(bySubject.get(s), ' ')} .`).join('\n\n'); + + return `${prefixes}\n\n${body}\n`; +} + +async function build() { + const shexj = parser.construct(BASE, {}).parse(read('ShExR.shex')); + + const ctx = JSON.parse(read('ShExJ-context.jsonld'))['@context']; + const doc = Object.assign({'@context': ctx}, JSON.parse(JSON.stringify(shexj))); + const nquads = await jsonld.toRDF(doc, {format: 'application/n-quads', base: BASE}); + const quads = new N3.Parser({format: 'N-Quads'}).parse(nquads); + + return { + shexj, + ttl: turtle(quads), + ntriples: await ntriples(quads), + }; +} + +(async () => { + const check = process.argv.includes('--check'); + const {shexj, ttl, ntriples} = await build(); + let bad = 0; + + // ShExR.json is compared as an AST -- content must match, formatting need not. + const json = JSON.parse(read('ShExR.json')); + delete json['@context']; + if (canon(json) !== canon(shexj)) { + console.error('doc/ShExR.json does not match doc/ShExR.shex'); + bad++; + } + + for (const [file, text] of [['ShExR.ttl', ttl], ['ShExR.ntriples', ntriples]]) { + const target = path.join(DOC, file); + if (check) { + if (fs.readFileSync(target, 'utf8') !== text) { + console.error(`doc/${file} is not what doc/ShExR.shex generates`); + bad++; + } + } else { + fs.writeFileSync(target, text); + console.error(`wrote doc/${file}`); + } + } + + if (bad) { + console.error(`\n${bad} file(s) out of sync with doc/ShExR.shex.`); + console.error('Run bin/mkShExR.js and commit the result; for ShExR.json,'); + console.error('hand-edit it to match (it is deliberately not regenerated).'); + process.exit(1); + } + if (check) console.error('doc/ShExR.{json,ttl,ntriples} all match doc/ShExR.shex'); +})().catch(e => { console.error(e.stack || e); process.exit(1); }); diff --git a/doc/ShExJ-context.jsonld b/doc/ShExJ-context.jsonld index b74a52dd..60cf2f22 100644 --- a/doc/ShExJ-context.jsonld +++ b/doc/ShExJ-context.jsonld @@ -29,17 +29,24 @@ "LiteralStemRange": "shex:LiteralStemRange", "NodeConstraint": "shex:NodeConstraint", "OneOf": "shex:OneOf", + "QueryMap": "shex:QueryMap", "Schema": "shex:Schema", "SemAct": "shex:SemAct", "Shape": "shex:Shape", "ShapeAnd": "shex:ShapeAnd", + "ShapeDecl": "shex:ShapeDecl", "ShapeExternal": "shex:ShapeExternal", + "ShapeMap": "shex:ShapeMap", "ShapeNot": "shex:ShapeNot", "ShapeOr": "shex:ShapeOr", "Stem": "shex:Stem", "StemRange": "shex:StemRange", "TripleConstraint": "shex:TripleConstraint", "Wildcard": "shex:Wildcard", + "abstract": { + "@id": "shex:abstract", + "@type": "xsd:boolean" + }, "closed": { "@id": "shex:closed", "@type": "xsd:boolean" @@ -61,6 +68,10 @@ "@type": "@id", "@container": "@list" }, + "extends": { + "@id": "shex:extends", + "@type": "@id" + }, "extra": { "@id": "shex:extra", "@type": "@id" @@ -73,6 +84,11 @@ "@id": "shex:fractiondigits", "@type": "xsd:integer" }, + "imports": { + "@id": "shex:imports", + "@type": "@id", + "@container": "@list" + }, "inverse": { "@id": "shex:inverse", "@type": "xsd:boolean" @@ -121,6 +137,10 @@ "@id": "shex:name", "@type": "@id" }, + "node": { + "@id": "shex:node", + "@type": "@id" + }, "nodeKind": { "@id": "shex:nodeKind", "@type": "@vocab" @@ -142,6 +162,10 @@ "@type": "@id", "@container": "@list" }, + "shape": { + "@id": "shex:shape", + "@type": "@id" + }, "shapeExpr": { "@id": "shex:shapeExpr", "@type": "@id" @@ -165,6 +189,10 @@ "@type": "@id", "@container": "@list" }, + "status": { + "@id": "shex:status", + "@language": null + }, "stem": { "@id": "shex:stem", "@type": "xsd:string" @@ -182,6 +210,8 @@ "@type": "@id", "@container": "@list" }, + "FOCUS": "shex:FOCUS", + "_": "shex:_", "bnode": "shex:bnode", "iri": "shex:iri", "literal": "shex:literal", diff --git a/doc/ShExR.json b/doc/ShExR.json index 4488ca6c..64617500 100644 --- a/doc/ShExR.json +++ b/doc/ShExR.json @@ -488,14 +488,6 @@ { "value": "true", "type": "http://www.w3.org/2001/XMLSchema#boolean" }, { "value": "false", "type": "http://www.w3.org/2001/XMLSchema#boolean" } ] } }, - { "type": "TripleConstraint", - "predicate": "http://www.w3.org/ns/shex#negated", "min": 0, "max": 1, - "valueExpr": { - "type": "NodeConstraint", - "values": [ - { "value": "true", "type": "http://www.w3.org/2001/XMLSchema#boolean" }, - { "value": "false", "type": "http://www.w3.org/2001/XMLSchema#boolean" } - ] } }, { "type": "TripleConstraint", "predicate": "http://www.w3.org/ns/shex#min", "min": 0, "max": 1, "valueExpr": { "type": "NodeConstraint", "datatype": "http://www.w3.org/2001/XMLSchema#integer" } }, diff --git a/doc/ShExR.ntriples b/doc/ShExR.ntriples index eea3c79c..be6ddb35 100644 --- a/doc/ShExR.ntriples +++ b/doc/ShExR.ntriples @@ -1,813 +1,1341 @@ -_:g70362524681520 . -_:g70362524681520 . -_:g70362516090120 . -_:g70362516090120 . -_:g70362516090120 _:g70362515955840 . - _:g70362525211160 . - . -_:g70362507328620 . -_:g70362507328620 . -_:g70362507328620 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . -_:g70362513018380 . - . - _:g70362516694580 . - "true"^^ . -_:g70362507327240 . -_:g70362507327240 "0"^^ . -_:g70362507327240 "-1"^^ . -_:g70362507327240 . -_:g70362507327240 . -_:g70362516694580 _:g70362516930080 . -_:g70362516694580 . -_:g70362516634300 . -_:g70362516634300 . -_:g70362516634300 _:g70362516532260 . -_:g70362513412640 . -_:g70362513412640 . -_:g70362512820820 . -_:g70362512820820 "0"^^ . -_:g70362512820820 "1"^^ . -_:g70362512820820 . -_:g70362512820820 . -_:g70362516546240 . -_:g70362516546240 _:g70362516549500 . -_:g70362516878120 _:g70362512371560 . -_:g70362516878120 _:g70362516906180 . -_:g70362513163240 _:g70362516090120 . -_:g70362513163240 _:g70362513179360 . -_:g70362516583260 . -_:g70362516583260 _:g70362516597560 . -_:g70362512808400 . -_:g70362512808400 . -_:g70362512808400 _:g70362513233280 . -_:g70362516153100 _:g70362513163240 . -_:g70362516153100 . -_:g70362512272660 . -_:g70362512272660 "0"^^ . -_:g70362512272660 "1"^^ . -_:g70362512272660 . -_:g70362512272660 . -_:g70362516827700 . -_:g70362516827700 _:g70362516858520 . - . - _:g70362516465580 . - "true"^^ . -_:g70362516532260 . -_:g70362516532260 _:g70362513022580 . -_:g70362524883880 _:g70362516842260 . -_:g70362524883880 _:g70362516450440 . - _:g70362516533460 . - . -_:g70362516957080 _:g70362512272660 . -_:g70362516957080 _:g70362516960860 . -_:g70362513492700 . -_:g70362513492700 . -_:g70362513492700 . -_:g70362511652000 _:g70362516174140 . -_:g70362511652000 _:g70362511785400 . -_:g70362516960860 _:g70362507327240 . -_:g70362516960860 . -_:g70362525144480 . -_:g70362525144480 . -_:g70362525144480 _:g70362525176300 . -_:g70362512339800 _:g70362517009420 . -_:g70362512339800 . -_:g70362513233280 . -_:g70362513233280 _:g70362515959980 . -_:g70362516943840 _:g70362512820820 . -_:g70362516943840 _:g70362516957080 . -_:g70362516533460 . -_:g70362516533460 _:g70362516546240 . -_:g70362516234820 . -_:g70362516234820 . -_:g70362516089580 . -_:g70362516089580 . -_:g70362524325020 . -_:g70362524325020 "0"^^ . -_:g70362524325020 "1"^^ . -_:g70362524325020 . -_:g70362524325020 . - . - _:g70362516173400 . - "true"^^ . -_:g70362525519660 . -_:g70362525519660 . -_:g70362525519660 _:g70362525572020 . -_:g70362525286720 . -_:g70362525286720 . -_:g70362516710520 . -_:g70362516710520 . -_:g70362516710520 _:g70362516599260 . -_:g70362525204680 _:g70362525357520 . -_:g70362525204680 _:g70362525208140 . -_:g70362525556320 _:g70362512935560 . -_:g70362525556320 _:g70362525567540 . -_:g70362525224600 _:g70362525437460 . -_:g70362525224600 _:g70362525227180 . -_:g70362524605080 "false"^^ . -_:g70362524605080 . -_:g70362524467420 . -_:g70362524467420 . -_:g70362524981240 . -_:g70362524981240 . -_:g70362524981240 _:g70362524928380 . -_:g70362515942040 . -_:g70362515942040 _:g70362513412640 . -_:g70362513588940 _:g70362525437540 . -_:g70362513588940 . -_:g70362525227180 _:g70362525337240 . -_:g70362525227180 . -_:g70362525536760 . -_:g70362525536760 . -_:g70362525536760 _:g70362525487000 . -_:g70362525572020 . -_:g70362525572020 _:g70362525601720 . -_:g70362507848060 . -_:g70362507848060 "0"^^ . -_:g70362507848060 "-1"^^ . -_:g70362507848060 . -_:g70362507848060 . -_:g70362524932540 . -_:g70362524932540 . -_:g70362524932540 . -_:g70362525241300 . -_:g70362525241300 . -_:g70362525241300 _:g70362525190100 . -_:g70362524770000 . -_:g70362524770000 _:g70362524730780 . -_:g70362524982380 . -_:g70362524982380 . -_:g70362524982380 . -_:g70362524796620 _:g70362524884580 . -_:g70362524796620 _:g70362524799520 . -_:g70362525437460 . -_:g70362525437460 . -_:g70362525437460 _:g70362525386900 . -_:g70362524212880 . -_:g70362524212880 "0"^^ . -_:g70362524212880 "-1"^^ . -_:g70362524212880 . -_:g70362524212880 . -_:g70362525093080 _:g70362525339000 . -_:g70362525093080 . -_:g70362512353340 _:g70362507704520 . -_:g70362512353340 . -_:g70362525008600 . -_:g70362525008600 _:g70362525041220 . -_:g70362512108420 . -_:g70362512108420 . -_:g70362524340120 _:g70362524439660 . -_:g70362524340120 _:g70362524343920 . -_:g70362524145640 . -_:g70362524145640 . -_:g70362516777840 . -_:g70362516777840 _:g70362524602480 . -_:g70362516465780 . -_:g70362516465780 . -_:g70362516091380 _:g70362516781740 . -_:g70362516091380 _:g70362516104760 . -_:g70362524157680 . -_:g70362524157680 _:g70362517221460 . -_:g70362525490080 . -_:g70362525490080 _:g70362525501220 . -_:g70362516042440 . -_:g70362516042440 . -_:g70362516549500 . -_:g70362516549500 _:g70362516583260 . -_:g70362508309920 . -_:g70362508309920 . -_:g70362524634680 _:g70362525634940 . -_:g70362524634680 . -_:g70362524617980 . -_:g70362524617980 . -_:g70362524617980 . -_:g70362516709480 . -_:g70362516709480 "0"^^ . -_:g70362516709480 "-1"^^ . -_:g70362516709480 . -_:g70362516709480 _:g70362524681520 . -_:g70362516595900 . -_:g70362516595900 _:g70362516961260 . -_:g70362516859100 . -_:g70362516859100 . -_:g70362513463820 . -_:g70362513463820 . -_:g70362524320480 _:g70362516027700 . -_:g70362524320480 . -_:g70362513625780 . -_:g70362513625780 . -_:g70362513179360 _:g70362513492700 . -_:g70362513179360 . -_:g70362524421200 . -_:g70362524421200 . -_:g70362525176300 . -_:g70362525176300 _:g70362525212500 . -_:g70362525224580 . -_:g70362525224580 . -_:g70362525224580 _:g70362516023600 . -_:g70362525649080 _:g70362524256100 . -_:g70362525649080 _:g70362525652120 . -_:g70362525392800 _:g70362525204680 . -_:g70362525392800 . -_:g70362525145140 . -_:g70362525145140 . -_:g70362524915780 . -_:g70362524915780 . -_:g70362524915780 . -_:g70362524291060 _:g70362524537460 . -_:g70362524291060 . - . - _:g70362524654840 . - "true"^^ . - _:g70362524229140 . - . -_:g70362524601440 . -_:g70362524601440 . -_:g70362525293040 . -_:g70362525293040 _:g70362525241300 . -_:g70362525293040 "true"^^ . - . - _:g70362524385460 . - "true"^^ . -_:g70362512663660 . -_:g70362512663660 . -_:g70362512663660 _:g70362512353340 . -_:g70362525634940 _:g70362524599220 . -_:g70362525634940 _:g70362525637840 . -_:g70362516599260 . -_:g70362516599260 _:g70362516468700 . -_:g70362516356620 . -_:g70362516356620 . -_:g70362516356620 _:g70362516595900 . -_:g70362507704520 _:g70362512108420 . -_:g70362507704520 _:g70362507983960 . -_:g70362524549920 . -_:g70362524549920 "0"^^ . -_:g70362524549920 "1"^^ . -_:g70362524549920 . -_:g70362524549920 _:g70362524454040 . -_:g70362512842560 _:g70362525614800 . -_:g70362512842560 _:g70362512867360 . -_:g70362515959980 . -_:g70362515959980 . -_:g70362524390200 . -_:g70362524390200 . -_:g70362516862920 . -_:g70362516862920 . -_:g70362525651960 . -_:g70362525651960 "0"^^ . -_:g70362525651960 "-1"^^ . -_:g70362525651960 . -_:g70362525651960 _:g70362525555800 . - . - _:g70362524634680 . - "true"^^ . -_:g70362513022580 . -_:g70362513022580 . -_:g70362524229140 . -_:g70362524229140 _:g70362524240080 . -_:g70362525142940 . -_:g70362525142940 . - . - _:g70362512584780 . - "true"^^ . -_:g70362524293820 "true"^^ . -_:g70362524293820 _:g70362524305040 . - . - _:g70362524981200 . - "true"^^ . -_:g70362524981200 . -_:g70362524981200 . -_:g70362524981200 _:g70362525008600 . -_:g70362525437540 _:g70362513445960 . -_:g70362525437540 _:g70362525440280 . -_:g70362525405400 _:g70362525144480 . -_:g70362525405400 _:g70362525407940 . -_:g70362524426140 . -_:g70362524426140 . -_:g70362524426140 _:g70362524457280 . -_:g70362524730780 . -_:g70362524730780 . -_:g70362524272600 . -_:g70362524272600 _:g70362524275260 . -_:g70362516547860 . -_:g70362516547860 . -_:g70362516465580 _:g70362511652000 . -_:g70362516465580 . -_:g70362524275260 . -_:g70362524275260 _:g70362524277860 . -_:g70362516930080 _:g70362516634300 . -_:g70362516930080 _:g70362516943840 . -_:g70362516961260 . -_:g70362516961260 _:g70362516827700 . -_:g70362525666620 _:g70362516220400 . -_:g70362525666620 _:g70362525669720 . -_:g70362516812040 _:g70362525538740 . -_:g70362516812040 . -_:g70362512320240 _:g70362511585560 . -_:g70362512320240 . -_:g70362525555800 _:g70362525490080 . -_:g70362525555800 . -_:g70362525586760 . -_:g70362525586760 . -_:g70362524647460 _:g70362524748800 . -_:g70362524647460 . - . - _:g70362516153100 . - "true"^^ . -_:g70362525240400 . -_:g70362525240400 _:g70362525191240 . -_:g70362516930160 _:g70362516614820 . -_:g70362516930160 . -_:g70362515955840 . -_:g70362515955840 _:g70362513625780 . - . - _:g70362512339800 . - "true"^^ . - . - _:g70362516864160 . - "true"^^ . -_:g70362517071200 . -_:g70362517071200 . -_:g70362517071200 _:g70362516930160 . -_:g70362512584780 _:g70362516878120 . -_:g70362512584780 . -_:g70362524977480 . -_:g70362524977480 _:g70362524980200 . -_:g70362517223520 _:g70362524212880 . -_:g70362517223520 . -_:g70362513391860 . -_:g70362513391860 . -_:g70362513391860 . -_:g70362524457280 . -_:g70362524457280 _:g70362516864020 . -_:g70362525211160 _:g70362525636740 . -_:g70362525211160 _:g70362525221960 . -_:g70362524829940 . -_:g70362524829940 . -_:g70362524829940 _:g70362524770000 . - . - _:g70362524174940 . - "true"^^ . -_:g70362512870120 . -_:g70362512870120 . -_:g70362525636740 . -_:g70362525636740 . -_:g70362525636740 _:g70362525586760 . -_:g70362517060600 _:g70362524145640 . -_:g70362517060600 _:g70362517072520 . -_:g70362524372900 _:g70362524421200 . -_:g70362524372900 . -_:g70362512988860 . -_:g70362512988860 . -_:g70362512988860 . -_:g70362512821400 _:g70362525519660 . -_:g70362512821400 _:g70362512842560 . -_:g70362515944160 . -_:g70362515944160 "0"^^ . -_:g70362515944160 "1"^^ . -_:g70362515944160 . -_:g70362515944160 . -_:g70362517060880 _:g70362517155080 . -_:g70362517060880 _:g70362524272600 . -_:g70362516858520 . -_:g70362516858520 _:g70362516862920 . -_:g70362525340400 . -_:g70362525340400 . - . - _:g70362516812040 . - "true"^^ . -_:g70362516627940 . -_:g70362516627940 . -_:g70362516104760 _:g70362516466320 . -_:g70362516104760 . -_:g70362524295020 _:g70362516356620 . -_:g70362524295020 _:g70362517060880 . -_:g70362516174140 . -_:g70362516174140 . -_:g70362516174140 _:g70362515942040 . -_:g70362524769120 _:g70362524932540 . -_:g70362524769120 _:g70362524780680 . -_:g70362516781740 . -_:g70362516781740 . -_:g70362516781740 _:g70362516651500 . -_:g70362516468700 . -_:g70362516468700 . -_:g70362512371560 . -_:g70362512371560 . -_:g70362512371560 _:g70362511958360 . -_:g70362516484480 _:g70362517071200 . -_:g70362516484480 . -_:g70362524439660 . -_:g70362524439660 _:g70362524390200 . -_:g70362524489380 . -_:g70362524489380 . -_:g70362516173400 _:g70362525405400 . -_:g70362516173400 . -_:g70362524881340 _:g70362524426140 . -_:g70362524881340 _:g70362524883880 . - . - _:g70362513588940 . - "true"^^ . -_:g70362507983960 . -_:g70362507983960 . -_:g70362524385460 _:g70362524881340 . -_:g70362524385460 . -_:g70362524845240 . -_:g70362524845240 . -_:g70362525337240 . -_:g70362525337240 . -_:g70362525337240 _:g70362525286720 . -_:g70362524745820 _:g70362525058300 . -_:g70362524745820 _:g70362524748560 . -_:g70362524107200 . -_:g70362524107200 . -_:g70362524359080 _:g70362524505880 . -_:g70362524359080 _:g70362524370300 . -_:g70362525663280 _:g70362516693540 . -_:g70362525663280 _:g70362525666620 . - . - _:g70362512320240 . -_:g70362524123700 . -_:g70362524123700 . -_:g70362524456040 . -_:g70362524456040 "0"^^ . -_:g70362524456040 "1"^^ . -_:g70362524456040 . -_:g70362524456040 _:g70362524356920 . -_:g70362516861800 . -_:g70362516861800 _:g70362516714680 . -_:g70362512502560 . -_:g70362512502560 "0"^^ . -_:g70362512502560 "1"^^ . -_:g70362512502560 . -_:g70362512502560 . -_:g70362517155080 . -_:g70362517155080 . -_:g70362517155080 _:g70362524123700 . -_:g70362524713660 . -_:g70362524713660 "0"^^ . -_:g70362524713660 "1"^^ . -_:g70362524713660 . -_:g70362524713660 . -_:g70362524196260 . -_:g70362524196260 "1"^^ . -_:g70362524196260 "-1"^^ . -_:g70362524196260 . -_:g70362524196260 . -_:g70362513722180 _:g70362525309940 . -_:g70362513722180 . -_:g70362524636620 _:g70362524848920 . -_:g70362524636620 _:g70362524647460 . -_:g70362513628480 _:g70362512821400 . -_:g70362513628480 . -_:g70362525501220 . -_:g70362525501220 . -_:g70362512500060 . -_:g70362512500060 "0"^^ . -_:g70362512500060 "-1"^^ . -_:g70362512500060 . -_:g70362512500060 . -_:g70362525354640 . -_:g70362525354640 . -_:g70362524599220 . -_:g70362524599220 . -_:g70362524599220 _:g70362524537940 . -_:g70362525407940 _:g70362525224580 . -_:g70362525407940 _:g70362513722180 . -_:g70362525287560 . -_:g70362525287560 . -_:g70362525287560 . -_:g70362525191240 . -_:g70362525191240 . -_:g70362525386900 . -_:g70362525386900 . -_:g70362516693540 . -_:g70362516693540 "0"^^ . -_:g70362516693540 "1"^^ . -_:g70362516693540 . -_:g70362516693540 _:g70362516465780 . - . - _:g70362513628480 . - "true"^^ . -_:g70362524402980 . -_:g70362524402980 . -_:g70362524402980 . -_:g70362524620120 _:g70362525057100 . -_:g70362524620120 _:g70362524631240 . -_:g70362525614800 . -_:g70362525614800 . -_:g70362525614800 _:g70362513463820 . -_:g70362524748560 _:g70362524981240 . -_:g70362524748560 . -_:g70362524602480 "true"^^ . -_:g70362524602480 _:g70362524605080 . - . - _:g70362525455200 . - "true"^^ . -_:g70362524748800 . -_:g70362524748800 . -_:g70362524748800 _:g70362524698500 . -_:g70362524277860 _:g70362524196260 . -_:g70362524277860 . -_:g70362517009420 _:g70362512808400 . -_:g70362517009420 _:g70362524320480 . -_:g70362525190100 . -_:g70362525190100 _:g70362525142940 . -_:g70362525652120 _:g70362517070540 . -_:g70362525652120 _:g70362525663280 . -_:g70362513166080 . -_:g70362513166080 _:g70362512870120 . -_:g70362525090000 _:g70362525418840 . -_:g70362525090000 _:g70362525093080 . -_:g70362516906180 _:g70362507328620 . -_:g70362516906180 . -_:g70362524106940 "false"^^ . -_:g70362524106940 . -_:g70362524130660 . -_:g70362524130660 . -_:g70362524130660 . -_:g70362516864020 . -_:g70362516864020 . -_:g70362524698500 . -_:g70362524698500 . -_:g70362516027700 _:g70362524295020 . -_:g70362516027700 . -_:g70362516864160 _:g70362516091380 . -_:g70362516864160 . -_:g70362525487000 . -_:g70362525487000 . -_:g70362516450440 _:g70362516709480 . -_:g70362516450440 _:g70362524861200 . -_:g70362507327280 _:g70362513266060 . -_:g70362507327280 _:g70362507391280 . -_:g70362512867360 _:g70362513391860 . -_:g70362512867360 . -_:g70362525142000 _:g70362525240400 . -_:g70362525142000 _:g70362525145140 . -_:g70362524454040 . -_:g70362524454040 . -_:g70362524697800 . -_:g70362524697800 "0"^^ . -_:g70362524697800 "1"^^ . -_:g70362524697800 . -_:g70362524697800 _:g70362524601440 . -_:g70362525455200 _:g70362525090000 . -_:g70362525455200 . -_:g70362525440280 _:g70362512663660 . -_:g70362525440280 _:g70362525451560 . -_:g70362524370300 _:g70362524467420 . -_:g70362524370300 _:g70362524372900 . -_:g70362525669720 _:g70362515944160 . -_:g70362525669720 _:g70362507327280 . -_:g70362524256100 . -_:g70362524256100 "0"^^ . -_:g70362524256100 "1"^^ . -_:g70362524256100 . -_:g70362524256100 _:g70362524157680 . -_:g70362524799520 . -_:g70362524799520 . -_:g70362511585560 . -_:g70362511585560 _:g70362511631960 . -_:g70362516842260 . -_:g70362516842260 "0"^^ . -_:g70362516842260 "1"^^ . -_:g70362516842260 . -_:g70362516842260 _:g70362516777840 . -_:g70362524654840 _:g70362524287600 . -_:g70362524654840 . -_:g70362516597560 . -_:g70362516597560 _:g70362516600920 . -_:g70362524863960 _:g70362517103960 . -_:g70362524863960 . -_:g70362516600920 . -_:g70362516600920 . - . - _:g70362524977780 . - "true"^^ . -_:g70362517070540 . -_:g70362517070540 "0"^^ . -_:g70362517070540 "1"^^ . -_:g70362517070540 . -_:g70362517070540 _:g70362516859100 . -_:g70362516352960 . -_:g70362516352960 "0"^^ . -_:g70362516352960 "1"^^ . -_:g70362516352960 . -_:g70362516352960 _:g70362516042440 . - _:g70362517060600 . - . -_:g70362524505880 . -_:g70362524505880 . -_:g70362524631240 _:g70362524982380 . -_:g70362524631240 _:g70362524634000 . -_:g70362525093640 _:g70362524745820 . -_:g70362525093640 . -_:g70362524240080 . -_:g70362524240080 _:g70362524242980 . -_:g70362524863800 _:g70362516536320 . -_:g70362524863800 . -_:g70362525357520 . -_:g70362525357520 . -_:g70362525357520 . -_:g70362525418840 . -_:g70362525418840 . -_:g70362525418840 . -_:g70362525339000 . -_:g70362525339000 . -_:g70362525339000 _:g70362525276740 . -_:g70362524861640 . -_:g70362524861640 . -_:g70362524861640 . -_:g70362516023600 . -_:g70362516023600 . -_:g70362524287600 _:g70362524617980 . -_:g70362524287600 _:g70362524291060 . - _:g70362524617380 . - . - . - _:g70362525093640 . - "true"^^ . -_:g70362524884580 . -_:g70362524884580 _:g70362524845240 . -_:g70362517103960 _:g70362524829940 . -_:g70362517103960 _:g70362517155760 . -_:g70362525058300 . -_:g70362525058300 . -_:g70362525058300 . -_:g70362525570460 _:g70362507848060 . -_:g70362525570460 . -_:g70362524537460 . -_:g70362524537460 . -_:g70362524537460 _:g70362524475220 . -_:g70362525567540 _:g70362512502560 . -_:g70362525567540 _:g70362525570460 . -_:g70362524780680 _:g70362524861640 . -_:g70362524780680 . -_:g70362524861200 _:g70362524713660 . -_:g70362524861200 _:g70362524863800 . -_:g70362525208140 _:g70362525287560 . -_:g70362525208140 . -_:g70362524980200 . -_:g70362524980200 . -_:g70362525124120 . -_:g70362525124120 . -_:g70362525124120 . -_:g70362525057100 . -_:g70362525057100 . -_:g70362525057100 . - _:g70362524966080 . - . -_:g70362525212500 . -_:g70362525212500 . - . - _:g70362524863960 . - "true"^^ . -_:g70362513445960 . -_:g70362513445960 . -_:g70362513445960 _:g70362513166080 . -_:g70362525097180 _:g70362525293040 . -_:g70362525097180 . -_:g70362525276740 _:g70362525142000 . -_:g70362525276740 . -_:g70362517219060 _:g70362524325020 . -_:g70362517219060 _:g70362517223520 . -_:g70362516536320 . -_:g70362516536320 "0"^^ . -_:g70362516536320 "1"^^ . -_:g70362516536320 . -_:g70362516536320 . -_:g70362516466320 . -_:g70362516466320 . -_:g70362516466320 _:g70362516234820 . -_:g70362525451560 _:g70362525651960 . -_:g70362525451560 . -_:g70362524356920 . -_:g70362524356920 _:g70362524293820 . -_:g70362511631960 . -_:g70362511631960 . -_:g70362524305040 "false"^^ . -_:g70362524305040 . - . - _:g70362525392800 . - "true"^^ . -_:g70362513266060 . -_:g70362513266060 "0"^^ . -_:g70362513266060 "1"^^ . -_:g70362513266060 . -_:g70362513266060 . -_:g70362524343920 . -_:g70362524343920 . -_:g70362524928380 _:g70362524796620 . -_:g70362524928380 . -_:g70362524977780 _:g70362524769120 . -_:g70362524977780 . -_:g70362507391280 _:g70362512500060 . -_:g70362507391280 . -_:g70362517155760 _:g70362524697800 . -_:g70362517155760 _:g70362517187160 . - _:g70362524359080 . - . -_:g70362517203940 _:g70362524402980 . -_:g70362517203940 _:g70362517219060 . -_:g70362524537940 . -_:g70362524537940 _:g70362524489380 . -_:g70362525309940 . -_:g70362525309940 "0"^^ . -_:g70362525309940 "1"^^ . -_:g70362525309940 . -_:g70362525309940 _:g70362525354640 . -_:g70362525538740 _:g70362516710520 . -_:g70362525538740 _:g70362525550520 . -_:g70362516651500 . -_:g70362516651500 _:g70362516547860 . -_:g70362525637840 _:g70362524456040 . -_:g70362525637840 _:g70362525649080 . -_:g70362516614820 _:g70362516861800 . -_:g70362516614820 _:g70362516627940 . -_:g70362517221460 "true"^^ . -_:g70362517221460 _:g70362524106940 . -_:g70362524617380 _:g70362525124120 . -_:g70362524617380 _:g70362524620120 . -_:g70362525601720 . -_:g70362525601720 . -_:g70362517187160 _:g70362524549920 . -_:g70362517187160 _:g70362517203940 . -_:g70362512935560 . -_:g70362512935560 . -_:g70362512935560 . -_:g70362515908780 . -_:g70362515908780 "0"^^ . -_:g70362515908780 "1"^^ . -_:g70362515908780 . -_:g70362515908780 _:g70362513333540 . -_:g70362511785400 _:g70362512988860 . -_:g70362511785400 . -_:g70362516467220 _:g70362524130660 . -_:g70362516467220 _:g70362516484480 . -_:g70362524475220 _:g70362524340120 . -_:g70362524475220 . -_:g70362524798440 . -_:g70362524798440 . -_:g70362525041220 . -_:g70362525041220 . -_:g70362524174940 _:g70362516467220 . -_:g70362524174940 . -_:g70362524242980 . -_:g70362524242980 . -_:g70362525094060 _:g70362525340400 . -_:g70362525094060 _:g70362525097180 . -_:g70362525550520 _:g70362516352960 . -_:g70362525550520 _:g70362525553060 . -_:g70362525221960 _:g70362525536760 . -_:g70362525221960 _:g70362525224600 . -_:g70362511958360 . -_:g70362511958360 _:g70362508309920 . -_:g70362516714680 . -_:g70362516714680 . -_:g70362524966080 . -_:g70362524966080 _:g70362524977480 . - _:g70362525094060 . - . -_:g70362517072520 _:g70362524107200 . -_:g70362517072520 . -_:g70362524848920 . -_:g70362524848920 . -_:g70362524848920 _:g70362524798440 . -_:g70362513333540 . -_:g70362513333540 . -_:g70362516220400 . -_:g70362516220400 . -_:g70362516220400 _:g70362516089580 . -_:g70362525553060 _:g70362515908780 . -_:g70362525553060 _:g70362525556320 . -_:g70362524634000 _:g70362524915780 . -_:g70362524634000 _:g70362524636620 . + . + _:b0_b67 . + . + _:b0_b240 . + . + _:b0_b169 . + . + _:b0_b205 . + . + _:b0_b103 . + . + _:b0_b246 . + . + _:b0_b109 . + . + _:b0_b131 . + . + _:b0_b137 . + . + _:b0_b262 . + . + _:b0_b143 . + . + _:b0_b117 . + . + _:b0_b254 . + . + _:b0_b123 . + . + _:b0_b33 . + . + _:b0_b157 . + . + _:b0_b158 . + . + _:b0_b1 . + . + _:b0_b59 . + . + _:b0_b212 . + . + _:b0_b44 . + . + _:b0_b23 . + . + _:b0_b10 . + . + _:b0_b218 . + . + _:b0_b56 . + . + _:b0_b28 . + . + _:b0_b18 . + . + _:b0_b180 . + . + _:b0_b151 . + . + _:b0_b74 . + . + _:b0_b511 . + . + _:b0_b95 . + . + _:b0_b100 . + . + _:b0_b9 . + . + _:b0_b228 . + . + _:b0_b224 . + . + _:b0_b17 . + . + _:b0_b517 . + . + _:b0_b156 . + . + _:b0_b199 . + . + _:b0_b195 . + . + _:b0_b99 . + . + _:b0_b234 . + . + _:b0_b521 . + "-1"^^ . + "0"^^ . +_:b0_b0 . +_:b0_b0 _:b0_b270 . +_:b0_b0 . +_:b0_b1 . +_:b0_b1 "true"^^ . +_:b0_b1 _:b0_b2 . +_:b0_b10 . +_:b0_b10 "true"^^ . +_:b0_b10 _:b0_b11 . +_:b0_b100 . +_:b0_b100 _:b0_b311 . +_:b0_b101 . +_:b0_b101 . +_:b0_b102 . +_:b0_b102 . +_:b0_b103 . +_:b0_b103 "true"^^ . +_:b0_b103 _:b0_b104 . +_:b0_b104 . +_:b0_b104 _:b0_b313 . +_:b0_b105 . +_:b0_b105 . +_:b0_b105 _:b0_b106 . +_:b0_b106 . +_:b0_b106 _:b0_b315 . +_:b0_b107 . +_:b0_b107 . +_:b0_b107 _:b0_b108 . +_:b0_b108 . +_:b0_b108 . +_:b0_b109 . +_:b0_b109 "true"^^ . +_:b0_b109 _:b0_b110 . +_:b0_b11 . +_:b0_b11 _:b0_b316 . +_:b0_b110 . +_:b0_b110 _:b0_b319 . +_:b0_b111 . +_:b0_b111 . +_:b0_b111 _:b0_b112 . +_:b0_b112 . +_:b0_b112 _:b0_b322 . +_:b0_b113 . +_:b0_b113 . +_:b0_b113 _:b0_b114 . +_:b0_b114 . +_:b0_b114 _:b0_b323 . +_:b0_b115 . +_:b0_b115 . +_:b0_b116 . +_:b0_b116 . +_:b0_b116 . +_:b0_b117 . +_:b0_b117 "true"^^ . +_:b0_b117 _:b0_b118 . +_:b0_b118 . +_:b0_b118 _:b0_b325 . +_:b0_b119 . +_:b0_b119 . +_:b0_b119 _:b0_b120 . +_:b0_b12 . +_:b0_b12 . +_:b0_b12 _:b0_b13 . +_:b0_b120 . +_:b0_b120 _:b0_b327 . +_:b0_b121 . +_:b0_b121 . +_:b0_b121 _:b0_b122 . +_:b0_b122 . +_:b0_b122 . +_:b0_b123 . +_:b0_b123 "true"^^ . +_:b0_b123 _:b0_b124 . +_:b0_b124 . +_:b0_b124 _:b0_b328 . +_:b0_b125 . +_:b0_b125 . +_:b0_b125 _:b0_b126 . +_:b0_b126 . +_:b0_b126 _:b0_b331 . +_:b0_b127 . +_:b0_b127 . +_:b0_b127 _:b0_b128 . +_:b0_b128 . +_:b0_b128 _:b0_b332 . +_:b0_b129 . +_:b0_b129 . +_:b0_b13 . +_:b0_b13 _:b0_b334 . +_:b0_b130 . +_:b0_b130 . +_:b0_b130 . +_:b0_b131 . +_:b0_b131 "true"^^ . +_:b0_b131 _:b0_b132 . +_:b0_b132 . +_:b0_b132 _:b0_b335 . +_:b0_b133 . +_:b0_b133 . +_:b0_b133 _:b0_b134 . +_:b0_b134 . +_:b0_b134 _:b0_b337 . +_:b0_b135 . +_:b0_b135 . +_:b0_b135 _:b0_b136 . +_:b0_b136 . +_:b0_b136 . +_:b0_b137 . +_:b0_b137 "true"^^ . +_:b0_b137 _:b0_b138 . +_:b0_b138 . +_:b0_b138 _:b0_b338 . +_:b0_b139 . +_:b0_b139 . +_:b0_b139 _:b0_b140 . +_:b0_b14 . +_:b0_b14 "1"^^ . +_:b0_b14 "0"^^ . +_:b0_b14 . +_:b0_b14 _:b0_b15 . +_:b0_b140 . +_:b0_b140 _:b0_b340 . +_:b0_b141 . +_:b0_b141 . +_:b0_b141 _:b0_b142 . +_:b0_b142 . +_:b0_b142 . +_:b0_b143 . +_:b0_b143 "true"^^ . +_:b0_b143 _:b0_b144 . +_:b0_b144 . +_:b0_b144 _:b0_b341 . +_:b0_b145 . +_:b0_b145 . +_:b0_b145 _:b0_b146 . +_:b0_b146 . +_:b0_b146 _:b0_b344 . +_:b0_b147 . +_:b0_b147 . +_:b0_b147 _:b0_b148 . +_:b0_b148 . +_:b0_b148 _:b0_b345 . +_:b0_b149 . +_:b0_b149 . +_:b0_b15 . +_:b0_b15 _:b0_b347 . +_:b0_b150 . +_:b0_b150 . +_:b0_b150 . +_:b0_b151 . +_:b0_b151 _:b0_b349 . +_:b0_b152 . +_:b0_b152 . +_:b0_b153 . +_:b0_b153 "true"^^ . +_:b0_b153 _:b0_b154 . +_:b0_b154 . +_:b0_b154 . +_:b0_b154 _:b0_b155 . +_:b0_b155 . +_:b0_b155 _:b0_b351 . +_:b0_b156 . +_:b0_b156 _:b0_b352 . +_:b0_b157 . +_:b0_b157 "true"^^ . +_:b0_b158 . +_:b0_b158 "true"^^ . +_:b0_b158 _:b0_b159 . +_:b0_b159 . +_:b0_b159 _:b0_b356 . +_:b0_b16 . +_:b0_b16 . +_:b0_b16 . +_:b0_b160 . +_:b0_b160 . +_:b0_b160 _:b0_b161 . +_:b0_b161 . +_:b0_b161 _:b0_b362 . +_:b0_b162 . +_:b0_b162 "1"^^ . +_:b0_b162 "0"^^ . +_:b0_b162 . +_:b0_b162 _:b0_b163 . +_:b0_b163 . +_:b0_b163 . +_:b0_b164 . +_:b0_b164 "1"^^ . +_:b0_b164 "0"^^ . +_:b0_b164 . +_:b0_b164 _:b0_b165 . +_:b0_b165 . +_:b0_b165 . +_:b0_b166 . +_:b0_b166 . +_:b0_b166 . +_:b0_b167 . +_:b0_b167 "1"^^ . +_:b0_b167 "0"^^ . +_:b0_b167 . +_:b0_b167 . +_:b0_b168 . +_:b0_b168 "1"^^ . +_:b0_b168 "0"^^ . +_:b0_b168 . +_:b0_b168 . +_:b0_b169 . +_:b0_b169 "true"^^ . +_:b0_b169 _:b0_b170 . +_:b0_b17 . +_:b0_b17 _:b0_b363 . +_:b0_b170 . +_:b0_b170 _:b0_b369 . +_:b0_b171 . +_:b0_b171 . +_:b0_b171 _:b0_b172 . +_:b0_b172 . +_:b0_b172 _:b0_b375 . +_:b0_b173 . +_:b0_b173 "1"^^ . +_:b0_b173 "0"^^ . +_:b0_b173 . +_:b0_b173 _:b0_b174 . +_:b0_b174 . +_:b0_b174 . +_:b0_b175 . +_:b0_b175 "1"^^ . +_:b0_b175 "0"^^ . +_:b0_b175 . +_:b0_b175 _:b0_b176 . +_:b0_b176 . +_:b0_b176 . +_:b0_b177 . +_:b0_b177 . +_:b0_b177 . +_:b0_b178 . +_:b0_b178 "1"^^ . +_:b0_b178 "0"^^ . +_:b0_b178 . +_:b0_b178 . +_:b0_b179 . +_:b0_b179 "1"^^ . +_:b0_b179 "0"^^ . +_:b0_b179 . +_:b0_b179 . +_:b0_b18 . +_:b0_b18 "true"^^ . +_:b0_b18 _:b0_b19 . +_:b0_b180 . +_:b0_b180 "true"^^ . +_:b0_b180 _:b0_b181 . +_:b0_b181 . +_:b0_b181 _:b0_b376 . +_:b0_b182 . +_:b0_b182 . +_:b0_b182 _:b0_b183 . +_:b0_b183 . +_:b0_b183 _:b0_b384 . +_:b0_b184 . +_:b0_b184 "1"^^ . +_:b0_b184 "0"^^ . +_:b0_b184 . +_:b0_b184 _:b0_b185 . +_:b0_b185 . +_:b0_b185 _:b0_b385 . +_:b0_b186 . +_:b0_b186 "1"^^ . +_:b0_b186 "0"^^ . +_:b0_b186 . +_:b0_b186 _:b0_b187 . +_:b0_b187 . +_:b0_b187 . +_:b0_b188 . +_:b0_b188 "1"^^ . +_:b0_b188 "0"^^ . +_:b0_b188 . +_:b0_b188 _:b0_b189 . +_:b0_b189 . +_:b0_b189 . +_:b0_b19 . +_:b0_b19 _:b0_b387 . +_:b0_b190 . +_:b0_b190 . +_:b0_b190 _:b0_b191 . +_:b0_b191 . +_:b0_b191 . +_:b0_b192 . +_:b0_b192 "1"^^ . +_:b0_b192 "0"^^ . +_:b0_b192 . +_:b0_b192 . +_:b0_b193 . +_:b0_b193 "1"^^ . +_:b0_b193 "0"^^ . +_:b0_b193 . +_:b0_b193 . +_:b0_b194 . +_:b0_b194 "1"^^ . +_:b0_b194 "0"^^ . +_:b0_b194 . +_:b0_b194 . +_:b0_b195 . +_:b0_b195 "true"^^ . +_:b0_b195 _:b0_b196 . +_:b0_b196 . +_:b0_b196 _:b0_b389 . +_:b0_b197 . +_:b0_b197 . +_:b0_b197 . +_:b0_b198 . +_:b0_b198 . +_:b0_b198 . +_:b0_b199 . +_:b0_b199 "true"^^ . +_:b0_b199 _:b0_b200 . +_:b0_b2 . +_:b0_b2 _:b0_b391 . +_:b0_b20 . +_:b0_b20 . +_:b0_b20 _:b0_b21 . +_:b0_b200 . +_:b0_b200 _:b0_b396 . +_:b0_b201 . +_:b0_b201 . +_:b0_b201 . +_:b0_b202 . +_:b0_b202 . +_:b0_b202 _:b0_b203 . +_:b0_b203 . +_:b0_b203 _:b0_b398 . +_:b0_b204 . +_:b0_b204 _:b0_b400 . +_:b0_b205 . +_:b0_b205 "true"^^ . +_:b0_b205 _:b0_b206 . +_:b0_b206 . +_:b0_b206 _:b0_b401 . +_:b0_b207 . +_:b0_b207 . +_:b0_b207 _:b0_b208 . +_:b0_b208 . +_:b0_b208 . +_:b0_b209 . +_:b0_b209 . +_:b0_b209 _:b0_b210 . +_:b0_b21 . +_:b0_b21 _:b0_b403 . +_:b0_b210 . +_:b0_b210 _:b0_b404 . +_:b0_b211 . +_:b0_b211 _:b0_b406 . +_:b0_b212 . +_:b0_b212 "true"^^ . +_:b0_b212 _:b0_b213 . +_:b0_b213 . +_:b0_b213 _:b0_b407 . +_:b0_b214 . +_:b0_b214 . +_:b0_b214 . +_:b0_b215 . +_:b0_b215 . +_:b0_b215 _:b0_b216 . +_:b0_b216 . +_:b0_b216 _:b0_b409 . +_:b0_b217 . +_:b0_b217 _:b0_b411 . +_:b0_b218 . +_:b0_b218 "true"^^ . +_:b0_b218 _:b0_b219 . +_:b0_b219 . +_:b0_b219 _:b0_b412 . +_:b0_b22 . +_:b0_b22 . +_:b0_b22 . +_:b0_b220 . +_:b0_b220 . +_:b0_b220 . +_:b0_b221 . +_:b0_b221 . +_:b0_b221 _:b0_b222 . +_:b0_b222 . +_:b0_b222 _:b0_b414 . +_:b0_b223 . +_:b0_b223 _:b0_b416 . +_:b0_b224 . +_:b0_b224 "true"^^ . +_:b0_b224 _:b0_b225 . +_:b0_b225 . +_:b0_b225 _:b0_b417 . +_:b0_b226 . +_:b0_b226 . +_:b0_b226 . +_:b0_b227 . +_:b0_b227 . +_:b0_b227 . +_:b0_b228 . +_:b0_b228 "true"^^ . +_:b0_b228 _:b0_b229 . +_:b0_b229 . +_:b0_b229 _:b0_b419 . +_:b0_b23 . +_:b0_b23 "true"^^ . +_:b0_b23 _:b0_b24 . +_:b0_b230 . +_:b0_b230 . +_:b0_b230 . +_:b0_b231 . +_:b0_b231 . +_:b0_b231 _:b0_b232 . +_:b0_b232 . +_:b0_b232 _:b0_b421 . +_:b0_b233 . +_:b0_b233 _:b0_b423 . +_:b0_b234 . +_:b0_b234 "true"^^ . +_:b0_b234 _:b0_b235 . +_:b0_b235 . +_:b0_b235 _:b0_b424 . +_:b0_b236 . +_:b0_b236 . +_:b0_b236 . +_:b0_b237 . +_:b0_b237 . +_:b0_b237 _:b0_b238 . +_:b0_b238 . +_:b0_b238 _:b0_b426 . +_:b0_b239 . +_:b0_b239 _:b0_b428 . +_:b0_b24 . +_:b0_b24 _:b0_b429 . +_:b0_b240 . +_:b0_b240 "true"^^ . +_:b0_b240 _:b0_b241 . +_:b0_b241 . +_:b0_b241 _:b0_b431 . +_:b0_b242 . +_:b0_b242 . +_:b0_b242 . +_:b0_b243 . +_:b0_b243 . +_:b0_b243 _:b0_b244 . +_:b0_b244 . +_:b0_b244 _:b0_b433 . +_:b0_b245 . +_:b0_b245 _:b0_b435 . +_:b0_b246 . +_:b0_b246 "true"^^ . +_:b0_b246 _:b0_b247 . +_:b0_b247 . +_:b0_b247 _:b0_b436 . +_:b0_b248 . +_:b0_b248 . +_:b0_b248 _:b0_b249 . +_:b0_b249 . +_:b0_b249 _:b0_b438 . +_:b0_b25 . +_:b0_b25 . +_:b0_b25 _:b0_b26 . +_:b0_b250 . +_:b0_b250 . +_:b0_b251 . +_:b0_b251 . +_:b0_b251 _:b0_b252 . +_:b0_b252 . +_:b0_b252 _:b0_b440 . +_:b0_b253 . +_:b0_b253 _:b0_b442 . +_:b0_b254 . +_:b0_b254 "true"^^ . +_:b0_b254 _:b0_b255 . +_:b0_b255 . +_:b0_b255 _:b0_b443 . +_:b0_b256 . +_:b0_b256 . +_:b0_b256 _:b0_b257 . +_:b0_b257 . +_:b0_b257 _:b0_b445 . +_:b0_b258 . +_:b0_b258 . +_:b0_b259 . +_:b0_b259 . +_:b0_b259 _:b0_b260 . +_:b0_b26 . +_:b0_b26 _:b0_b447 . +_:b0_b260 . +_:b0_b260 _:b0_b448 . +_:b0_b261 . +_:b0_b261 _:b0_b450 . +_:b0_b262 . +_:b0_b262 "true"^^ . +_:b0_b262 _:b0_b263 . +_:b0_b263 . +_:b0_b263 _:b0_b451 . +_:b0_b264 . +_:b0_b264 . +_:b0_b264 _:b0_b265 . +_:b0_b265 . +_:b0_b265 _:b0_b453 . +_:b0_b266 . +_:b0_b266 . +_:b0_b267 . +_:b0_b267 . +_:b0_b267 _:b0_b268 . +_:b0_b268 . +_:b0_b268 _:b0_b455 . +_:b0_b269 . +_:b0_b269 _:b0_b457 . +_:b0_b27 . +_:b0_b27 . +_:b0_b27 . +_:b0_b270 . +_:b0_b270 _:b0_b271 . +_:b0_b271 . +_:b0_b271 _:b0_b272 . +_:b0_b272 . +_:b0_b272 _:b0_b273 . +_:b0_b273 . +_:b0_b273 _:b0_b274 . +_:b0_b274 . +_:b0_b274 _:b0_b275 . +_:b0_b275 . +_:b0_b275 _:b0_b276 . +_:b0_b276 . +_:b0_b276 _:b0_b277 . +_:b0_b277 . +_:b0_b277 _:b0_b278 . +_:b0_b278 . +_:b0_b278 _:b0_b279 . +_:b0_b279 . +_:b0_b279 _:b0_b280 . +_:b0_b28 . +_:b0_b28 "true"^^ . +_:b0_b28 _:b0_b29 . +_:b0_b280 . +_:b0_b280 _:b0_b281 . +_:b0_b281 . +_:b0_b281 _:b0_b282 . +_:b0_b282 . +_:b0_b282 _:b0_b283 . +_:b0_b283 . +_:b0_b283 _:b0_b284 . +_:b0_b284 . +_:b0_b284 _:b0_b285 . +_:b0_b285 . +_:b0_b285 _:b0_b286 . +_:b0_b286 . +_:b0_b286 _:b0_b287 . +_:b0_b287 . +_:b0_b287 _:b0_b288 . +_:b0_b288 . +_:b0_b288 _:b0_b289 . +_:b0_b289 . +_:b0_b289 _:b0_b290 . +_:b0_b29 . +_:b0_b29 _:b0_b458 . +_:b0_b290 . +_:b0_b290 _:b0_b291 . +_:b0_b291 . +_:b0_b291 _:b0_b292 . +_:b0_b292 . +_:b0_b292 _:b0_b293 . +_:b0_b293 . +_:b0_b293 _:b0_b294 . +_:b0_b294 . +_:b0_b294 _:b0_b295 . +_:b0_b295 . +_:b0_b295 _:b0_b296 . +_:b0_b296 . +_:b0_b296 _:b0_b297 . +_:b0_b297 . +_:b0_b297 _:b0_b298 . +_:b0_b298 . +_:b0_b298 _:b0_b299 . +_:b0_b299 . +_:b0_b299 _:b0_b300 . +_:b0_b3 . +_:b0_b3 . +_:b0_b3 _:b0_b4 . +_:b0_b30 . +_:b0_b30 . +_:b0_b30 _:b0_b31 . +_:b0_b300 . +_:b0_b300 _:b0_b301 . +_:b0_b301 . +_:b0_b301 _:b0_b302 . +_:b0_b302 . +_:b0_b302 _:b0_b303 . +_:b0_b303 . +_:b0_b303 _:b0_b304 . +_:b0_b304 . +_:b0_b304 _:b0_b305 . +_:b0_b305 . +_:b0_b305 _:b0_b306 . +_:b0_b306 . +_:b0_b306 _:b0_b307 . +_:b0_b307 . +_:b0_b307 _:b0_b308 . +_:b0_b308 . +_:b0_b308 _:b0_b309 . +_:b0_b309 . +_:b0_b309 _:b0_b310 . +_:b0_b31 . +_:b0_b31 _:b0_b460 . +_:b0_b310 . +_:b0_b310 . +_:b0_b311 _:b0_b101 . +_:b0_b311 _:b0_b312 . +_:b0_b312 _:b0_b102 . +_:b0_b312 . +_:b0_b313 _:b0_b105 . +_:b0_b313 _:b0_b314 . +_:b0_b314 _:b0_b107 . +_:b0_b314 . +_:b0_b315 . +_:b0_b315 . +_:b0_b316 _:b0_b12 . +_:b0_b316 _:b0_b317 . +_:b0_b317 _:b0_b14 . +_:b0_b317 _:b0_b318 . +_:b0_b318 _:b0_b16 . +_:b0_b318 . +_:b0_b319 _:b0_b111 . +_:b0_b319 _:b0_b320 . +_:b0_b32 . +_:b0_b32 . +_:b0_b32 . +_:b0_b320 _:b0_b113 . +_:b0_b320 _:b0_b321 . +_:b0_b321 _:b0_b116 . +_:b0_b321 . +_:b0_b322 . +_:b0_b322 . +_:b0_b323 _:b0_b115 . +_:b0_b323 _:b0_b324 . +_:b0_b324 . +_:b0_b324 . +_:b0_b325 _:b0_b119 . +_:b0_b325 _:b0_b326 . +_:b0_b326 _:b0_b121 . +_:b0_b326 . +_:b0_b327 . +_:b0_b327 . +_:b0_b328 _:b0_b125 . +_:b0_b328 _:b0_b329 . +_:b0_b329 _:b0_b127 . +_:b0_b329 _:b0_b330 . +_:b0_b33 . +_:b0_b33 "true"^^ . +_:b0_b33 _:b0_b34 . +_:b0_b330 _:b0_b130 . +_:b0_b330 . +_:b0_b331 . +_:b0_b331 . +_:b0_b332 _:b0_b129 . +_:b0_b332 _:b0_b333 . +_:b0_b333 . +_:b0_b333 . +_:b0_b334 . +_:b0_b334 . +_:b0_b335 _:b0_b133 . +_:b0_b335 _:b0_b336 . +_:b0_b336 _:b0_b135 . +_:b0_b336 . +_:b0_b337 . +_:b0_b337 . +_:b0_b338 _:b0_b139 . +_:b0_b338 _:b0_b339 . +_:b0_b339 _:b0_b141 . +_:b0_b339 . +_:b0_b34 . +_:b0_b34 _:b0_b461 . +_:b0_b340 . +_:b0_b340 . +_:b0_b341 _:b0_b145 . +_:b0_b341 _:b0_b342 . +_:b0_b342 _:b0_b147 . +_:b0_b342 _:b0_b343 . +_:b0_b343 _:b0_b150 . +_:b0_b343 . +_:b0_b344 . +_:b0_b344 . +_:b0_b345 _:b0_b149 . +_:b0_b345 _:b0_b346 . +_:b0_b346 . +_:b0_b346 . +_:b0_b347 "true"^^ . +_:b0_b347 _:b0_b348 . +_:b0_b348 "false"^^ . +_:b0_b348 . +_:b0_b349 _:b0_b152 . +_:b0_b349 _:b0_b350 . +_:b0_b35 . +_:b0_b35 . +_:b0_b35 _:b0_b36 . +_:b0_b350 _:b0_b153 . +_:b0_b350 . +_:b0_b351 . +_:b0_b351 . +_:b0_b352 . +_:b0_b352 _:b0_b353 . +_:b0_b353 . +_:b0_b353 _:b0_b354 . +_:b0_b354 . +_:b0_b354 _:b0_b355 . +_:b0_b355 . +_:b0_b355 . +_:b0_b356 _:b0_b160 . +_:b0_b356 _:b0_b357 . +_:b0_b357 _:b0_b162 . +_:b0_b357 _:b0_b358 . +_:b0_b358 _:b0_b164 . +_:b0_b358 _:b0_b359 . +_:b0_b359 _:b0_b166 . +_:b0_b359 _:b0_b360 . +_:b0_b36 . +_:b0_b36 _:b0_b468 . +_:b0_b360 _:b0_b167 . +_:b0_b360 _:b0_b361 . +_:b0_b361 _:b0_b168 . +_:b0_b361 . +_:b0_b362 . +_:b0_b362 . +_:b0_b363 . +_:b0_b363 _:b0_b364 . +_:b0_b364 . +_:b0_b364 _:b0_b365 . +_:b0_b365 . +_:b0_b365 _:b0_b366 . +_:b0_b366 . +_:b0_b366 _:b0_b367 . +_:b0_b367 . +_:b0_b367 _:b0_b368 . +_:b0_b368 . +_:b0_b368 . +_:b0_b369 _:b0_b171 . +_:b0_b369 _:b0_b370 . +_:b0_b37 . +_:b0_b37 "1"^^ . +_:b0_b37 "0"^^ . +_:b0_b37 . +_:b0_b37 _:b0_b38 . +_:b0_b370 _:b0_b173 . +_:b0_b370 _:b0_b371 . +_:b0_b371 _:b0_b175 . +_:b0_b371 _:b0_b372 . +_:b0_b372 _:b0_b177 . +_:b0_b372 _:b0_b373 . +_:b0_b373 _:b0_b178 . +_:b0_b373 _:b0_b374 . +_:b0_b374 _:b0_b179 . +_:b0_b374 . +_:b0_b375 . +_:b0_b375 . +_:b0_b376 _:b0_b182 . +_:b0_b376 _:b0_b377 . +_:b0_b377 _:b0_b184 . +_:b0_b377 _:b0_b378 . +_:b0_b378 _:b0_b186 . +_:b0_b378 _:b0_b379 . +_:b0_b379 _:b0_b188 . +_:b0_b379 _:b0_b380 . +_:b0_b38 . +_:b0_b38 _:b0_b469 . +_:b0_b380 _:b0_b190 . +_:b0_b380 _:b0_b381 . +_:b0_b381 _:b0_b192 . +_:b0_b381 _:b0_b382 . +_:b0_b382 _:b0_b193 . +_:b0_b382 _:b0_b383 . +_:b0_b383 _:b0_b194 . +_:b0_b383 . +_:b0_b384 . +_:b0_b384 . +_:b0_b385 "true"^^ . +_:b0_b385 _:b0_b386 . +_:b0_b386 "false"^^ . +_:b0_b386 . +_:b0_b387 _:b0_b20 . +_:b0_b387 _:b0_b388 . +_:b0_b388 _:b0_b22 . +_:b0_b388 . +_:b0_b389 _:b0_b197 . +_:b0_b389 _:b0_b390 . +_:b0_b39 . +_:b0_b39 "1"^^ . +_:b0_b39 "0"^^ . +_:b0_b39 . +_:b0_b39 _:b0_b40 . +_:b0_b390 _:b0_b198 . +_:b0_b390 . +_:b0_b391 _:b0_b3 . +_:b0_b391 _:b0_b392 . +_:b0_b392 _:b0_b5 . +_:b0_b392 _:b0_b393 . +_:b0_b393 _:b0_b6 . +_:b0_b393 _:b0_b394 . +_:b0_b394 _:b0_b7 . +_:b0_b394 _:b0_b395 . +_:b0_b395 _:b0_b8 . +_:b0_b395 . +_:b0_b396 _:b0_b201 . +_:b0_b396 _:b0_b397 . +_:b0_b397 _:b0_b202 . +_:b0_b397 . +_:b0_b398 _:b0_b204 . +_:b0_b398 _:b0_b399 . +_:b0_b399 . +_:b0_b399 . +_:b0_b4 . +_:b0_b4 _:b0_b473 . +_:b0_b40 . +_:b0_b40 . +_:b0_b400 . +_:b0_b400 . +_:b0_b401 _:b0_b207 . +_:b0_b401 _:b0_b402 . +_:b0_b402 _:b0_b209 . +_:b0_b402 . +_:b0_b403 . +_:b0_b403 . +_:b0_b404 _:b0_b211 . +_:b0_b404 _:b0_b405 . +_:b0_b405 . +_:b0_b405 . +_:b0_b406 . +_:b0_b406 . +_:b0_b407 _:b0_b214 . +_:b0_b407 _:b0_b408 . +_:b0_b408 _:b0_b215 . +_:b0_b408 . +_:b0_b409 _:b0_b217 . +_:b0_b409 _:b0_b410 . +_:b0_b41 . +_:b0_b41 "1"^^ . +_:b0_b41 "0"^^ . +_:b0_b41 . +_:b0_b41 . +_:b0_b410 . +_:b0_b410 . +_:b0_b411 . +_:b0_b411 . +_:b0_b412 _:b0_b220 . +_:b0_b412 _:b0_b413 . +_:b0_b413 _:b0_b221 . +_:b0_b413 . +_:b0_b414 _:b0_b223 . +_:b0_b414 _:b0_b415 . +_:b0_b415 . +_:b0_b415 . +_:b0_b416 . +_:b0_b416 . +_:b0_b417 _:b0_b226 . +_:b0_b417 _:b0_b418 . +_:b0_b418 _:b0_b227 . +_:b0_b418 . +_:b0_b419 _:b0_b230 . +_:b0_b419 _:b0_b420 . +_:b0_b42 . +_:b0_b42 "1"^^ . +_:b0_b42 "0"^^ . +_:b0_b42 . +_:b0_b42 . +_:b0_b420 _:b0_b231 . +_:b0_b420 . +_:b0_b421 _:b0_b233 . +_:b0_b421 _:b0_b422 . +_:b0_b422 . +_:b0_b422 . +_:b0_b423 . +_:b0_b423 . +_:b0_b424 _:b0_b236 . +_:b0_b424 _:b0_b425 . +_:b0_b425 _:b0_b237 . +_:b0_b425 . +_:b0_b426 _:b0_b239 . +_:b0_b426 _:b0_b427 . +_:b0_b427 . +_:b0_b427 . +_:b0_b428 . +_:b0_b428 . +_:b0_b429 _:b0_b25 . +_:b0_b429 _:b0_b430 . +_:b0_b43 . +_:b0_b43 "1"^^ . +_:b0_b43 "0"^^ . +_:b0_b43 . +_:b0_b43 . +_:b0_b430 _:b0_b27 . +_:b0_b430 . +_:b0_b431 _:b0_b242 . +_:b0_b431 _:b0_b432 . +_:b0_b432 _:b0_b243 . +_:b0_b432 . +_:b0_b433 _:b0_b245 . +_:b0_b433 _:b0_b434 . +_:b0_b434 . +_:b0_b434 . +_:b0_b435 . +_:b0_b435 . +_:b0_b436 _:b0_b248 . +_:b0_b436 _:b0_b437 . +_:b0_b437 _:b0_b251 . +_:b0_b437 . +_:b0_b438 _:b0_b250 . +_:b0_b438 _:b0_b439 . +_:b0_b439 . +_:b0_b439 . +_:b0_b44 . +_:b0_b44 "true"^^ . +_:b0_b44 _:b0_b45 . +_:b0_b440 _:b0_b253 . +_:b0_b440 _:b0_b441 . +_:b0_b441 . +_:b0_b441 . +_:b0_b442 . +_:b0_b442 . +_:b0_b443 _:b0_b256 . +_:b0_b443 _:b0_b444 . +_:b0_b444 _:b0_b259 . +_:b0_b444 . +_:b0_b445 _:b0_b258 . +_:b0_b445 _:b0_b446 . +_:b0_b446 . +_:b0_b446 . +_:b0_b447 . +_:b0_b447 . +_:b0_b448 _:b0_b261 . +_:b0_b448 _:b0_b449 . +_:b0_b449 . +_:b0_b449 . +_:b0_b45 . +_:b0_b45 _:b0_b474 . +_:b0_b450 . +_:b0_b450 . +_:b0_b451 _:b0_b264 . +_:b0_b451 _:b0_b452 . +_:b0_b452 _:b0_b267 . +_:b0_b452 . +_:b0_b453 _:b0_b266 . +_:b0_b453 _:b0_b454 . +_:b0_b454 . +_:b0_b454 . +_:b0_b455 _:b0_b269 . +_:b0_b455 _:b0_b456 . +_:b0_b456 . +_:b0_b456 . +_:b0_b457 . +_:b0_b457 . +_:b0_b458 _:b0_b30 . +_:b0_b458 _:b0_b459 . +_:b0_b459 _:b0_b32 . +_:b0_b459 . +_:b0_b46 . +_:b0_b46 . +_:b0_b46 _:b0_b47 . +_:b0_b460 . +_:b0_b460 . +_:b0_b461 _:b0_b35 . +_:b0_b461 _:b0_b462 . +_:b0_b462 _:b0_b37 . +_:b0_b462 _:b0_b463 . +_:b0_b463 _:b0_b39 . +_:b0_b463 _:b0_b464 . +_:b0_b464 . +_:b0_b464 _:b0_b465 . +_:b0_b465 _:b0_b41 . +_:b0_b465 _:b0_b466 . +_:b0_b466 _:b0_b42 . +_:b0_b466 _:b0_b467 . +_:b0_b467 _:b0_b43 . +_:b0_b467 . +_:b0_b468 . +_:b0_b468 . +_:b0_b469 . +_:b0_b469 _:b0_b470 . +_:b0_b47 . +_:b0_b47 _:b0_b481 . +_:b0_b470 . +_:b0_b470 _:b0_b471 . +_:b0_b471 . +_:b0_b471 _:b0_b472 . +_:b0_b472 . +_:b0_b472 . +_:b0_b473 . +_:b0_b473 . +_:b0_b474 _:b0_b46 . +_:b0_b474 _:b0_b475 . +_:b0_b475 _:b0_b48 . +_:b0_b475 _:b0_b476 . +_:b0_b476 _:b0_b49 . +_:b0_b476 _:b0_b477 . +_:b0_b477 _:b0_b51 . +_:b0_b477 _:b0_b478 . +_:b0_b478 _:b0_b53 . +_:b0_b478 _:b0_b479 . +_:b0_b479 _:b0_b54 . +_:b0_b479 _:b0_b480 . +_:b0_b48 . +_:b0_b48 "1"^^ . +_:b0_b48 "0"^^ . +_:b0_b48 . +_:b0_b48 . +_:b0_b480 _:b0_b55 . +_:b0_b480 . +_:b0_b481 . +_:b0_b481 . +_:b0_b482 "true"^^ . +_:b0_b482 _:b0_b483 . +_:b0_b483 "false"^^ . +_:b0_b483 . +_:b0_b484 . +_:b0_b484 . +_:b0_b485 _:b0_b61 . +_:b0_b485 _:b0_b486 . +_:b0_b486 _:b0_b63 . +_:b0_b486 _:b0_b487 . +_:b0_b487 _:b0_b65 . +_:b0_b487 . +_:b0_b488 . +_:b0_b488 . +_:b0_b489 _:b0_b69 . +_:b0_b489 _:b0_b490 . +_:b0_b49 . +_:b0_b49 "1"^^ . +_:b0_b49 "0"^^ . +_:b0_b49 . +_:b0_b49 _:b0_b50 . +_:b0_b490 _:b0_b71 . +_:b0_b490 _:b0_b491 . +_:b0_b491 _:b0_b73 . +_:b0_b491 . +_:b0_b492 . +_:b0_b492 . +_:b0_b493 . +_:b0_b493 _:b0_b494 . +_:b0_b494 . +_:b0_b494 _:b0_b495 . +_:b0_b495 . +_:b0_b495 . +_:b0_b496 _:b0_b83 . +_:b0_b496 _:b0_b497 . +_:b0_b497 _:b0_b85 . +_:b0_b497 . +_:b0_b498 . +_:b0_b498 _:b0_b499 . +_:b0_b499 . +_:b0_b499 . +_:b0_b5 . +_:b0_b5 "1"^^ . +_:b0_b5 "0"^^ . +_:b0_b5 . +_:b0_b5 . +_:b0_b50 . +_:b0_b50 _:b0_b482 . +_:b0_b500 _:b0_b96 . +_:b0_b500 _:b0_b501 . +_:b0_b501 _:b0_b97 . +_:b0_b501 _:b0_b502 . +_:b0_b502 _:b0_b98 . +_:b0_b502 . +_:b0_b503 . +_:b0_b503 _:b0_b504 . +_:b0_b504 . +_:b0_b504 _:b0_b505 . +_:b0_b505 . +_:b0_b505 _:b0_b506 . +_:b0_b506 . +_:b0_b506 _:b0_b507 . +_:b0_b507 . +_:b0_b507 _:b0_b508 . +_:b0_b508 . +_:b0_b508 _:b0_b509 . +_:b0_b509 . +_:b0_b509 _:b0_b510 . +_:b0_b51 . +_:b0_b51 "-1"^^ . +_:b0_b51 "0"^^ . +_:b0_b51 . +_:b0_b51 _:b0_b52 . +_:b0_b510 . +_:b0_b510 . +_:b0_b511 _:b0_b87 . +_:b0_b511 _:b0_b512 . +_:b0_b512 _:b0_b88 . +_:b0_b512 _:b0_b513 . +_:b0_b513 _:b0_b89 . +_:b0_b513 _:b0_b514 . +_:b0_b514 _:b0_b90 . +_:b0_b514 _:b0_b515 . +_:b0_b515 _:b0_b91 . +_:b0_b515 _:b0_b516 . +_:b0_b516 _:b0_b93 . +_:b0_b516 . +_:b0_b517 _:b0_b76 . +_:b0_b517 _:b0_b518 . +_:b0_b518 _:b0_b78 . +_:b0_b518 _:b0_b519 . +_:b0_b519 _:b0_b80 . +_:b0_b519 _:b0_b520 . +_:b0_b52 . +_:b0_b52 . +_:b0_b520 _:b0_b82 . +_:b0_b520 . +_:b0_b521 . +_:b0_b521 _:b0_b522 . +_:b0_b522 . +_:b0_b522 . +_:b0_b53 . +_:b0_b53 "1"^^ . +_:b0_b53 "0"^^ . +_:b0_b53 . +_:b0_b53 . +_:b0_b54 . +_:b0_b54 "1"^^ . +_:b0_b54 "0"^^ . +_:b0_b54 . +_:b0_b54 . +_:b0_b55 . +_:b0_b55 "1"^^ . +_:b0_b55 "0"^^ . +_:b0_b55 . +_:b0_b55 . +_:b0_b56 . +_:b0_b56 "true"^^ . +_:b0_b56 _:b0_b57 . +_:b0_b57 . +_:b0_b57 . +_:b0_b57 _:b0_b58 . +_:b0_b58 . +_:b0_b58 _:b0_b484 . +_:b0_b59 . +_:b0_b59 "true"^^ . +_:b0_b59 _:b0_b60 . +_:b0_b6 . +_:b0_b6 "1"^^ . +_:b0_b6 "0"^^ . +_:b0_b6 . +_:b0_b6 . +_:b0_b60 . +_:b0_b60 _:b0_b485 . +_:b0_b61 . +_:b0_b61 . +_:b0_b61 _:b0_b62 . +_:b0_b62 . +_:b0_b62 _:b0_b488 . +_:b0_b63 . +_:b0_b63 . +_:b0_b63 _:b0_b64 . +_:b0_b64 . +_:b0_b64 . +_:b0_b65 . +_:b0_b65 "1"^^ . +_:b0_b65 "0"^^ . +_:b0_b65 . +_:b0_b65 _:b0_b66 . +_:b0_b66 . +_:b0_b66 . +_:b0_b67 . +_:b0_b67 "true"^^ . +_:b0_b67 _:b0_b68 . +_:b0_b68 . +_:b0_b68 _:b0_b489 . +_:b0_b69 . +_:b0_b69 . +_:b0_b69 _:b0_b70 . +_:b0_b7 . +_:b0_b7 "1"^^ . +_:b0_b7 "0"^^ . +_:b0_b7 . +_:b0_b7 . +_:b0_b70 . +_:b0_b70 _:b0_b492 . +_:b0_b71 . +_:b0_b71 . +_:b0_b71 _:b0_b72 . +_:b0_b72 . +_:b0_b72 . +_:b0_b73 . +_:b0_b73 . +_:b0_b73 . +_:b0_b74 . +_:b0_b74 _:b0_b75 . +_:b0_b75 . +_:b0_b75 _:b0_b493 . +_:b0_b76 . +_:b0_b76 . +_:b0_b76 _:b0_b77 . +_:b0_b77 . +_:b0_b77 . +_:b0_b78 . +_:b0_b78 . +_:b0_b78 _:b0_b79 . +_:b0_b79 . +_:b0_b79 . +_:b0_b8 . +_:b0_b8 "1"^^ . +_:b0_b8 "0"^^ . +_:b0_b8 . +_:b0_b8 . +_:b0_b80 . +_:b0_b80 . +_:b0_b80 _:b0_b81 . +_:b0_b81 . +_:b0_b81 . +_:b0_b82 . +_:b0_b82 _:b0_b496 . +_:b0_b83 . +_:b0_b83 . +_:b0_b83 _:b0_b84 . +_:b0_b84 . +_:b0_b84 . +_:b0_b85 . +_:b0_b85 "1"^^ . +_:b0_b85 "0"^^ . +_:b0_b85 . +_:b0_b85 _:b0_b86 . +_:b0_b86 . +_:b0_b86 . +_:b0_b87 . +_:b0_b87 . +_:b0_b87 . +_:b0_b88 . +_:b0_b88 . +_:b0_b88 . +_:b0_b89 . +_:b0_b89 . +_:b0_b89 . +_:b0_b9 . +_:b0_b9 _:b0_b498 . +_:b0_b90 . +_:b0_b90 . +_:b0_b90 . +_:b0_b91 . +_:b0_b91 . +_:b0_b91 _:b0_b92 . +_:b0_b92 . +_:b0_b92 . +_:b0_b93 . +_:b0_b93 . +_:b0_b93 _:b0_b94 . +_:b0_b94 . +_:b0_b94 . +_:b0_b95 . +_:b0_b95 _:b0_b500 . +_:b0_b96 . +_:b0_b96 . +_:b0_b97 . +_:b0_b97 . +_:b0_b98 . +_:b0_b98 . +_:b0_b99 . +_:b0_b99 _:b0_b503 . diff --git a/doc/ShExR.shex b/doc/ShExR.shex index 98e7b1f1..43e7cde8 100644 --- a/doc/ShExR.shex +++ b/doc/ShExR.shex @@ -152,7 +152,6 @@ start=@<#Schema> <#TripleConstraint> CLOSED { a [sx:TripleConstraint] ; sx:inverse [true false] ? ; - sx:negated [true false] ? ; sx:min xsd:integer ? ; sx:max xsd:integer ? ; sx:predicate IRI ; diff --git a/doc/ShExR.ttl b/doc/ShExR.ttl index e4be74fc..5e405479 100644 --- a/doc/ShExR.ttl +++ b/doc/ShExR.ttl @@ -1,466 +1,614 @@ -BASE PREFIX rdf: PREFIX sx: PREFIX xsd: -[] a sx:Schema ; - sx:start <#Schema> ; - sx:shapes ( - <#Schema> - <#shapeDeclOrExpr> - <#ShapeDecl> - <#shapeExpr> - <#ShapeOr> - <#ShapeAnd> - <#ShapeNot> - <#NodeConstraint> - <#Shape> - <#ShapeExternal> - <#SemAct> - <#Annotation> - <#facet_holder> - <#numericLiteral> - <#valueSetValue> - <#objectValue> - <#IriStem> - <#IriStemRange> - <#LiteralStem> - <#LiteralStemRange> - <#Language> - <#LanguageStem> - <#LanguageStemRange> - <#Wildcard> - <#tripleExpression> - <#NotYetResolvedInclusion> - <#OneOf> - <#EachOf> - <#TripleConstraint> - <#tripleExpressionList2Plus> - <#tripleExpressionList1Plus> - <#IriList1Plus> - <#SemActList1Plus> - <#ShapeDeclList1Plus> - <#shapeDeclOrExprList2Plus> - <#shapeDeclOrExprList1Plus> - <#valueSetValueList1Plus> - <#AnnotationList1Plus> - <#IriStemExclusionList1Plus> - <#LiteralStemExclusionList1Plus> - <#LanguageStemExclusionList1Plus> - ) . - -<#Schema> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:type ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( sx:Schema ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:imports ; sx:min 0 ; sx:max 1 ; - sx:valueExpr <#IriList1Plus> ] - [ a sx:TripleConstraint ; sx:predicate sx:startActs ; sx:min 0 ; sx:max 1 ; - sx:valueExpr <#SemActList1Plus> ] - [ a sx:TripleConstraint ; sx:predicate sx:start ; sx:min 0 ; sx:max 1 ; - sx:valueExpr <#shapeDeclOrExpr> ] - [ a sx:TripleConstraint ; sx:predicate sx:shapes ; sx:min 0 ; sx:max 1 ; - sx:valueExpr <#ShapeDeclList1Plus> ] ) ] ] . - -<#shapeDeclOrExpr> a sx:ShapeDecl ; sx:shapeExpr [ a sx:ShapeOr ; - sx:shapeExprs ( <#ShapeDecl> <#shapeExpr> ) ] . - -<#ShapeDecl> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:type ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( sx:ShapeDecl ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:abstract ; sx:min 0 ; sx:max 1 ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( true false ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:shapeExpr ; - sx:valueExpr <#shapeExpr> ] ) ] ] . - -<#shapeExpr> a sx:ShapeDecl ; sx:shapeExpr [ a sx:ShapeOr ; - sx:shapeExprs ( <#ShapeOr> <#ShapeAnd> <#ShapeNot> <#NodeConstraint> <#Shape> <#ShapeExternal> ) ] . - -<#ShapeOr> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:type ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( sx:ShapeOr ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:shapeExprs ; - sx:valueExpr <#shapeDeclOrExprList2Plus> ] ) ] ] . - -<#ShapeAnd> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:type ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( sx:ShapeAnd ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:shapeExprs ; - sx:valueExpr <#shapeDeclOrExprList2Plus> ] ) ] ] . - -<#ShapeNot> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:type ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( sx:ShapeNot ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:shapeExpr ; - sx:valueExpr <#shapeDeclOrExpr> ] ) ] ] . - -<#NodeConstraint> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:type ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( sx:NodeConstraint ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:nodeKind ; sx:min 0 ; sx:max 1 ; - sx:valueExpr - [ a sx:NodeConstraint ; sx:values ( sx:iri sx:bnode sx:literal sx:nonliteral ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:datatype ; sx:min 0 ; sx:max 1 ; - sx:valueExpr [ a sx:NodeConstraint ; sx:nodeKind sx:iri ] ] - <#xsFacets> - [ a sx:TripleConstraint ; sx:predicate sx:values ; sx:min 0 ; sx:max 1 ; - sx:valueExpr <#valueSetValueList1Plus> ] - [ a sx:TripleConstraint ; sx:predicate sx:semActs ; sx:min 0 ; sx:max 1 ; - sx:valueExpr <#SemActList1Plus> ] - [ a sx:TripleConstraint ; sx:predicate sx:annotation ; sx:min 0 ; sx:max 1 ; - sx:valueExpr <#AnnotationList1Plus> ] ) ] ] . - -<#Shape> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:type ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( sx:Shape ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:extends ; sx:min 0 ; sx:max 1 ; - sx:valueExpr <#shapeDeclOrExprList1Plus> ] - [ a sx:TripleConstraint ; sx:predicate sx:closed ; sx:min 0 ; sx:max 1 ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( true false ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:extra ; sx:min 0 ; sx:max -1 ; - sx:valueExpr [ a sx:NodeConstraint ; sx:nodeKind sx:iri ] ] - [ a sx:TripleConstraint ; sx:predicate sx:expression ; sx:min 0 ; sx:max 1 ; - sx:valueExpr <#tripleExpression> ] - [ a sx:TripleConstraint ; sx:predicate sx:semActs ; sx:min 0 ; sx:max 1 ; - sx:valueExpr <#SemActList1Plus> ] - [ a sx:TripleConstraint ; sx:predicate sx:annotation ; sx:min 0 ; sx:max 1 ; - sx:valueExpr <#AnnotationList1Plus> ] ) ] ] . - -<#ShapeExternal> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:TripleConstraint ; sx:predicate rdf:type ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( sx:ShapeExternal ) ] ] ] . - -<#SemAct> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:type ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( sx:SemAct ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:name ; - sx:valueExpr [ a sx:NodeConstraint ; sx:nodeKind sx:iri ] ] - [ a sx:TripleConstraint ; sx:predicate sx:code ; sx:min 0 ; sx:max 1 ; - sx:valueExpr [ a sx:NodeConstraint ; sx:datatype xsd:string ] ] ) ] ] . - -<#Annotation> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:type ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( sx:Annotation ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:predicate ; - sx:valueExpr [ a sx:NodeConstraint ; sx:nodeKind sx:iri ] ] - [ a sx:TripleConstraint ; sx:predicate sx:object ; sx:valueExpr <#objectValue> ] ) ] ] . - -<#facet_holder> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; # hold labeled productions - sx:expression [ a sx:EachOf ; sx:expressions ( - <#xsFacets> - <#stringFacet> - <#numericFacet> - ) ] ] . -<#xsFacets> a sx:OneOf ; sx:min 0 ; sx:max -1 ; - sx:expressions ( - <#stringFacet> - <#numericFacet> - ) . -<#stringFacet> a sx:OneOf ; - sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate sx:length ; - sx:valueExpr [ a sx:NodeConstraint ; sx:datatype xsd:integer ] ] - [ a sx:TripleConstraint ; sx:predicate sx:minlength ; - sx:valueExpr [ a sx:NodeConstraint ; sx:datatype xsd:integer ] ] - [ a sx:TripleConstraint ; sx:predicate sx:maxlength ; - sx:valueExpr [ a sx:NodeConstraint ; sx:datatype xsd:integer ] ] - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate sx:pattern ; - sx:valueExpr [ a sx:NodeConstraint ; sx:datatype xsd:string ] ] - [ a sx:TripleConstraint ; sx:predicate sx:flags ; sx:min 0 ; sx:max 1 ; - sx:valueExpr [ a sx:NodeConstraint ; sx:datatype xsd:string ] ] - ) ] - ) . -<#numericFacet> a sx:OneOf ; - sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate sx:mininclusive ; - sx:valueExpr <#numericLiteral> ] - [ a sx:TripleConstraint ; sx:predicate sx:minexclusive ; - sx:valueExpr <#numericLiteral> ] - [ a sx:TripleConstraint ; sx:predicate sx:maxinclusive ; - sx:valueExpr <#numericLiteral> ] - [ a sx:TripleConstraint ; sx:predicate sx:maxexclusive ; - sx:valueExpr <#numericLiteral> ] - [ a sx:TripleConstraint ; sx:predicate sx:totaldigits ; - sx:valueExpr [ a sx:NodeConstraint ; sx:datatype xsd:integer ] ] - [ a sx:TripleConstraint ; sx:predicate sx:fractiondigits ; - sx:valueExpr [ a sx:NodeConstraint ; sx:datatype xsd:integer ] ] ) . - -<#numericLiteral> a sx:ShapeDecl ; sx:shapeExpr [ a sx:ShapeOr ; - sx:shapeExprs ( - [ a sx:NodeConstraint ; sx:datatype xsd:integer ] - [ a sx:NodeConstraint ; sx:datatype xsd:decimal ] - [ a sx:NodeConstraint ; sx:datatype xsd:double ] ) ] . - -<#valueSetValue> a sx:ShapeDecl ; sx:shapeExpr [ a sx:ShapeOr ; - sx:shapeExprs ( <#objectValue> <#IriStem> <#IriStemRange> - <#LiteralStem> <#LiteralStemRange> - <#Language> <#LanguageStem> <#LanguageStemRange> ) ] . -<#objectValue> a sx:ShapeDecl ; sx:shapeExpr [ a sx:ShapeOr ; - sx:shapeExprs ( - [ a sx:NodeConstraint ; sx:nodeKind sx:iri ] - [ a sx:NodeConstraint ; sx:nodeKind sx:literal ] ) ] . # rdf:langString breaks on Annotation.object - -<#IriStem> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:type ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( sx:IriStem ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:stem ; - sx:valueExpr [ a sx:NodeConstraint ; sx:datatype xsd:string ] ] ) ] ] . -<#IriStemRange> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:type ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( sx:IriStemRange ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:stem ; - sx:valueExpr [ a sx:ShapeOr ; sx:shapeExprs ( - [ a sx:NodeConstraint ; sx:datatype xsd:string ] - <#Wildcard> ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:exclusion ; - sx:valueExpr <#IriStemExclusionList1Plus> ] ) ] ] . - -<#LiteralStem> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:type ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( sx:LiteralStem ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:stem ; - sx:valueExpr [ a sx:NodeConstraint ; sx:datatype xsd:string ] ] ) ] ] . -<#LiteralStemRange> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:type ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( sx:LiteralStemRange ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:stem ; - sx:valueExpr [ a sx:ShapeOr ; sx:shapeExprs ( - [ a sx:NodeConstraint ; sx:datatype xsd:string ] - <#Wildcard> ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:exclusion ; - sx:valueExpr <#LiteralStemExclusionList1Plus> ] ) ] ] . - -<#Language> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:type ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( sx:Language ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:languageTag ; - sx:valueExpr [ a sx:NodeConstraint ; sx:datatype xsd:string ] ] ) ] ] . -<#LanguageStem> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:type ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( sx:LanguageStem ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:stem ; - sx:valueExpr [ a sx:NodeConstraint ; sx:datatype xsd:string ] ] ) ] ] . -<#LanguageStemRange> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:type ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( sx:LanguageStemRange ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:stem ; - sx:valueExpr [ a sx:ShapeOr ; sx:shapeExprs ( - [ a sx:NodeConstraint ; sx:datatype xsd:string ] - <#Wildcard> ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:exclusion ; - sx:valueExpr <#LanguageStemExclusionList1Plus> ] ) ] ] . - -<#Wildcard> a sx:ShapeDecl ; sx:shapeExpr [ a sx:ShapeAnd ; - sx:shapeExprs ( - [ a sx:NodeConstraint ; sx:nodeKind sx:bnode ] - [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:TripleConstraint ; sx:predicate rdf:type ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( sx:Wildcard ) ] ] ] ) ] . - -<#tripleExpression> a sx:ShapeDecl ; sx:shapeExpr [ a sx:ShapeOr ; - sx:shapeExprs ( - <#NotYetResolvedInclusion> - <#TripleConstraint> - <#OneOf> - <#EachOf> - ) ] . - -<#NotYetResolvedInclusion> a sx:ShapeDecl ; - sx:shapeExpr [ a sx:Shape ; sx:closed true ] . # will have 1 incoming, 0 outgoing arcs - -<#OneOf> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:type ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( sx:OneOf ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:min ; sx:min 0 ; sx:max 1 ; - sx:valueExpr [ a sx:NodeConstraint ; sx:datatype xsd:integer ] ] - [ a sx:TripleConstraint ; sx:predicate sx:max ; sx:min 0 ; sx:max 1 ; - sx:valueExpr [ a sx:NodeConstraint ; sx:datatype xsd:integer ] ] - [ a sx:TripleConstraint ; sx:predicate sx:expressions ; - sx:valueExpr <#tripleExpressionList2Plus> ] - [ a sx:TripleConstraint ; sx:predicate sx:semActs ; sx:min 0 ; sx:max 1 ; - sx:valueExpr <#SemActList1Plus> ] - [ a sx:TripleConstraint ; sx:predicate sx:annotation ; sx:min 0 ; sx:max 1 ; - sx:valueExpr <#AnnotationList1Plus> ] ) ] ] . - -<#EachOf> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:type ; - sx:valueExpr - [ a sx:NodeConstraint ; sx:values ( sx:EachOf ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:min ; sx:min 0 ; sx:max 1 ; - sx:valueExpr - [ a sx:NodeConstraint ; sx:datatype xsd:integer ] ] - [ a sx:TripleConstraint ; sx:predicate sx:max ; sx:min 0 ; sx:max 1 ; - sx:valueExpr [ a sx:NodeConstraint ; sx:datatype xsd:integer ] ] - [ a sx:TripleConstraint ; sx:predicate sx:expressions ; - sx:valueExpr <#tripleExpressionList2Plus> ] - [ a sx:TripleConstraint ; sx:predicate sx:semActs ; sx:min 0 ; sx:max 1 ; - sx:valueExpr <#SemActList1Plus> ] - [ a sx:TripleConstraint ; sx:predicate sx:annotation ; sx:min 0 ; sx:max 1 ; - sx:valueExpr <#AnnotationList1Plus> ] ) ] ] . - -<#TripleConstraint> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:type ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( sx:TripleConstraint ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:inverse ; sx:min 0 ; sx:max 1 ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( true false ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:negated ; sx:min 0 ; sx:max 1 ; - sx:valueExpr [ a sx:NodeConstraint ; sx:values ( true false ) ] ] - [ a sx:TripleConstraint ; sx:predicate sx:min ; sx:min 0 ; sx:max 1 ; - sx:valueExpr [ a sx:NodeConstraint ; sx:datatype xsd:integer ] ] - [ a sx:TripleConstraint ; sx:predicate sx:max ; sx:min 0 ; sx:max 1 ; - sx:valueExpr [ a sx:NodeConstraint ; sx:datatype xsd:integer ] ] - [ a sx:TripleConstraint ; sx:predicate sx:predicate ; - sx:valueExpr [ a sx:NodeConstraint ; sx:nodeKind sx:iri ] ] - [ a sx:TripleConstraint ; sx:predicate sx:valueExpr ; sx:min 0 ; sx:max 1 ; - sx:valueExpr <#shapeDeclOrExpr> ] - [ a sx:TripleConstraint ; sx:predicate sx:semActs ; sx:min 0 ; sx:max 1 ; - sx:valueExpr <#SemActList1Plus> ] - [ a sx:TripleConstraint ; sx:predicate sx:annotation ; sx:min 0 ; sx:max 1 ; - sx:valueExpr <#AnnotationList1Plus> ] ) ] ] . - -# RDF Lists - -<#tripleExpressionList2Plus> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:first ; - sx:valueExpr <#tripleExpression> ] - [ a sx:TripleConstraint ; sx:predicate rdf:rest ; - sx:valueExpr <#tripleExpressionList1Plus> ] ) ] ] . - -<#tripleExpressionList1Plus> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:first ; - sx:valueExpr <#tripleExpression> ] - [ a sx:TripleConstraint ; sx:predicate rdf:rest ; - sx:valueExpr - [ a sx:ShapeOr ; sx:shapeExprs ( - [ a sx:NodeConstraint ; sx:values ( rdf:nil ) ] - <#tripleExpressionList1Plus> ) ] ] ) ] ] . - -<#IriList1Plus> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:first ; sx:valueExpr [ a sx:NodeConstraint ; sx:nodeKind sx:iri ] ] - [ a sx:TripleConstraint ; sx:predicate rdf:rest ; - sx:valueExpr [ a sx:ShapeOr ; sx:shapeExprs ( - [ a sx:NodeConstraint ; sx:values ( rdf:nil ) ] - <#IriList1Plus> ) ] ] ) ] ] . - -<#SemActList1Plus> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:first ; sx:valueExpr <#SemAct> ] - [ a sx:TripleConstraint ; sx:predicate rdf:rest ; - sx:valueExpr [ a sx:ShapeOr ; sx:shapeExprs ( - [ a sx:NodeConstraint ; sx:values ( rdf:nil ) ] - <#SemActList1Plus> ) ] ] ) ] ] . - -<#ShapeDeclList1Plus> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:first ; sx:valueExpr <#ShapeDecl> ] - [ a sx:TripleConstraint ; sx:predicate rdf:rest ; - sx:valueExpr [ a sx:ShapeOr ; sx:shapeExprs ( - [ a sx:NodeConstraint ; sx:values ( rdf:nil ) ] - <#ShapeDeclList1Plus> ) ] ] ) ] ] . - -<#shapeDeclOrExprList2Plus> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:first ; sx:valueExpr <#shapeDeclOrExpr> ] - [ a sx:TripleConstraint ; sx:predicate rdf:rest ; sx:valueExpr <#shapeDeclOrExprList1Plus> ] ) ] ] . - -<#shapeDeclOrExprList1Plus> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:first ; sx:valueExpr <#shapeDeclOrExpr> ] - [ a sx:TripleConstraint ; sx:predicate rdf:rest ; - sx:valueExpr [ a sx:ShapeOr ; sx:shapeExprs ( - [ a sx:NodeConstraint ; sx:values ( rdf:nil ) ] <#shapeDeclOrExprList1Plus> ) ] ] ) ] ] . - -<#valueSetValueList1Plus> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:first ; sx:valueExpr <#valueSetValue> ] - [ a sx:TripleConstraint ; sx:predicate rdf:rest ; - sx:valueExpr [ a sx:ShapeOr ; sx:shapeExprs ( - [ a sx:NodeConstraint ; sx:values ( rdf:nil ) ] - <#valueSetValueList1Plus> ) ] ] ) ] ] . - -<#AnnotationList1Plus> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:first ; sx:valueExpr <#Annotation> ] - [ a sx:TripleConstraint ; sx:predicate rdf:rest ; - sx:valueExpr [ a sx:ShapeOr ; sx:shapeExprs ( - [ a sx:NodeConstraint ; sx:values ( rdf:nil ) ] - <#AnnotationList1Plus> ) ] ] ) ] ] . - -<#IriStemExclusionList1Plus> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:first ; sx:valueExpr [ a sx:ShapeOr ; sx:shapeExprs ( [ a sx:NodeConstraint ; sx:nodeKind sx:iri ] <#IriStem> ) ] ] - [ a sx:TripleConstraint ; sx:predicate rdf:rest ; - sx:valueExpr [ a sx:ShapeOr ; sx:shapeExprs ( - [ a sx:NodeConstraint ; sx:values ( rdf:nil ) ] - <#IriStemExclusionList1Plus> ) ] ] ) ] ] . - -<#LiteralStemExclusionList1Plus> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:first ; sx:valueExpr [ a sx:ShapeOr ; sx:shapeExprs ( [ a sx:NodeConstraint ; sx:datatype xsd:string ] <#LiteralStem> ) ] ] - [ a sx:TripleConstraint ; sx:predicate rdf:rest ; - sx:valueExpr [ a sx:ShapeOr ; sx:shapeExprs ( - [ a sx:NodeConstraint ; sx:values ( rdf:nil ) ] - <#LiteralStemExclusionList1Plus> ) ] ] ) ] ] . - -<#LanguageStemExclusionList1Plus> a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ; sx:closed true ; - sx:expression - [ a sx:EachOf ; sx:expressions ( - [ a sx:TripleConstraint ; sx:predicate rdf:first ; sx:valueExpr [ a sx:ShapeOr ; sx:shapeExprs ( [ a sx:NodeConstraint ; sx:datatype xsd:string ] <#LanguageStem> ) ] ] - [ a sx:TripleConstraint ; sx:predicate rdf:rest ; - sx:valueExpr [ a sx:ShapeOr ; sx:shapeExprs ( - [ a sx:NodeConstraint ; sx:values ( rdf:nil ) ] - <#LanguageStemExclusionList1Plus> ) ] ] ) ] ] . - +[] a sx:Schema; + sx:shapes ( sx:Schema sx:shapeDeclOrExpr sx:ShapeDecl sx:shapeExpr sx:ShapeOr sx:ShapeAnd sx:ShapeNot sx:NodeConstraint sx:Shape sx:ShapeExternal sx:SemAct sx:Annotation sx:facet_holder sx:numericLiteral sx:valueSetValue sx:objectValue sx:IriStem sx:IriStemRange sx:LiteralStem sx:LiteralStemRange sx:Language sx:LanguageStem sx:LanguageStemRange sx:Wildcard sx:tripleExpression sx:NotYetResolvedInclusion sx:OneOf sx:EachOf sx:TripleConstraint sx:tripleExpressionList2Plus sx:tripleExpressionList1Plus sx:IriList1Plus sx:SemActList1Plus sx:ShapeDeclList1Plus sx:shapeDeclOrExprList2Plus sx:shapeDeclOrExprList1Plus sx:valueSetValueList1Plus sx:AnnotationList1Plus sx:IriStemExclusionList1Plus sx:LiteralStemExclusionList1Plus sx:LanguageStemExclusionList1Plus ); + sx:start sx:Schema . + +sx:Annotation a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:type; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:Annotation ) ] ] [ a sx:TripleConstraint; + sx:predicate sx:predicate; + sx:valueExpr [ a sx:NodeConstraint; + sx:nodeKind sx:iri ] ] [ a sx:TripleConstraint; + sx:predicate sx:object; + sx:valueExpr sx:objectValue ] ) ] ] . + +sx:AnnotationList1Plus a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:first; + sx:valueExpr sx:Annotation ] [ a sx:TripleConstraint; + sx:predicate rdf:rest; + sx:valueExpr [ a sx:ShapeOr; + sx:shapeExprs ( [ a sx:NodeConstraint; + sx:values ( () ) ] sx:AnnotationList1Plus ) ] ] ) ] ] . + +sx:EachOf a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:type; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:EachOf ) ] ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:min; + sx:valueExpr [ a sx:NodeConstraint; + sx:datatype xsd:integer ] ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:max; + sx:valueExpr [ a sx:NodeConstraint; + sx:datatype xsd:integer ] ] [ a sx:TripleConstraint; + sx:predicate sx:expressions; + sx:valueExpr sx:tripleExpressionList2Plus ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:semActs; + sx:valueExpr sx:SemActList1Plus ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:annotation; + sx:valueExpr sx:AnnotationList1Plus ] ) ] ] . + +sx:IriList1Plus a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:first; + sx:valueExpr [ a sx:NodeConstraint; + sx:nodeKind sx:iri ] ] [ a sx:TripleConstraint; + sx:predicate rdf:rest; + sx:valueExpr [ a sx:ShapeOr; + sx:shapeExprs ( [ a sx:NodeConstraint; + sx:values ( () ) ] sx:IriList1Plus ) ] ] ) ] ] . + +sx:IriStem a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:type; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:IriStem ) ] ] [ a sx:TripleConstraint; + sx:predicate sx:stem; + sx:valueExpr [ a sx:NodeConstraint; + sx:datatype xsd:string ] ] ) ] ] . + +sx:IriStemExclusionList1Plus a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:first; + sx:valueExpr [ a sx:ShapeOr; + sx:shapeExprs ( [ a sx:NodeConstraint; + sx:nodeKind sx:iri ] sx:IriStem ) ] ] [ a sx:TripleConstraint; + sx:predicate rdf:rest; + sx:valueExpr [ a sx:ShapeOr; + sx:shapeExprs ( [ a sx:NodeConstraint; + sx:values ( () ) ] sx:IriStemExclusionList1Plus ) ] ] ) ] ] . + +sx:IriStemRange a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:type; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:IriStemRange ) ] ] [ a sx:TripleConstraint; + sx:predicate sx:stem; + sx:valueExpr [ a sx:ShapeOr; + sx:shapeExprs ( [ a sx:NodeConstraint; + sx:datatype xsd:string ] sx:Wildcard ) ] ] [ a sx:TripleConstraint; + sx:predicate sx:exclusion; + sx:valueExpr sx:IriStemExclusionList1Plus ] ) ] ] . + +sx:Language a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:type; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:Language ) ] ] [ a sx:TripleConstraint; + sx:predicate sx:languageTag; + sx:valueExpr [ a sx:NodeConstraint; + sx:datatype xsd:string ] ] ) ] ] . + +sx:LanguageStem a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:type; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:LanguageStem ) ] ] [ a sx:TripleConstraint; + sx:predicate sx:stem; + sx:valueExpr [ a sx:NodeConstraint; + sx:datatype xsd:string ] ] ) ] ] . + +sx:LanguageStemExclusionList1Plus a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:first; + sx:valueExpr [ a sx:ShapeOr; + sx:shapeExprs ( [ a sx:NodeConstraint; + sx:datatype xsd:string ] sx:LanguageStem ) ] ] [ a sx:TripleConstraint; + sx:predicate rdf:rest; + sx:valueExpr [ a sx:ShapeOr; + sx:shapeExprs ( [ a sx:NodeConstraint; + sx:values ( () ) ] sx:LanguageStemExclusionList1Plus ) ] ] ) ] ] . + +sx:LanguageStemRange a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:type; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:LanguageStemRange ) ] ] [ a sx:TripleConstraint; + sx:predicate sx:stem; + sx:valueExpr [ a sx:ShapeOr; + sx:shapeExprs ( [ a sx:NodeConstraint; + sx:datatype xsd:string ] sx:Wildcard ) ] ] [ a sx:TripleConstraint; + sx:predicate sx:exclusion; + sx:valueExpr sx:LanguageStemExclusionList1Plus ] ) ] ] . + +sx:LiteralStem a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:type; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:LiteralStem ) ] ] [ a sx:TripleConstraint; + sx:predicate sx:stem; + sx:valueExpr [ a sx:NodeConstraint; + sx:datatype xsd:string ] ] ) ] ] . + +sx:LiteralStemExclusionList1Plus a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:first; + sx:valueExpr [ a sx:ShapeOr; + sx:shapeExprs ( [ a sx:NodeConstraint; + sx:datatype xsd:string ] sx:LiteralStem ) ] ] [ a sx:TripleConstraint; + sx:predicate rdf:rest; + sx:valueExpr [ a sx:ShapeOr; + sx:shapeExprs ( [ a sx:NodeConstraint; + sx:values ( () ) ] sx:LiteralStemExclusionList1Plus ) ] ] ) ] ] . + +sx:LiteralStemRange a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:type; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:LiteralStemRange ) ] ] [ a sx:TripleConstraint; + sx:predicate sx:stem; + sx:valueExpr [ a sx:ShapeOr; + sx:shapeExprs ( [ a sx:NodeConstraint; + sx:datatype xsd:string ] sx:Wildcard ) ] ] [ a sx:TripleConstraint; + sx:predicate sx:exclusion; + sx:valueExpr sx:LiteralStemExclusionList1Plus ] ) ] ] . + +sx:NodeConstraint a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:type; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:NodeConstraint ) ] ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:nodeKind; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:iri sx:bnode sx:literal sx:nonliteral ) ] ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:datatype; + sx:valueExpr [ a sx:NodeConstraint; + sx:nodeKind sx:iri ] ] sx:xsFacets [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:values; + sx:valueExpr sx:valueSetValueList1Plus ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:semActs; + sx:valueExpr sx:SemActList1Plus ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:annotation; + sx:valueExpr sx:AnnotationList1Plus ] ) ] ] . + +sx:NotYetResolvedInclusion a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true ] . + +sx:OneOf a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:type; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:OneOf ) ] ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:min; + sx:valueExpr [ a sx:NodeConstraint; + sx:datatype xsd:integer ] ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:max; + sx:valueExpr [ a sx:NodeConstraint; + sx:datatype xsd:integer ] ] [ a sx:TripleConstraint; + sx:predicate sx:expressions; + sx:valueExpr sx:tripleExpressionList2Plus ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:semActs; + sx:valueExpr sx:SemActList1Plus ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:annotation; + sx:valueExpr sx:AnnotationList1Plus ] ) ] ] . + +sx:Schema a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:type; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:Schema ) ] ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:imports; + sx:valueExpr sx:IriList1Plus ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:startActs; + sx:valueExpr sx:SemActList1Plus ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:start; + sx:valueExpr sx:shapeDeclOrExpr ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:shapes; + sx:valueExpr sx:ShapeDeclList1Plus ] ) ] ] . + +sx:SemAct a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:type; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:SemAct ) ] ] [ a sx:TripleConstraint; + sx:predicate sx:name; + sx:valueExpr [ a sx:NodeConstraint; + sx:nodeKind sx:iri ] ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:code; + sx:valueExpr [ a sx:NodeConstraint; + sx:datatype xsd:string ] ] ) ] ] . + +sx:SemActList1Plus a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:first; + sx:valueExpr sx:SemAct ] [ a sx:TripleConstraint; + sx:predicate rdf:rest; + sx:valueExpr [ a sx:ShapeOr; + sx:shapeExprs ( [ a sx:NodeConstraint; + sx:values ( () ) ] sx:SemActList1Plus ) ] ] ) ] ] . + +sx:Shape a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:type; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:Shape ) ] ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:extends; + sx:valueExpr sx:shapeDeclOrExprList1Plus ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:closed; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( true false ) ] ] [ a sx:TripleConstraint; + sx:max -1; + sx:min 0; + sx:predicate sx:extra; + sx:valueExpr [ a sx:NodeConstraint; + sx:nodeKind sx:iri ] ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:expression; + sx:valueExpr sx:tripleExpression ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:semActs; + sx:valueExpr sx:SemActList1Plus ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:annotation; + sx:valueExpr sx:AnnotationList1Plus ] ) ] ] . + +sx:ShapeAnd a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:type; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:ShapeAnd ) ] ] [ a sx:TripleConstraint; + sx:predicate sx:shapeExprs; + sx:valueExpr sx:shapeDeclOrExprList2Plus ] ) ] ] . + +sx:ShapeDecl a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:type; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:ShapeDecl ) ] ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:abstract; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( true false ) ] ] [ a sx:TripleConstraint; + sx:predicate sx:shapeExpr; + sx:valueExpr sx:shapeExpr ] ) ] ] . + +sx:ShapeDeclList1Plus a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:first; + sx:valueExpr sx:ShapeDecl ] [ a sx:TripleConstraint; + sx:predicate rdf:rest; + sx:valueExpr [ a sx:ShapeOr; + sx:shapeExprs ( [ a sx:NodeConstraint; + sx:values ( () ) ] sx:ShapeDeclList1Plus ) ] ] ) ] ] . + +sx:ShapeExternal a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:TripleConstraint; + sx:predicate rdf:type; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:ShapeExternal ) ] ] ] . + +sx:ShapeNot a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:type; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:ShapeNot ) ] ] [ a sx:TripleConstraint; + sx:predicate sx:shapeExpr; + sx:valueExpr sx:shapeDeclOrExpr ] ) ] ] . + +sx:ShapeOr a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:type; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:ShapeOr ) ] ] [ a sx:TripleConstraint; + sx:predicate sx:shapeExprs; + sx:valueExpr sx:shapeDeclOrExprList2Plus ] ) ] ] . + +sx:TripleConstraint a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:type; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:TripleConstraint ) ] ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:inverse; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( true false ) ] ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:min; + sx:valueExpr [ a sx:NodeConstraint; + sx:datatype xsd:integer ] ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:max; + sx:valueExpr [ a sx:NodeConstraint; + sx:datatype xsd:integer ] ] [ a sx:TripleConstraint; + sx:predicate sx:predicate; + sx:valueExpr [ a sx:NodeConstraint; + sx:nodeKind sx:iri ] ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:valueExpr; + sx:valueExpr sx:shapeDeclOrExpr ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:semActs; + sx:valueExpr sx:SemActList1Plus ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:annotation; + sx:valueExpr sx:AnnotationList1Plus ] ) ] ] . + +sx:Wildcard a sx:ShapeDecl; + sx:shapeExpr [ a sx:ShapeAnd; + sx:shapeExprs ( [ a sx:NodeConstraint; + sx:nodeKind sx:bnode ] [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:TripleConstraint; + sx:predicate rdf:type; + sx:valueExpr [ a sx:NodeConstraint; + sx:values ( sx:Wildcard ) ] ] ] ) ] . + +sx:facet_holder a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:expression [ a sx:EachOf; + sx:expressions ( sx:xsFacets sx:stringFacet sx:numericFacet ) ] ] . + +sx:numericFacet a sx:OneOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate sx:mininclusive; + sx:valueExpr sx:numericLiteral ] [ a sx:TripleConstraint; + sx:predicate sx:minexclusive; + sx:valueExpr sx:numericLiteral ] [ a sx:TripleConstraint; + sx:predicate sx:maxinclusive; + sx:valueExpr sx:numericLiteral ] [ a sx:TripleConstraint; + sx:predicate sx:maxexclusive; + sx:valueExpr sx:numericLiteral ] [ a sx:TripleConstraint; + sx:predicate sx:totaldigits; + sx:valueExpr [ a sx:NodeConstraint; + sx:datatype xsd:integer ] ] [ a sx:TripleConstraint; + sx:predicate sx:fractiondigits; + sx:valueExpr [ a sx:NodeConstraint; + sx:datatype xsd:integer ] ] ) . + +sx:numericLiteral a sx:ShapeDecl; + sx:shapeExpr [ a sx:ShapeOr; + sx:shapeExprs ( [ a sx:NodeConstraint; + sx:datatype xsd:integer ] [ a sx:NodeConstraint; + sx:datatype xsd:decimal ] [ a sx:NodeConstraint; + sx:datatype xsd:double ] ) ] . + +sx:objectValue a sx:ShapeDecl; + sx:shapeExpr [ a sx:ShapeOr; + sx:shapeExprs ( [ a sx:NodeConstraint; + sx:nodeKind sx:iri ] [ a sx:NodeConstraint; + sx:nodeKind sx:literal ] ) ] . + +sx:shapeDeclOrExpr a sx:ShapeDecl; + sx:shapeExpr [ a sx:ShapeOr; + sx:shapeExprs ( sx:ShapeDecl sx:shapeExpr ) ] . + +sx:shapeDeclOrExprList1Plus a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:first; + sx:valueExpr sx:shapeDeclOrExpr ] [ a sx:TripleConstraint; + sx:predicate rdf:rest; + sx:valueExpr [ a sx:ShapeOr; + sx:shapeExprs ( [ a sx:NodeConstraint; + sx:values ( () ) ] sx:shapeDeclOrExprList1Plus ) ] ] ) ] ] . + +sx:shapeDeclOrExprList2Plus a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:first; + sx:valueExpr sx:shapeDeclOrExpr ] [ a sx:TripleConstraint; + sx:predicate rdf:rest; + sx:valueExpr sx:shapeDeclOrExprList1Plus ] ) ] ] . + +sx:shapeExpr a sx:ShapeDecl; + sx:shapeExpr [ a sx:ShapeOr; + sx:shapeExprs ( sx:ShapeOr sx:ShapeAnd sx:ShapeNot sx:NodeConstraint sx:Shape sx:ShapeExternal ) ] . + +sx:stringFacet a sx:OneOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate sx:length; + sx:valueExpr [ a sx:NodeConstraint; + sx:datatype xsd:integer ] ] [ a sx:TripleConstraint; + sx:predicate sx:minlength; + sx:valueExpr [ a sx:NodeConstraint; + sx:datatype xsd:integer ] ] [ a sx:TripleConstraint; + sx:predicate sx:maxlength; + sx:valueExpr [ a sx:NodeConstraint; + sx:datatype xsd:integer ] ] [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate sx:pattern; + sx:valueExpr [ a sx:NodeConstraint; + sx:datatype xsd:string ] ] [ a sx:TripleConstraint; + sx:max 1; + sx:min 0; + sx:predicate sx:flags; + sx:valueExpr [ a sx:NodeConstraint; + sx:datatype xsd:string ] ] ) ] ) . + +sx:tripleExpression a sx:ShapeDecl; + sx:shapeExpr [ a sx:ShapeOr; + sx:shapeExprs ( sx:NotYetResolvedInclusion sx:TripleConstraint sx:OneOf sx:EachOf ) ] . + +sx:tripleExpressionList1Plus a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:first; + sx:valueExpr sx:tripleExpression ] [ a sx:TripleConstraint; + sx:predicate rdf:rest; + sx:valueExpr [ a sx:ShapeOr; + sx:shapeExprs ( [ a sx:NodeConstraint; + sx:values ( () ) ] sx:tripleExpressionList1Plus ) ] ] ) ] ] . + +sx:tripleExpressionList2Plus a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:first; + sx:valueExpr sx:tripleExpression ] [ a sx:TripleConstraint; + sx:predicate rdf:rest; + sx:valueExpr sx:tripleExpressionList1Plus ] ) ] ] . + +sx:valueSetValue a sx:ShapeDecl; + sx:shapeExpr [ a sx:ShapeOr; + sx:shapeExprs ( sx:objectValue sx:IriStem sx:IriStemRange sx:LiteralStem sx:LiteralStemRange sx:Language sx:LanguageStem sx:LanguageStemRange ) ] . + +sx:valueSetValueList1Plus a sx:ShapeDecl; + sx:shapeExpr [ a sx:Shape; + sx:closed true; + sx:expression [ a sx:EachOf; + sx:expressions ( [ a sx:TripleConstraint; + sx:predicate rdf:first; + sx:valueExpr sx:valueSetValue ] [ a sx:TripleConstraint; + sx:predicate rdf:rest; + sx:valueExpr [ a sx:ShapeOr; + sx:shapeExprs ( [ a sx:NodeConstraint; + sx:values ( () ) ] sx:valueSetValueList1Plus ) ] ] ) ] ] . + +sx:xsFacets a sx:OneOf; + sx:expressions ( sx:stringFacet sx:numericFacet ); + sx:max -1; + sx:min 0 . diff --git a/doc/ShExV.jsg b/doc/ShExV.jsg index eb1b5ea5..27b7750d 100644 --- a/doc/ShExV.jsg +++ b/doc/ShExV.jsg @@ -46,7 +46,7 @@ ShapeExternal { } tripleExpr = EachOf | OneOf | TripleConstraint | tripleExprLabel ; EachOf { id:tripleExprLabel? expressions:[tripleExpr{2,}] min:INTEGER? max:INTEGER? semActs:[SemAct+]? annotations:[Annotation+]? } OneOf { id:tripleExprLabel? expressions:[tripleExpr{2,}] min:INTEGER? max:INTEGER? semActs:[SemAct+]? annotations:[Annotation+]? } -TripleConstraint { id:tripleExprLabel? inverse:BOOL? negated:BOOL? predicate:IRI valueExpr:shapeExpr? min:INTEGER? max:INTEGER? semActs:[SemAct+]? annotations:[Annotation+]? } +TripleConstraint { id:tripleExprLabel? inverse:BOOL? predicate:IRI valueExpr:shapeExpr? min:INTEGER? max:INTEGER? semActs:[SemAct+]? annotations:[Annotation+]? } # XML Schema facets xsFacet = stringFacet | numericFacet ; diff --git a/doc/syntax-deltas.html b/doc/syntax-deltas.html new file mode 100644 index 00000000..d7442186 --- /dev/null +++ b/doc/syntax-deltas.html @@ -0,0 +1,245 @@ + + + + + +ShExC / ShExJ / ShExR deltas + + + + +

Where ShExC, ShExJ and ShExR disagree

+

Deltas between the three renderings of a ShEx schema, with the +evidence for each. Written up because the abstract syntax they are all supposed +to share is not quite the same in each.

+ +

ShEx schemas exist in three syntaxes, and each has its own grammar:

+ + + + + + + + + + + + + + + + + + + + +
SyntaxGrammarKind
ShExCShEx Semantics § LanguageEBNF over a compact text syntax
ShExJdoc/ShExJ.jsgJSON Schema Grammar over a JSON tree
ShExRdoc/ShExR.shexa ShEx schema over an RDF graph
+ +

ShExJ is the pivot: ShExC parses to it, and ShExJ plus +doc/ShExJ-context.jsonld +is ShExR — which is how +bin/mkShExR.js +derives ShExR.ttl and ShExR.ntriples. So a delta between ShExC and +ShExR is a place where that round trip is not total.

+ +

1. ShExR lets start be a ShapeDecl; nothing else does

+ +

The three grammars say:

+ + + +

Since ShEx 2.1 moved id onto ShapeDecl, a ShExJ +shapeExpr cannot itself be a ShapeDecl. ShExR's +shapeDeclOrExpr says it can. Running the same four start +forms through all three grammars:

+ + + + + + + + + + + +
start is…ShExCShExJ.jsgShExR.shex
a reference — start = @<S>✓acceptedaccepted
an inline shapeExpr — start = { }✓acceptedaccepted
an anonymous ShapeDeclno productionrejectedaccepted
an anonymous abstract ShapeDeclno productionrejectedaccepted
+ +

Why ShExR has to be this way

+ +

RDF cannot distinguish reference from containment. In ShExJ a reference is a +bare string:

+ +
{ "type": "Schema", "start": "http://ex/S",
+  "shapes": [ { "type": "ShapeDecl", "id": "http://ex/S", "shapeExpr": {…} } ] }
+ +

structurally unlike an inline object. In RDF there is no such distinction — +the arc is the thing:

+ +
<http://ex/sch> a sx:Schema ; sx:start <http://ex/S> ; sx:shapes ( <http://ex/S> ) .
+<http://ex/S>   a sx:ShapeDecl ; sx:shapeExpr [ a sx:Shape ] .
+ +

So ShExR must let sx:start reach a ShapeDecl, or it could +not encode start = @<S> at all. The cost is that it also admits an +anonymous inline ShapeDecl, which no ShExC document can write and ShExJ's own +grammar rejects.

+ +

The obvious tightening does not work either. You might add AND IRI +to the ShapeDecl branch, forcing references to be IRIs — but +shapeDeclLabel = IRIREF | BNODE, +so blank-node-labelled ShapeDecls are legal, and a reference to one is a +blank-node arc, indistinguishable from inlining it. The ambiguity is +irreducible unless ShExJ drops BNODE from shapeDeclLabel.

+ +

Not confined to start

+ +

The same shapeDeclOrExpr sits under every slot where ShExJ writes +shapeExprOrRef:

+ + + + + + + + + + + + + +
ShExRShExJ
sx:startSchema.start
sx:shapeExprs (ShapeOr, ShapeAnd)shapeExprs
sx:shapeExpr (ShapeNot)ShapeNot.shapeExpr
sx:extendsShape.extends
sx:valueExprTripleConstraint.valueExpr
+ +

start is just where it is easiest to see.

+ +

2. An abstract start slips past the abstract-shape requirement

+ +

ShExR accepts sx:start [ a sx:ShapeDecl ; sx:abstract true ; … ]. The +specification's abstract-shape requirement is worded over shapeExprRefs:

+ +
Every shapeExprRef referer MUST identify at least one +non-abstract shape.
+ +

An inline abstract ShapeDecl at start is not a ref, so the +requirement's wording does not reach it — leaving a start shape that nothing +can satisfy. This is the one delta with semantic teeth rather than just +surplus expressivity.

+ +

3. inlineShapeExpression restricts start only in ShExC

+ +

ShExC's start takes an inline shape expression. Comparing the +inline and general forms, the only difference is the tail:

+ +
+
shapeDefinition       ::= (includeSet | extraPropertySet | "CLOSED")* '{' tripleExpression? '}' annotation* semanticActions
+inlineShapeDefinition ::= (includeSet | extraPropertySet | "CLOSED")* '{' tripleExpression? '}'
+
+ +

So an inline shape definition may not carry +annotations or +semantic actions, +and per the grammar this is ill-formed:

+ +
start = { <p> . } %<a>%          # annotation/semAct on an inlineShapeDefinition
+ +

while parenthesising reaches the general production through +inlineShapeAtom's +'(' shapeExpression ')' branch:

+ +
start = ( { <p> . } %<a>% )      # well-formed
+ +

Neither ShExJ nor ShExR has any such restriction — sx:start reaches +<#Shape>, which permits sx:semActs and +sx:annotation unconditionally. The restriction is purely syntactic +and has no counterpart in the abstract syntax, so it is an obligation on +writers: a ShExJ→ShExC serialiser must parenthesise a start +carrying annotations or semantic actions, or it emits invalid ShExC.

+ +

Implementation note

+ +

shex.js accepts the bare form +above and attaches semActs to the start Shape, so its parser is more +permissive than the published grammar here. That is an implementation/grammar +divergence rather than a syntax/syntax one, but it means the bare form +round-trips in practice and so is likely to appear in the wild.

+ +

Reproducing

+ +

ShExC and ShExJ, from a shex.js checkout:

+ +
node -e "const p=require('./packages/shex-parser');
+  console.log(JSON.stringify(p.construct('http://ex/',{}).parse('<S> {} start = @<S>').start))"
+# "http://ex/S"  -- a shapeDeclRef, not an object
+
+npx json-grammar doc/ShExJ.jsg start-shapedecl.json
+# rejects { "type":"Schema", "start":{ "type":"ShapeDecl", … } }
+ +

ShExR, validating a candidate graph against doc/ShExR.shex:

+ +
const shexr = ShExParser.construct('http://www.w3.org/ns/shex',{},{index:true})
+                        .parse(fs.readFileSync('doc/ShExR.shex','utf8'));
+new ShExValidator(shexr, rdfjsDB(graph), {})
+  .validateShapeMap([{node:'http://ex/sch', shape:'http://www.w3.org/ns/shex#Schema'}]);
+ +
PREFIX sx: <http://www.w3.org/ns/shex#>
+<http://ex/sch> a sx:Schema ;
+  sx:start [ a sx:ShapeDecl ; sx:abstract true ; sx:shapeExpr [ a sx:Shape ] ] .
+# conformant -- though no ShExC or ShExJ document can denote this
+ +

Open question

+ +

What ShExUtil.ShExRtoShExJ does with an anonymous ShapeDecl at +start is not established here: the loader failed earlier +(Cannot read properties of undefined (reading 'validator')) before +reaching the conversion. If it emits start: {type: "ShapeDecl", …}, +that is a ShExJ document its own grammar rejects, which would turn this from a +specification gap into a reachable bug.

+ +
+Lives in shexSpec/shexTest +beside the two grammars it compares. The ShExC productions link into +ShEx Semantics; productions are +quoted inline so this note stands on its own if line numbers drift. +
+ + + diff --git a/package-lock.json b/package-lock.json index 6dbf0fff..26bf35b1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,10 @@ "version": "2.2.0-alpha.1", "license": "MIT", "devDependencies": { + "@shexjs/parser": "^1.0.0-alpha.28", "@types/shexj": "^2.1.2", "json-grammar": "^0.3.2", + "jsonld": "^9.0.0", "n3": "^2.7.12", "xlsx": "^0.18.5" }, @@ -18,6 +20,100 @@ "node": ">=0.10.0" } }, + "node_modules/@digitalbazaar/http-client": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@digitalbazaar/http-client/-/http-client-4.4.0.tgz", + "integrity": "sha512-ODhCGmElUPmR3IR+KZmBNkRAFyjJ01rxvk2E+/qQ2h2EGPJH5k6bz3N24ympGc5+i4YCGk/ipIpmkwc0+iSmRg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "ky": "^1.14.3", + "undici": "^6.28.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@rdfjs/types": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@rdfjs/types/-/types-2.0.1.tgz", + "integrity": "sha512-uyAzpugX7KekAXAHq26m3JlUIZJOC0uSBhpnefGV5i15bevDyyejoB7I+9MKeUrzXD8OOUI3+4FeV1wwQr5ihA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@shexjs/parser": { + "version": "1.0.0-alpha.33", + "resolved": "https://registry.npmjs.org/@shexjs/parser/-/parser-1.0.0-alpha.33.tgz", + "integrity": "sha512-V3BZ39uVQivMA2AmvLrl+r9ecFqJNspchpqPmTkgKVdbqaHV1I+7pbyhbAZjLW8vf1QrDQPYJIG+W0j3wUmrDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shexjs/term": "^1.0.0-alpha.28", + "@ts-jison/lexer": "^0.4.1-alpha.1", + "@ts-jison/parser": "^0.4.1-alpha.3", + "@types/shexj": "^2.1.7" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@shexjs/term": { + "version": "1.0.0-alpha.29", + "resolved": "https://registry.npmjs.org/@shexjs/term/-/term-1.0.0-alpha.29.tgz", + "integrity": "sha512-ja9xi4PTMb5jVWKtro2JEzGUE3P/2q72VJxzEU3lJiRsiJjhuVgCr3nJ+YUysSheoR2KZdhFgzwLTwI7BrPjvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rdfjs/types": "^2.0.1", + "@types/shexj": "^2.1.7", + "rdf-data-factory": "^2.0.2", + "relativize-url": "^0.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ts-jison/common": { + "version": "0.4.1-alpha.4", + "resolved": "https://registry.npmjs.org/@ts-jison/common/-/common-0.4.1-alpha.4.tgz", + "integrity": "sha512-3P2x2i/sIh8mVeAY+lu9/NqpuLm4V+McGPce3k/1Zf5pw6fQPa/ideqNu5A5331UEEdMYlQFpP8fJDdAytY/9g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@ts-jison/lexer": { + "version": "0.4.1-alpha.4", + "resolved": "https://registry.npmjs.org/@ts-jison/lexer/-/lexer-0.4.1-alpha.4.tgz", + "integrity": "sha512-OkmxoZJIAmU6wTQfEeqey+4C62cehwfhV9gx4Hbge2dhdNtZkUbNkrYyuSdUbsIx3E4w6bwVOp+8kQAFblpVrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ts-jison/common": "^0.4.1-alpha.4" + } + }, + "node_modules/@ts-jison/parser": { + "version": "0.4.1-alpha.4", + "resolved": "https://registry.npmjs.org/@ts-jison/parser/-/parser-0.4.1-alpha.4.tgz", + "integrity": "sha512-GD+AGlG/Nc7zF/rLtsM695G7Pff6UFBLYuMRC4KD4K9pDGGNMKjCE0/+XGh/1lyo89eb9bLcN7pezRk/JENmPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ts-jison/common": "^0.4.1-alpha.4", + "@ts-jison/lexer": "^0.4.1-alpha.4" + } + }, + "node_modules/@types/node": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.2.tgz", + "integrity": "sha512-X1P21scMv4zGKLYqjdGjaKa7COa0RKVYYZZN/NfvLQ1JegxFhdhpZG/Lyn8AXx6CDUavKAd11v6BvfpkDByK8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~8.9.0" + } + }, "node_modules/@types/shexj": { "version": "2.1.7", "resolved": "https://registry.npmjs.org/@types/shexj/-/shexj-2.1.7.tgz", @@ -103,6 +199,16 @@ "ieee754": "^1.2.1" } }, + "node_modules/canonicalize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/canonicalize/-/canonicalize-2.1.0.tgz", + "integrity": "sha512-F705O3xrsUtgt98j7leetNhTWPe+5S72rlL5O4jA1pKqBVQ/dT1O1D6PFxmSXvc0SUOinWS57DKx0I3CHrXJHQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "canonicalize": "bin/canonicalize.js" + } + }, "node_modules/cfb": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz", @@ -206,6 +312,48 @@ "json-grammar": "lib/cli.js" } }, + "node_modules/jsonld": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/jsonld/-/jsonld-9.0.0.tgz", + "integrity": "sha512-pjMIdkXfC1T2wrX9B9i2uXhGdyCmgec3qgMht+TDj+S0qX3bjWMQUfL7NeqEhuRTi8G5ESzmL9uGlST7nzSEWg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@digitalbazaar/http-client": "^4.2.0", + "canonicalize": "^2.1.0", + "lru-cache": "^6.0.0", + "rdf-canonize": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/ky": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/ky/-/ky-1.14.3.tgz", + "integrity": "sha512-9zy9lkjac+TR1c2tG+mkNSVlyOpInnWdSMiue4F+kq8TwJSgv6o8jhLRg8Ho6SnZ9wOYUq/yozts9qQCfk7bIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/ky?sponsor=1" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/n3": { "version": "2.7.12", "resolved": "https://registry.npmjs.org/n3/-/n3-2.7.12.tgz", @@ -230,6 +378,33 @@ "node": ">= 0.6.0" } }, + "node_modules/rdf-canonize": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/rdf-canonize/-/rdf-canonize-5.0.0.tgz", + "integrity": "sha512-g8OUrgMXAR9ys/ZuJVfBr05sPPoMA7nHIVs8VEvg9QwM5W4GR2qSFEEHjsyHF1eWlBaf8Ev40WNjQFQ+nJTO3w==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "setimmediate": "^1.0.5" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/rdf-data-factory": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/rdf-data-factory/-/rdf-data-factory-2.1.0.tgz", + "integrity": "sha512-q81ZuJvrNLHD4x6qPnNKRKYn1VqYkxZ9zFI8I4JwIfAxlfduNNstmO8i0dRIZemORQDbuVEDoKCo4aOwINmUqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rdfjs/types": "^2.0.0" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/rubensworks/" + } + }, "node_modules/readable-stream": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", @@ -247,6 +422,13 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/relativize-url": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/relativize-url/-/relativize-url-0.1.1.tgz", + "integrity": "sha512-Z3uvG8fITjw8Xcz6ACzO6QZoI02D574Q6PBKvYUfkOxILtiDV9aOBSeSytIky1bBKX/JeK3/YNqCD9sM5FH+Bw==", + "dev": true, + "license": "ISC" + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -268,6 +450,13 @@ ], "license": "MIT" }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true, + "license": "MIT" + }, "node_modules/ssf": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz", @@ -290,6 +479,23 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/undici": { + "version": "6.28.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.28.1.tgz", + "integrity": "sha512-zWpdTVD54H48CIybL0rWQ3ukpb9d23wM7eH5RtfdmeP70cWHNjtfo7P4vZX+5CoDcO53J4Pu5uXp7lNfjc6DRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, + "node_modules/undici-types": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.9.0.tgz", + "integrity": "sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==", + "dev": true, + "license": "MIT" + }, "node_modules/wmf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz", @@ -328,9 +534,93 @@ "engines": { "node": ">=0.8" } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" } }, "dependencies": { + "@digitalbazaar/http-client": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@digitalbazaar/http-client/-/http-client-4.4.0.tgz", + "integrity": "sha512-ODhCGmElUPmR3IR+KZmBNkRAFyjJ01rxvk2E+/qQ2h2EGPJH5k6bz3N24ympGc5+i4YCGk/ipIpmkwc0+iSmRg==", + "dev": true, + "requires": { + "ky": "^1.14.3", + "undici": "^6.28.0" + } + }, + "@rdfjs/types": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@rdfjs/types/-/types-2.0.1.tgz", + "integrity": "sha512-uyAzpugX7KekAXAHq26m3JlUIZJOC0uSBhpnefGV5i15bevDyyejoB7I+9MKeUrzXD8OOUI3+4FeV1wwQr5ihA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@shexjs/parser": { + "version": "1.0.0-alpha.33", + "resolved": "https://registry.npmjs.org/@shexjs/parser/-/parser-1.0.0-alpha.33.tgz", + "integrity": "sha512-V3BZ39uVQivMA2AmvLrl+r9ecFqJNspchpqPmTkgKVdbqaHV1I+7pbyhbAZjLW8vf1QrDQPYJIG+W0j3wUmrDA==", + "dev": true, + "requires": { + "@shexjs/term": "^1.0.0-alpha.28", + "@ts-jison/lexer": "^0.4.1-alpha.1", + "@ts-jison/parser": "^0.4.1-alpha.3", + "@types/shexj": "^2.1.7" + } + }, + "@shexjs/term": { + "version": "1.0.0-alpha.29", + "resolved": "https://registry.npmjs.org/@shexjs/term/-/term-1.0.0-alpha.29.tgz", + "integrity": "sha512-ja9xi4PTMb5jVWKtro2JEzGUE3P/2q72VJxzEU3lJiRsiJjhuVgCr3nJ+YUysSheoR2KZdhFgzwLTwI7BrPjvw==", + "dev": true, + "requires": { + "@rdfjs/types": "^2.0.1", + "@types/shexj": "^2.1.7", + "rdf-data-factory": "^2.0.2", + "relativize-url": "^0.1.0" + } + }, + "@ts-jison/common": { + "version": "0.4.1-alpha.4", + "resolved": "https://registry.npmjs.org/@ts-jison/common/-/common-0.4.1-alpha.4.tgz", + "integrity": "sha512-3P2x2i/sIh8mVeAY+lu9/NqpuLm4V+McGPce3k/1Zf5pw6fQPa/ideqNu5A5331UEEdMYlQFpP8fJDdAytY/9g==", + "dev": true + }, + "@ts-jison/lexer": { + "version": "0.4.1-alpha.4", + "resolved": "https://registry.npmjs.org/@ts-jison/lexer/-/lexer-0.4.1-alpha.4.tgz", + "integrity": "sha512-OkmxoZJIAmU6wTQfEeqey+4C62cehwfhV9gx4Hbge2dhdNtZkUbNkrYyuSdUbsIx3E4w6bwVOp+8kQAFblpVrQ==", + "dev": true, + "requires": { + "@ts-jison/common": "^0.4.1-alpha.4" + } + }, + "@ts-jison/parser": { + "version": "0.4.1-alpha.4", + "resolved": "https://registry.npmjs.org/@ts-jison/parser/-/parser-0.4.1-alpha.4.tgz", + "integrity": "sha512-GD+AGlG/Nc7zF/rLtsM695G7Pff6UFBLYuMRC4KD4K9pDGGNMKjCE0/+XGh/1lyo89eb9bLcN7pezRk/JENmPw==", + "dev": true, + "requires": { + "@ts-jison/common": "^0.4.1-alpha.4", + "@ts-jison/lexer": "^0.4.1-alpha.4" + } + }, + "@types/node": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.2.tgz", + "integrity": "sha512-X1P21scMv4zGKLYqjdGjaKa7COa0RKVYYZZN/NfvLQ1JegxFhdhpZG/Lyn8AXx6CDUavKAd11v6BvfpkDByK8g==", + "dev": true, + "requires": { + "undici-types": "~8.9.0" + } + }, "@types/shexj": { "version": "2.1.7", "resolved": "https://registry.npmjs.org/@types/shexj/-/shexj-2.1.7.tgz", @@ -374,6 +664,12 @@ "ieee754": "^1.2.1" } }, + "canonicalize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/canonicalize/-/canonicalize-2.1.0.tgz", + "integrity": "sha512-F705O3xrsUtgt98j7leetNhTWPe+5S72rlL5O4jA1pKqBVQ/dT1O1D6PFxmSXvc0SUOinWS57DKx0I3CHrXJHQ==", + "dev": true + }, "cfb": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz", @@ -436,6 +732,33 @@ "commander": "^2.19.0" } }, + "jsonld": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/jsonld/-/jsonld-9.0.0.tgz", + "integrity": "sha512-pjMIdkXfC1T2wrX9B9i2uXhGdyCmgec3qgMht+TDj+S0qX3bjWMQUfL7NeqEhuRTi8G5ESzmL9uGlST7nzSEWg==", + "dev": true, + "requires": { + "@digitalbazaar/http-client": "^4.2.0", + "canonicalize": "^2.1.0", + "lru-cache": "^6.0.0", + "rdf-canonize": "^5.0.0" + } + }, + "ky": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/ky/-/ky-1.14.3.tgz", + "integrity": "sha512-9zy9lkjac+TR1c2tG+mkNSVlyOpInnWdSMiue4F+kq8TwJSgv6o8jhLRg8Ho6SnZ9wOYUq/yozts9qQCfk7bIw==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "n3": { "version": "2.7.12", "resolved": "https://registry.npmjs.org/n3/-/n3-2.7.12.tgz", @@ -452,6 +775,24 @@ "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", "dev": true }, + "rdf-canonize": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/rdf-canonize/-/rdf-canonize-5.0.0.tgz", + "integrity": "sha512-g8OUrgMXAR9ys/ZuJVfBr05sPPoMA7nHIVs8VEvg9QwM5W4GR2qSFEEHjsyHF1eWlBaf8Ev40WNjQFQ+nJTO3w==", + "dev": true, + "requires": { + "setimmediate": "^1.0.5" + } + }, + "rdf-data-factory": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/rdf-data-factory/-/rdf-data-factory-2.1.0.tgz", + "integrity": "sha512-q81ZuJvrNLHD4x6qPnNKRKYn1VqYkxZ9zFI8I4JwIfAxlfduNNstmO8i0dRIZemORQDbuVEDoKCo4aOwINmUqQ==", + "dev": true, + "requires": { + "@rdfjs/types": "^2.0.0" + } + }, "readable-stream": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", @@ -465,12 +806,24 @@ "string_decoder": "^1.3.0" } }, + "relativize-url": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/relativize-url/-/relativize-url-0.1.1.tgz", + "integrity": "sha512-Z3uvG8fITjw8Xcz6ACzO6QZoI02D574Q6PBKvYUfkOxILtiDV9aOBSeSytIky1bBKX/JeK3/YNqCD9sM5FH+Bw==", + "dev": true + }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, "ssf": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz", @@ -489,6 +842,18 @@ "safe-buffer": "~5.2.0" } }, + "undici": { + "version": "6.28.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.28.1.tgz", + "integrity": "sha512-zWpdTVD54H48CIybL0rWQ3ukpb9d23wM7eH5RtfdmeP70cWHNjtfo7P4vZX+5CoDcO53J4Pu5uXp7lNfjc6DRA==", + "dev": true + }, + "undici-types": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.9.0.tgz", + "integrity": "sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==", + "dev": true + }, "wmf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz", @@ -515,6 +880,12 @@ "wmf": "~1.0.1", "word": "~0.3.0" } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } } diff --git a/package.json b/package.json index 21e4d911..bbfd1407 100644 --- a/package.json +++ b/package.json @@ -4,12 +4,16 @@ "description": "Shape Expressions library tests.", "scripts": { "dist": "for d in schemas/ negativeSyntax/ negativeStructure/ validation/; do (cd $d && echo -n $d ':' && make); done", - "test": "npm run test-shexj-jsg && npm run test-shexv-val && npm run test-shexv-err && npm run test-schema-imports && npm run test-ts", + "test": "npm run test-shexj-jsg && npm run test-shexv-val && npm run test-shexv-err && npm run test-schema-imports && npm run vocab-check && npm run shexr-check && npm run test-ts", "test-ts": "rm -rf _ts && mkdir -p _ts/schemas && for f in $(ls schemas/*.json | egrep -v '(coverage|representationTests).json'); do sh bin/makeTsTests.sh _ts $f; done && tsc --noEmit _ts/schemas/*.ts && rm -r _ts", "test-shexj-jsg": "ls schemas/*.json | egrep -v '(coverage|representationTests).json' | xargs json-grammar doc/ShExJ.jsg", "test-shexv-val": "ls validation/*.val | xargs json-grammar doc/ShExV.jsg", "test-shexv-err": "ls validation/*.err | xargs json-grammar doc/ShExV.jsg", - "test-schema-imports": "bin/checkSchemaImports.js schemas" + "test-schema-imports": "bin/checkSchemaImports.js schemas", + "vocab": "node vocab/mk_vocab.js", + "vocab-check": "node vocab/mk_vocab.js --check", + "shexr": "node bin/mkShExR.js", + "shexr-check": "node bin/mkShExR.js --check" }, "author": { "name": "Eric Prud'hommeaux", @@ -46,8 +50,10 @@ "url": "https://github.com/shexSpec/shexTest/issues" }, "devDependencies": { + "@shexjs/parser": "^1.0.0-alpha.28", "@types/shexj": "^2.1.2", "json-grammar": "^0.3.2", + "jsonld": "^9.0.0", "n3": "^2.7.12", "xlsx": "^0.18.5" } diff --git a/schemas/meta.ttl b/schemas/meta.ttl index 3c03c569..ad542344 100644 --- a/schemas/meta.ttl +++ b/schemas/meta.ttl @@ -18,7 +18,6 @@ PREFIX sht: <1dotLNexComment.shex> sht:sameAbstractSyntaxAs <1dot.shex> . <1dotLNdefault.shex> sht:sameAbstractSyntaxAs <1dot.shex> . <1dotNSdefault.shex> sht:sameAbstractSyntaxAs <1dot.shex> . - <1inversenegateddot.shex> sht:sameAbstractSyntaxAs <1negatedinversedot.shex> . <2dotCommas.shex> sht:sameAbstractSyntaxAs <2dotCommas.shex> . sht:sameAbstractSyntaxAs <2dotCommas.shex> . sht:sameAbstractSyntaxAs <2dotCommas.shex> . diff --git a/vocab/README.md b/vocab/README.md new file mode 100644 index 00000000..cbe796a3 --- /dev/null +++ b/vocab/README.md @@ -0,0 +1,103 @@ +# ShEx vocabulary source + +`vocab.csv` is the source of truth for the ShEx vocabulary, +`http://www.w3.org/ns/shex#`. `mk_vocab.js` generates the derived files from +it. + +This lives here because shexTest already carried two hand-maintained copies of +this vocabulary — `../doc/ShExJ-context.jsonld` and `../doc/ShExR.shex` — and +both had drifted from what is published at www.w3.org/ns/shex. + +## History + +Gregg Kellogg (RIP) wrote the original `mk_vocab.rb` plus an erubis +`template.html`, in +[shexSpec/shexspec.github.io/ns](https://github.com/shexSpec/shexspec.github.io/tree/master/ns) +(dormant since 2018). `mk_vocab.js` is a dependency-free Node port of it, +verified to reproduce the Ruby's output byte-for-byte before any new terms were +added. The template is folded into the `renderHtml` function. + +The port fixes the Ruby's `dc:imports` and `http;//purl.org` typos, and folds +back the edits that had been made by hand to the generated files in w3c/ns +since 2017 (`shex:extends`, `shex:shapes` as a `@list`). + +## Generated files + +| file | generated? | +| --- | --- | +| `../doc/ShExJ-context.jsonld` | yes, by `npm run vocab` | +| `w3c/ns` `shex.ttl`, `shex.jsonld`, `shex.html` | yes, with `--nsdir` | +| `../doc/ShExR.shex`, `../doc/ShExR.ttl` | **no** — hand-maintained | + +`mk_vocab.rb` had a fourth output format, `to_shexc`, that emitted a ShExC +sketch of ShExR from the domain/range/multiplicity columns. It is ported as +`-f shexc`, but it does not and cannot replace `../doc/ShExR.shex`: the +generated schema has no `CLOSED`, no `a [sx:Class]` type arcs and no +`…List1Plus` shapes for the `@list`-valued properties, and as of this writing +it does not parse. ShExR stays hand-maintained; `npm run vocab-check` guards +it instead (see below). + +`../doc/ShExR.shex` is also mirrored into shex.js as +`packages/shex-webapp/doc/ShExRSchema.js`, which has to be updated by hand to +match. + +## Updating the vocabulary + +1. Edit `vocab.csv`. Columns: + `id,type,label,subClassOf,domain,range,@type,@container,ForwardMultiplicity,ReverseMultiplicity,term,comment` + - `type` selects the kind of row: `prefix`, `term` (context-only alias), + `rdf:Property`, `rdfs:Class`, `rdfs:Datatype`, `owl:imports`, + `rdfs:seeAlso`, or a class name, which makes the row an instance of it. + - `subClassOf` doubles as subPropertyOf for properties, and as the URI for + prefix/term/imports/seeAlso rows. + - `@type`/`@container` override the JSON-LD context coercions otherwise + derived from `range`; an `@type` of `@null` keeps the term out of the + context entirely. + - Row order does not matter; the output is sorted. +2. Commit `vocab.csv`. `dc:date` and `owl:versionInfo` come from + `git log -1 vocab.csv`, so the commit has to exist before the files are + generated. If the merge rewrites the sha (a squash merge will), regenerate + afterwards so `owl:versionInfo` points at a commit that exists. +3. `npm run vocab` regenerates `../doc/ShExJ-context.jsonld`. + Add `-- --nsdir path/to/w3c/ns` to also regenerate `shex.ttl`, + `shex.jsonld` and `shex.html` in a [w3c/ns](https://github.com/w3c/ns) + checkout, then raise a PR there. Those three files are published at + ; nothing else in this directory belongs in + that repo, because that repo is the document root of www.w3.org/ns/. +4. Commit the regenerated files. + +`node vocab/mk_vocab.js --help` lists the rest of the options. + +## Drift check + +`npm run vocab-check` reports terms that `../doc/ShExR.shex` uses but +`vocab.csv` does not define. It is part of `npm test`, and it passes. + +It was written because ShExR had drifted from the published vocabulary in both +directions. `sx:ShapeDecl`, `sx:abstract` and `sx:imports` had arrived with the +ShEx 2.1 `EXTENDS`/`abstract` work and were never published; they are now in +`vocab.csv`. `sx:negated` pointed the other way and has been **deleted from +ShExR** rather than added to the vocabulary: + +`negated` was the ShEx 2.0 draft's `!` operator on TripleConstraint. It was +removed from the language in November 2016 (shexTest `224c610` "- negated", +spec `d3f882d` "- negation") over the semantics problem in shexSpec/shex#11, +and replaced by `{0,0}` cardinality and `ShapeNot`. Seven weeks later +`fe51e15` ("~ aligned with ShExJ.jsg") copied it back into `doc/ShExR.shex` +from the grammar, which had not yet been cleaned up; `e01f012` +("TripleConstraint -= negated:BOOL") dropped it from `doc/ShExJ.jsg` in 2020 +but left `ShExR.shex` alone, so the RDF rendering kept a term the JSON +rendering had deleted. It was never in the published namespace, never in the +spec, and the ShExC parser has no `!` rule, so nothing could produce it. + +## Known stale files + +`doc/ShExR.ntriples` was last regenerated in 2017 (`7a7da0d`). It predates +`ShapeDecl`, `abstract`, `imports` and `extends`, and holds 800 triples against +`doc/ShExR.ttl`'s 1354 — it is a snapshot, not a current serialization, and +nothing regenerates it. `vocab-check` only reads `doc/ShExR.shex`, so it does +not police this. Either regenerate it from `doc/ShExR.ttl` or delete it. + +`doc/ShExJ.jsg` has `restricts` on ShapeDecl; neither `doc/ShExR.shex` nor +`vocab.csv` defines it. Extending the check to read the JSG too would catch +that class of gap. diff --git a/vocab/mk_vocab.js b/vocab/mk_vocab.js new file mode 100644 index 00000000..6b19f2a8 --- /dev/null +++ b/vocab/mk_vocab.js @@ -0,0 +1,715 @@ +#!/usr/bin/env node +// Parse vocabulary definition in CSV to generate Context+Vocabulary in +// JSON-LD, Turtle, or ReSpec HTML. +// +// This is a JavaScript port of Gregg Kellogg's mk_vocab.rb from +// https://github.com/shexSpec/shexspec.github.io/tree/master/ns +// (including its erubis template.html, folded into renderHtml below). +// +// Usage: +// node mk_vocab.js # regenerate every derived file in place +// node mk_vocab.js -f jsonld # one format to stdout +// # (jsonld|ttl|html|context|shexc) +// node mk_vocab.js -f ttl -o out.ttl +// node mk_vocab.js --nsdir ../../../w3c/ns # where the shex.{ttl,jsonld,html} live +// node mk_vocab.js --date 2017-07-07 --commit https://github.com/.../commit/ +// +// --date/--commit override the values otherwise taken from `git log -1 vocab.csv`. + +'use strict'; +const fs = require('fs'); +const path = require('path'); +const { execSync } = require('child_process'); + +const TITLE = 'Shape Expression Vocabulary'; +const DESCRIPTION = 'This document describes the RDFS vocabulary description used in the Shape Expression Language (ShEx) [[shex-semantics]] along with the default JSON-LD Context and shape expression to validate RDF versions of shapes.'; +const COMMIT_BASE = 'https://github.com/shexSpec/shexTest/commit/'; + +// ---------------------------------------------------------------- CSV input + +function parseCSV(text) { + const rows = []; + let row = [], field = '', inQuotes = false, sawField = false; + for (let i = 0; i < text.length; i++) { + const c = text[i]; + if (inQuotes) { + if (c === '"') { + if (text[i + 1] === '"') { field += '"'; i++; } + else inQuotes = false; + } else field += c; + } else if (c === '"') { + inQuotes = true; sawField = true; + } else if (c === ',') { + row.push(sawField || field !== '' ? field : null); field = ''; sawField = false; + } else if (c === '\n' || c === '\r') { + if (c === '\r' && text[i + 1] === '\n') i++; + row.push(sawField || field !== '' ? field : null); + rows.push(row); + row = []; field = ''; sawField = false; + } else field += c; + } + if (field !== '' || sawField || row.length) { + row.push(sawField || field !== '' ? field : null); + rows.push(row); + } + return rows.map(r => r.map(v => v === '' ? null : v)); +} + +// Mimics Ruby Array#to_s (inspect), used by mk_vocab.rb to sort rows. +function rubyInspect(row) { + return '[' + row.map(v => + v == null ? 'nil' : '"' + v.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"' + ).join(', ') + ']'; +} + +class Vocab { + constructor(csvPath, opts = {}) { + const raw = parseCSV(fs.readFileSync(csvPath, 'utf8')); + const columns = raw.shift().map(c => c); + this.prefixes = {}; this.terms = {}; this.properties = {}; + this.classes = {}; this.datatypes = {}; this.instances = {}; + this.imports = []; this.seeAlso = []; + + let sha = null, date = null; + try { + const out = execSync( + `git log -1 --format=%H%n%ad --date=format:%Y-%m-%d -- ${JSON.stringify(path.basename(csvPath))}`, + { cwd: path.dirname(csvPath), encoding: 'utf8' }).trim(); + if (out) [sha, date] = out.split('\n'); + } catch (e) { /* not a git checkout; fall through */ } + this.commit = opts.commit || COMMIT_BASE + (sha || 'uncommitted'); + this.date = opts.date || date || new Date().toISOString().slice(0, 10); + + raw.sort((a, b) => rubyInspect(a) < rubyInspect(b) ? -1 : 1) + .forEach(line => { + const entry = {}; + columns.forEach((c, i) => { + const v = line[i]; + entry[c] = v == null ? null : v.replace(/\r/g, '\n').replace(/\\/g, '\\\\'); + }); + switch (entry.type) { + case 'prefix': this.prefixes[entry.id] = entry; break; + case 'term': this.terms[entry.id] = entry; break; + case 'rdf:Property': this.properties[entry.id] = entry; break; + case 'rdfs:Class': this.classes[entry.id] = entry; break; + case 'rdfs:Datatype': this.datatypes[entry.id] = entry; break; + case 'owl:imports': this.imports.push(entry.subClassOf); break; + case 'rdfs:seeAlso': this.seeAlso.push(entry.subClassOf); break; + default: this.instances[entry.id] = entry; + } + }); + } + + namespaced(term) { + return term.includes(':') ? term : `shex:${term}`; + } + + // ------------------------------------------------------------- JSON-LD + + buildJsonld() { + const context = {}; + const rdfsContext = { + "id": "@id", + "type": "@type", + "dc:title": {"@container": "@language"}, + "dc:description": {"@container": "@language"}, + "dc:date": {"@type": "xsd:date"}, + "rdfs:comment": {"@container": "@language"}, + "rdfs:domain": {"@type": "@id"}, + "rdfs:label": {"@container": "@language"}, + "rdfs:range": {"@type": "@id"}, + "rdfs:seeAlso": {"@type": "@id"}, + "rdfs:subClassOf": {"@type": "@id"}, + "rdfs:subPropertyOf": {"@type": "@id"}, + "owl:equivalentClass": {"@type": "@vocab"}, + "owl:equivalentProperty": {"@type": "@vocab"}, + "owl:oneOf": {"@container": "@list", "@type": "@vocab"}, + "owl:imports": {"@type": "@id"}, + "owl:versionInfo": {"@type": "@id"}, + "owl:inverseOf": {"@type": "@vocab"}, + "owl:unionOf": {"@type": "@vocab", "@container": "@list"}, + "rdfs_classes": {"@reverse": "rdfs:isDefinedBy", "@type": "@id"}, + "rdfs_properties": {"@reverse": "rdfs:isDefinedBy", "@type": "@id"}, + "rdfs_datatypes": {"@reverse": "rdfs:isDefinedBy", "@type": "@id"}, + "rdfs_instances": {"@reverse": "rdfs:isDefinedBy", "@type": "@id"} + }; + const rdfsClasses = [], rdfsProperties = [], rdfsDatatypes = [], rdfsInstances = []; + + for (const [id, entry] of Object.entries(this.prefixes)) + context[id] = entry.subClassOf; + + for (const [id, entry] of Object.entries(this.terms)) { + if (entry['@type'] === '@null') continue; + if (entry['@container'] || entry['@type']) { + const defn = {'@id': entry.subClassOf}; + if (entry['@container']) defn['@container'] = entry['@container']; + if (entry['@type']) defn['@type'] = entry['@type']; + context[id] = defn; + } else { + context[id] = entry.subClassOf; + } + } + + for (const [id, entry] of Object.entries(this.classes)) { + const term = entry.term || id; + if (entry['@type'] !== '@null') context[term] = this.namespaced(id); + + const node = { + '@id': this.namespaced(id), + '@type': 'rdfs:Class', + 'rdfs:label': {en: entry.label || ''}, + 'rdfs:comment': {en: entry.comment || ''}, + }; + if (entry.subClassOf) node['rdfs:subClassOf'] = this.namespaced(entry.subClassOf); + rdfsClasses.push(node); + } + + for (const [id, entry] of Object.entries(this.properties)) { + const defn = {'@id': this.namespaced(id)}; + if (entry.range === 'xsd:string') defn['@language'] = null; + else if (entry.range && /xsd:/.test(entry.range)) defn['@type'] = entry.range.split(',')[0]; + else if (entry.range == null || entry.range === 'rdfs:Literal') { /* nothing */ } + else defn['@type'] = '@id'; + + if (entry['@container']) defn['@container'] = entry['@container']; + if (entry['@type']) defn['@type'] = entry['@type']; + + const term = entry.term || id; + if (entry['@type'] !== '@null') context[term] = defn; + + const node = { + '@id': this.namespaced(id), + '@type': 'rdf:Property', + 'rdfs:label': {en: entry.label || ''}, + 'rdfs:comment': {en: entry.comment || ''}, + }; + if (entry.subClassOf) node['rdfs:subPropertyOf'] = this.namespaced(entry.subClassOf); + + const domains = (entry.domain || '').split(',').filter(s => s !== ''); + if (domains.length === 1) node['rdfs:domain'] = this.namespaced(domains[0]); + else if (domains.length > 1) node['rdfs:domain'] = {'owl:unionOf': domains.map(d => this.namespaced(d))}; + + const ranges = (entry.range || '').split(',').filter(s => s !== ''); + if (ranges.length === 1) node['rdfs:range'] = this.namespaced(ranges[0]); + else if (ranges.length > 1) node['rdfs:range'] = {'owl:unionOf': ranges.map(r => this.namespaced(r))}; + + rdfsProperties.push(node); + } + + for (const [id, entry] of Object.entries(this.datatypes)) { + if (entry['@type'] !== '@null') context[id] = this.namespaced(id); + const node = { + '@id': this.namespaced(id), + '@type': 'rdfs:Datatype', + 'rdfs:label': {en: entry.label || ''}, + 'rdfs:comment': {en: entry.comment || ''}, + }; + if (entry.subClassOf) node['rdfs:subClassOf'] = this.namespaced(entry.subClassOf); + rdfsDatatypes.push(node); + } + + for (const [id, entry] of Object.entries(this.instances)) { + if (entry['@type'] !== '@null') context[id] = this.namespaced(id); + rdfsInstances.push({ + '@id': this.namespaced(id), + '@type': entry.type, + 'rdfs:label': {en: entry.label || ''}, + 'rdfs:comment': {en: entry.comment || ''}, + }); + } + + // Use separate rdfs context so as not to polute the ShEx context. + const ontology = { + '@context': rdfsContext, + '@id': this.prefixes['shex'].subClassOf, + '@type': 'owl:Ontology', + 'dc': 'http://purl.org/dc/terms/', + 'owl': 'http://www.w3.org/2002/07/owl#', + 'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', + 'rdfs': 'http://www.w3.org/2000/01/rdf-schema#', + 'dc:title': {en: TITLE}, + 'dc:description': {en: DESCRIPTION}, + 'dc:date': this.date, + 'owl:imports': this.imports, + 'owl:versionInfo': this.commit, + 'rdfs:seeAlso': this.seeAlso, + 'rdfs_classes': rdfsClasses, + 'rdfs_properties': rdfsProperties, + 'rdfs_datatypes': rdfsDatatypes, + 'rdfs_instances': rdfsInstances, + }; + for (const [k, v] of Object.entries(ontology)) + if (Array.isArray(v) && v.length === 0) delete ontology[k]; + + return {'@context': context, '@graph': ontology}; + } + + toJsonld() { + return JSON.stringify(this.buildJsonld(), null, 2); + } + + // The JSON-LD context on its own, as ../doc/ShExJ-context.jsonld — the + // context ShExJ documents reference, without the ontology in @graph. + toContext() { + return JSON.stringify({'@context': this.buildJsonld()['@context']}, null, 2); + } + + // -------------------------------------------------------------- Turtle + + toTtl() { + const output = []; + + const prefixes = Object.assign({ + dc: {subClassOf: 'http://purl.org/dc/terms/'}, + owl: {subClassOf: 'http://www.w3.org/2002/07/owl#'}, + rdf: {subClassOf: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'}, + rdfs: {subClassOf: 'http://www.w3.org/2000/01/rdf-schema#'}, + }, this.prefixes); + for (const [id, entry] of Object.entries(prefixes)) + output.push(`@prefix ${id}: <${entry.subClassOf}> .`); + + output.push('\n# CSVM Ontology definition'); + output.push('shex: a owl:Ontology;'); + output.push(` dc:title "${TITLE}"@en;`); + output.push(` dc:description """${DESCRIPTION}"""@en;`); + output.push(` dc:date "${this.date}"^^xsd:date;`); + if (this.imports.length) + output.push(` owl:imports ${this.imports.map(i => '<' + i + '>').join(', ')};`); + output.push(` owl:versionInfo <${this.commit}>;`); + output.push(` rdfs:seeAlso ${this.seeAlso.map(i => '<' + i + '>').join(', ')};`); + output.push(' .\n'); + + output.push('\n# Class definitions'); + for (const [id, entry] of Object.entries(this.classes)) { + output.push(`shex:${id} a rdfs:Class;`); + output.push(` rdfs:label "${entry.label || ''}"@en;`); + output.push(` rdfs:comment """${entry.comment || ''}"""@en;`); + if (entry.subClassOf) output.push(` rdfs:subClassOf ${this.namespaced(entry.subClassOf)};`); + output.push(' rdfs:isDefinedBy shex: .'); + } + + output.push('\n# Property definitions'); + for (const [id, entry] of Object.entries(this.properties)) { + output.push(`shex:${id} a rdf:Property;`); + output.push(` rdfs:label "${entry.label || ''}"@en;`); + output.push(` rdfs:comment """${entry.comment || ''}"""@en;`); + if (entry.subClassOf) output.push(` rdfs:subPropertyOf ${this.namespaced(entry.subClassOf)};`); + + const domains = (entry.domain || '').split(',').filter(s => s !== ''); + if (domains.length === 1) output.push(` rdfs:domain ${this.namespaced(entry.domain)};`); + else if (domains.length > 1) + output.push(` rdfs:domain [ owl:unionOf (${domains.map(d => this.namespaced(d)).join(' ')})];`); + + const ranges = (entry.range || '').split(',').filter(s => s !== ''); + if (ranges.length === 1) output.push(` rdfs:range ${this.namespaced(entry.range)};`); + else if (ranges.length > 1) + output.push(` rdfs:range [ owl:unionOf (${ranges.map(r => this.namespaced(r)).join(' ')})];`); + + output.push(' rdfs:isDefinedBy shex: .'); + } + + output.push('\n# Datatype definitions'); + for (const [id, entry] of Object.entries(this.datatypes)) { + output.push(`shex:${id} a rdfs:Datatype;`); + output.push(` rdfs:label "${entry.label || ''}"@en;`); + output.push(` rdfs:comment """${entry.comment || ''}"""@en;`); + if (entry.subClassOf) output.push(` rdfs:subClassOf ${this.namespaced(entry.subClassOf)};`); + output.push(' rdfs:isDefinedBy shex: .'); + } + + output.push('\n# Instance definitions'); + for (const [id, entry] of Object.entries(this.instances)) { + output.push(`shex:${id} a ${this.namespaced(entry.type)};`); + output.push(` rdfs:label "${entry.label || ''}"@en;`); + output.push(` rdfs:comment """${entry.comment || ''}"""@en;`); + output.push(' rdfs:isDefinedBy shex: .'); + } + + return output.join('\n'); + } + + // --------------------------------------------------------------- ShExC + + // Port of Gregg's to_shexc. This is a sketch of ShExR derived from the + // domain/range/multiplicity columns, NOT a replacement for the + // hand-maintained ../doc/ShExR.shex: it has no CLOSED, no `a [sx:Class]` + // type arcs, and no List2Plus/List1Plus shapes for the @list-valued + // properties. Use `--check` to compare the two. + toShexc() { + const output = []; + const typeDef = term => { + const t = term.includes(':') ? term : `shex:${term}`; + if (t === 'rdfs:Resource') return 'IRI'; + if (t.startsWith('xsd')) return t; + return '@' + t; + }; + const mult = s => ({'0:1': '?', '1:1': '', '1:N': '+', '0:N': '*'})[s] || ''; + + for (const [id, entry] of Object.entries(this.prefixes)) + output.push(`PREFIX ${id}: <${entry.subClassOf}>`); + + output.push('#ShExc definition of ShExJ'); + output.push(`#${TITLE}`); + output.push(`#${DESCRIPTION}`); + output.push(`#Date: ${this.date}`); + if (this.imports.length) + output.push(`#Imports ${this.imports.map(i => '<' + i + '>').join(', ')}`); + output.push(`#Version ${this.commit}`); + output.push(`#See also ${this.seeAlso.map(i => '<' + i + '>').join(', ')}`); + output.push(' \n'); + output.push('start = @shex:Schema'); + output.push(''); + + output.push('\n# Shape definitions'); + for (const [id, cls] of Object.entries(this.classes)) { + output.push(`shex:${id} {`); + if (cls.subClassOf) + output.push(` #// rdfs:subClassOf ${this.namespaced(cls.subClassOf)};`); + + for (const [propid, prop] of Object.entries(this.properties)) { + const domains = (prop.domain || '').split(',').filter(s => s !== ''); + if (!domains.includes(id)) continue; + const ranges = (prop.range || '').split(',').filter(s => s !== ''); + if (ranges.length === 1) + output.push(` shex:${propid} ${typeDef(prop.range)}${mult(prop.ForwardMultiplicity)} ;`); + else if (ranges.length > 1) + output.push(` shex:${propid} (${ranges.map(typeDef).join(' OR ')})${mult(prop.ForwardMultiplicity)} ;`); + if (prop.subClassOf) + output.push(` #// rdfs:subPropertyOf ${this.namespaced(prop.subClassOf)};`); + } + + const childs = Object.entries(this.classes) + .filter(([, c]) => c.subClassOf === id) + .map(([childId]) => '&shex:' + childId); + if (childs.length) output.push(` (${childs.join(' | ')})`); + + const values = Object.entries(this.instances) + .filter(([, e]) => e.type === id) + .map(([instid]) => `shex:${instid}`); + if (values.length) output.push(` [${values.join(' ')}]`); + + output.push('}'); + } + return output.join('\n'); + } + + // ------------------------------------------------- ReSpec HTML template + + toHtml() { + const json = this.buildJsonld(); + return renderHtml(json['@graph'], json['@context']); + } +} + +function renderHtml(ont, context) { + const out = []; + const w = line => out.push(line); + + w(` + + + ${ont['dc:title']['en']} + + + + + +
+

This document describes the + ${ont['dc:title']['en']} + and Term definitions used + for describing Shape Expressions [[shex-semantics]]. This document provides the RDFS [[RDF-SCHEMA]] vocabulary definition and a description of the JSON-LD context definition for use with + defining shape expressions.

+

Alternate versions of the vocabulary definition exist in + Turtle and + JSON-LD, + which also includes the @context required for metadata descriptions. + +

+
+
Published:
`); + const imports = ont['owl:imports'] || []; + if (imports.length) { + w('
Imports:
'); + for (const ref of imports) + w(`
${ref}
`); + } + w(`
Version Info:
+
${ont['owl:versionInfo']}
+
See Also:
`); + for (const ref of ont['rdfs:seeAlso'] || []) + w(`
${ref}
`); + w(`
+
+
+

+ FIXME +

+
+
+

Introduction

+

${ont['dc:description']['en']}

+

This specification makes use of the following namespaces:

+
+
shex:
+
http://www.w3.org/ns/shex#
+
rdf:
+
http://www.w3.org/1999/02/22-rdf-syntax-ns#
+
rdfs:
+
http://www.w3.org/2000/01/rdf-schema#
+
xsd:
+
http://www.w3.org/2001/XMLSchema#
+
+
`); + + for (const sect of [ + {heading: 'Class Definitions', key: 'rdfs_classes'}, + {heading: 'Property Definitions', key: 'rdfs_properties'}, + {heading: 'Datatype Definitions', key: 'rdfs_datatypes'}, + {heading: 'Instance Definitions', key: 'rdfs_instances'}, + ]) { + w('
'); + w(`

${sect.heading}

`); + w(`

The following are ${sect.heading.toLowerCase()} in the shex namespace:

`); + w(' '); + for (const defn of ont[sect.key] || []) { + const frag = defn['@id'].slice(5); + const label = defn['rdfs:label']['en']; + w(` `); + w(` `); + w(` '); + w(' '); + } + w('
${frag}`); + w(` ${label}`); + w(` §`); + w(`

${defn['rdfs:comment']['en']}

`); + w(' '); + const props = ['rdfs:subClassOf', 'rdfs:subPropertyOf', 'rdfs:range', 'rdfs:domain']; + if (props.some(p => p in defn)) { + w('
'); + for (const p of props) { + if (!(p in defn)) continue; + w(`
${p}
`); + const v = defn[p]; + if (typeof v === 'object' && v !== null && 'owl:unionOf' in v) { + w(`
`); + w(' Union of'); + for (const c of v['owl:unionOf']) + w(` ${c}`); + w('
'); + } else { + w(`
${v}
`); + } + } + w('
'); + } + w('
'); + w('
'); + } + + w('
'); + w('

Term Definitions

'); + w('
'); + for (const term of Object.keys(context).sort()) { + const defn = context[term]; + w(`
${term}
`); + w('
'); + if (typeof defn === 'string') w(` ${defn}`); + else if (defn['@id']) w(` ${defn['@id']}`); + else if (defn['@reverse']) w(` reverse of ${defn['@reverse']}`); + else w(` ${term}`); + if (typeof defn === 'object' && defn['@type']) + w(` with string values interpreted as ${defn['@type']}`); + if (typeof defn === 'object' && defn['@container']) { + if (defn['@container'] === '@language') + w(' with object values interpreted as language-specific, indexed by language'); + else if (defn['@container'] === '@index') + w(' with object values interpreted indexed by index'); + else + w(` with array values interpreted as ${defn['@container']}`); + } + w('
'); + } + w('
'); + w('
'); + w(' '); + w(''); + + return out.join('\n'); +} + +// ------------------------------------------------------------ drift check + +// The vocabulary has derived copies that this script does NOT generate, +// because they are hand-maintained and richer than anything the CSV can +// express (../doc/ShExR.shex and its ../doc/ShExR.ttl serialization, mirrored +// into shex.js as packages/shex-webapp/doc/ShExRSchema.js). They drift in both +// directions: ShExR ran years ahead of the vocabulary with sx:ShapeDecl, +// sx:abstract and sx:imports, and still carries sx:negated, which the language +// dropped in 2016 (see README.md). Comparing the term sets makes that show up +// as a failure rather than as a surprise years later. +function check(vocab) { + const defined = new Set([ + ...Object.keys(vocab.classes), + ...Object.keys(vocab.properties), + ...Object.keys(vocab.datatypes), + ...Object.keys(vocab.instances), + ]); + + const shexrPath = path.join(__dirname, '..', 'doc', 'ShExR.shex'); + const used = new Set(); + for (const m of fs.readFileSync(shexrPath, 'utf8').matchAll(/\bsx:([A-Za-z_][A-Za-z0-9_]*)/g)) + used.add(m[1]); + + const missing = [...used].filter(t => !defined.has(t)).sort(); + + // Terms the vocabulary defines but ShExR never mentions are expected: the + // abstract classes and properties ShExR expands away, and the shape-map + // terms, which describe ShapeMaps rather than schemas. + console.log(`vocab.csv defines ${defined.size} terms; doc/ShExR.shex uses ${used.size}`); + if (missing.length) { + console.error(`\ndoc/ShExR.shex uses ${missing.length} term(s) absent from vocab.csv:`); + missing.forEach(t => console.error(` sx:${t}`)); + console.error('\nEither correct ShExR.shex, or add them to vocab.csv and regenerate.'); + console.error('See README.md -- sx:negated is expected here, and wants removing'); + console.error('from ShExR rather than adding to a published W3C namespace.'); + return 1; + } + console.log('doc/ShExR.shex uses no terms absent from vocab.csv'); + return 0; +} + +// -------------------------------------------------------------------- CLI + +const USAGE = `Usage: mk_vocab.js [options] + -f, --format FMT emit one format to stdout: jsonld|ttl|html|context|shexc + -o, --output FILE write --format output to FILE instead of stdout + --nsdir DIR also regenerate shex.{ttl,jsonld,html} in DIR + (a w3c/ns checkout; they are published at www.w3.org/ns/) + --check report terms used by ../doc/ShExR.shex but not defined here + --csv FILE vocabulary source (default: ./vocab.csv) + --date DATE override the dc:date otherwise taken from git log + --commit URL override the owl:versionInfo otherwise taken from git log + +With no options, regenerates the derived files inside this repo +(../doc/ShExJ-context.jsonld).`; + +function main() { + const args = process.argv.slice(2); + const opts = {}; + for (let i = 0; i < args.length; i++) { + switch (args[i]) { + case '--format': case '-f': opts.format = args[++i]; break; + case '--output': case '-o': opts.output = args[++i]; break; + case '--csv': opts.csv = args[++i]; break; + case '--date': opts.date = args[++i]; break; + case '--commit': opts.commit = args[++i]; break; + case '--nsdir': opts.nsdir = args[++i]; break; + case '--check': opts.check = true; break; + case '--help': case '-?': console.error(USAGE); process.exit(1); + default: + console.error(`Unknown option: ${args[i]}\n\n${USAGE}`); + process.exit(1); + } + } + + const vocab = new Vocab(opts.csv || path.join(__dirname, 'vocab.csv'), opts); + const gen = { + jsonld: () => vocab.toJsonld(), + ttl: () => vocab.toTtl(), + html: () => vocab.toHtml(), + context: () => vocab.toContext(), + shexc: () => vocab.toShexc(), + }; + + if (opts.check) process.exit(check(vocab)); + + if (opts.format) { + if (!gen[opts.format]) { + console.error(`Unknown format: ${opts.format}\n\n${USAGE}`); + process.exit(1); + } + const text = gen[opts.format]() + '\n'; + if (opts.output) fs.writeFileSync(opts.output, text); + else process.stdout.write(text); + return; + } + + const write = (target, text) => { + fs.writeFileSync(target, text + '\n'); + console.error(`wrote ${target}`); + }; + + write(path.join(__dirname, '..', 'doc', 'ShExJ-context.jsonld'), gen.context()); + + if (opts.nsdir) { + for (const [format, fn] of Object.entries({jsonld: 'shex.jsonld', ttl: 'shex.ttl', html: 'shex.html'})) + write(path.join(opts.nsdir, fn), gen[format]()); + } +} + +main(); diff --git a/vocab/vocab.csv b/vocab/vocab.csv new file mode 100644 index 00000000..57e797d4 --- /dev/null +++ b/vocab/vocab.csv @@ -0,0 +1,92 @@ +id,type,label,subClassOf,domain,range,@type,@container,ForwardMultiplicity,ReverseMultiplicity,term,comment +,rdfs:seeAlso,,http://shex.io/shex-semantics,,,,,,,, +literal,NodeKind,literal,,,,,,,,,Requires node to be an rdf:Literal +nonliteral,NodeKind,nonliteral,,,,,,,,,Requires node to be a Blank Node or IRI +iri,NodeKind,iri,,,,,,,,,Requires node to be an IRI +bnode,NodeKind,bnode,,,,,,,,,Requires node to be a Blank Node +rdf,prefix,,http://www.w3.org/1999/02/22-rdf-syntax-ns#,,,,,,,, +rdfs,prefix,,http://www.w3.org/2000/01/rdf-schema#,,,,,,,, +shex,prefix,,http://www.w3.org/ns/shex#,,,,,,,, +xsd,prefix,,http://www.w3.org/2001/XMLSchema#,,,,,,,, +annotation,rdf:Property,annotation,,"EachOf,OneOf,TripleConstraint",Annotation,@null,,0:N,1:N,,Annotations on a TripleExpression. +closed,rdf:Property,closed,,Shape,xsd:boolean,,,0:1,,,"Indicates that a Shape is closed, meaning that it may contain no property values other than those used within TripleConstraints." +code,rdf:Property,code,,SemAct,xsd:string,,,1:1,,,Code executed by Semantic Action. +datatype,rdf:Property,datatype,,NodeConstraint,rdfs:Datatype,,,0:1,0:N,,A datatype constraint. +exclusion,rdf:Property,exclusion,,StemRange,"rdfs:Resource,Stem",@null,,0:N,0:N,,Values that are excluded from value matching. +expression,rdf:Property,expression,,Shape,TripleExpression,,,0:N,0:N,,Expression associated with the TripleExpression. +expressions,rdf:Property,expressions,,"EachOf,OneOf",TripleExpression,,@list,1:N,0:N,,List of 2 or more expressions associated with the TripleExpression. +extra,rdf:Property,extra,,Shape,rdfs:Resource,,,0:N,0:N,,Properties which may have extra values beyond those matched through a constraint. +flags,rdf:Property,flags,,NodeConstraint,xsd:string,,,0:1,,,Regular expression flags +fractiondigits,rdf:Property,fraction digits,numericFacet,NodeConstraint,xsd:integer,,,0:1,,,"for ""fractiondigits"" constraints, v is less than or equals the number of digits to the right of the decimal place in the XML Schema canonical form[xmlschema-2] of the value of n, ignoring trailing zeros." +inverse,rdf:Property,inverse,,TripleConstraint,xsd:boolean,,,0:1,,,"Constrains the subject of a triple, rather than the object." +languageTag,rdf:Property,language tag,,Language,xsd:string,,,1:1,1:1,,The value used to match the language tag of a language-tagged string. +length,rdf:Property,length,stringFacet,NodeConstraint,xsd:integer,,,0:1,,,The exact length of the value of the cell. +max,rdf:Property,maximum cardinality,,"EachOf,OneOf,TripleConstraint",xsd:integer,,,1:1,,,Maximum number of times this TripleExpression may match; -1 for “*” +maxexclusive,rdf:Property,max exclusive,numericFacet,NodeConstraint,"xsd:integer,xsd:decimal,xsd:double",,,0:1,,,An atomic property that contains a single number that is the maximum valid value (exclusive). +maxinclusive,rdf:Property,max inclusive,numericFacet,NodeConstraint,"xsd:integer,xsd:decimal,xsd:double",,,0:1,,,An atomic property that contains a single number that is the maximum valid value (inclusive). +maxlength,rdf:Property,max length,stringFacet,NodeConstraint,xsd:integer,,,0:1,,,A numeric atomic property that contains a single integer that is the maximum length of the value. +min,rdf:Property,minimum cardinatliy,,"EachOf,OneOf,TripleConstraint",xsd:integer,,,1:1,,,Minimum number of times this TripleExpression may match. +minexclusive,rdf:Property,min exclusive,numericFacet,NodeConstraint,"xsd:integer,xsd:decimal,xsd:double",,,,,,An atomic property that contains a single number that is the minimum valid value (exclusive). +mininclusive,rdf:Property,min inclusive,numericFacet,NodeConstraint,"xsd:integer,xsd:decimal,xsd:double",,,,,,An atomic property that contains a single number that is the minimum valid value (inclusive). +minlength,rdf:Property,min length,stringFacet,NodeConstraint,xsd:integer,,,0:1,,,An atomic property that contains a single integer that is the minimum length of the value. +name,rdf:Property,name,,SemAct,rdfs:Resource,,,1:1,0:N,,Identifier of SemAct extension. +nodeKind,rdf:Property,node kind,,NodeConstraint,NodeKind,@vocab,,0:1,,,"Restiction on the kind of node matched; restricted to the defined instances of NodeKind. One of shex:iri, shex:bnode, shex:literal, or shex:nonliteral." +numericFacet,rdf:Property,,xsFacet,,,@null,,,,,Abstract property of numeric facets on a NodeConstraint. +object,rdf:Property,object,,Annotation,rdfs:Resource,,,1:1,0:N,,The object of an Annotation. +pattern,rdf:Property,pattern,stringFacet,NodeConstraint,xsd:string,,,0:1,,,A regular expression used for matching a value. +predicate,rdf:Property,predicate,,"Annotation,TripleConstraint",rdfs:Resource,,,1:1,0:N,,The predicate of a TripleConstraint or Annotation. +semActs,rdf:Property,semantic action,,"EachOf,OneOf,TripleConstraint",SemAct,,@list,0:N,1:N,,Semantic Actions on this TripleExpression. +shapes,rdf:Property,shapes,,Schema,ShapeDecl,,@list,0:1,1:1,,Shape declarations in this Schema. +shapeExpr,rdf:Property,shape expression,,"ShapeNot,ShapeDecl",ShapeExpression,,,1:1,0:N,,Shape Expression referenced by this shape or shape declaration. +shapeExprs,rdf:Property,shape expressions,shapeExpr,"ShapeAnd,ShapeOr",ShapeExpression,,@list,1:N,0:N,,A list of 2 or more Shape Expressions referenced by this shape. +start,rdf:Property,start,,Schema,ShapeExpression,,,0:1,0:1,,A ShapeExpression matched against the focus node prior to any other mapped expressions. +startActs,rdf:Property,start actions,,Schema,SemAct,,@list,0:N,,,Semantic Actions run on the Schema. +stem,rdf:Property,stem,,"Stem,StemRange","xsd:string,Wildcard",xsd:string,,1:1,0:N,,A stem value used for matching or excluding values. +stringFacet,rdf:Property,,xsFacet,,,@null,,,,,An abstract property of string facets on a NodeConstraint. +totaldigits,rdf:Property,total digits,numericFacet,NodeConstraint,xsd:integer,,,0:1,,,"for ""totaldigits"" constraints, v equals the number of digits in the XML Schema canonical form[xmlschema-2] of the value of n" +values,rdf:Property,values,,NodeConstraint,"rdfs:Resource,Language,Stem,StemRange",,@list,0:N,0:N,,A value restriction on a NodeConstraint. +valueExpr,rdf:Property,value expression,,TripleConstraint,ShapeExpression,,,1:1,0:N,,A ShapeExpression used for matching the object (or subject if inverted) of a TripleConstraint. +xsFacet,rdf:Property,,,NodeConstraint,,@null,,,,,An abstract property of string and numeric facets on a NodeConstraint. +Annotation,rdfs:Class,Annotation,,,,,,,,,Annotations provide a format-independent way to provide additional information about elements in a schema. +EachOf,rdfs:Class,Each Of,TripleExpression,,,,,,,,"A TripleExpression composed of one or more sub-expressions, all of which must match." +NodeConstraint,rdfs:Class,Node Constraint,ShapeExpression,,,,,,,,A constraint on the type or value of an RDF Node. +NodeKind,rdfs:Class,Node Kind,,,,@null,,,,,The set of kinds of RDF Nodes. +OneOf,rdfs:Class,One Of,TripleExpression,,,,,,,,"A TripleExpression composed of one or more sub-expressions, one of which must match." +Schema,rdfs:Class,Schema,,,,,,,,,"A Schema contains the set of shapes, used for matching a focus node." +SemAct,rdfs:Class,Semantic Actions,,,,,,,,,"A list of Semantic Actions that serve as an extension point for Shape Expressions. They appear in lists in Schema's startActs and Shape, OneOf, EachOf and TripleConstraint's semActs." +Shape,rdfs:Class,Shape Or,ShapeExpression,,,,,,,,A shapes schema is captured in a Schema object where shapes is a mapping from shape label to shape expression. +ShapeAnd,rdfs:Class,Shape And,ShapeExpression,,,,,,,,"A ShapeExpression composed of one or more sub-expressions, all of which must match." +ShapeExpression,rdfs:Class,Shape Expression,,,,@null,,,,,The abstract class of Shape Expressions. +ShapeExternal,rdfs:Class,Shape External,ShapeExpression,,,,,,,,A reference to a shape defined in some external Schema. +ShapeNot,rdfs:Class,Shape Not,ShapeExpression,,,,,,,,A ShapeNot is satisfied when it’s included ShapeExpression is not satisfied. +ShapeOr,rdfs:Class,Shape Or,ShapeExpression,,,,,,,,"A ShapeExpression composed of one or more sub-expressions, one of which must match." +Stem,rdfs:Class,Stem,,,,,,,,,Abstract class for Stems +IriStem,rdfs:Class,IRI Stem,Stem,,,,,,,,An IRI prefix used for matching IRIs. +LiteralStem,rdfs:Class,Literal Stem,Stem,,,,,,,,An Literal prefix used for matching Literals. +Language,rdfs:Class,Language,,,,,,,,,An Language tag used for matching Literal Languages. +LanguageStem,rdfs:Class,Language Stem,Stem,,,,,,,,An Language prefix used for matching Literal Languages. +StemRange,rdfs:Class,StemRange,,,,,,,,,Abstract Class for Stem Ranges +IriStemRange,rdfs:Class,IRI StemRange,StemRange,,,,,,,,"An IRI prefix (or wildcard) along with a set of excluded values, used for node matching." +LiteralStemRange,rdfs:Class,Literal StemRange,StemRange,,,,,,,,"An Literal prefix (or wildcard) along with a set of excluded values, used for node matching." +LanguageStemRange,rdfs:Class,Language StemRange,StemRange,,,,,,,,"An Language prefix (or wildcard) along with a set of excluded values, used for node matching." +TripleConstraint,rdfs:Class,Triple Constraint,TripleExpression,,,,,,,,A constraint on a triple having a specific predicate and optionally a shape expression used for matching values. +TripleExpression,rdfs:Class,Triple Expression,,,,@null,,,,,The abstract class of Triple Expressions. +Wildcard,rdfs:Class,Wildcard,,,,,,,,,"Indicates that a stem is a Wildcard, rather than a URI prefix." +annotations,term,,shex:annotation,,,@id,@list,,,,A synonym for the annotation property. +exclusions,term,,shex:exclusion,,,@id,@list,,,,A synonym for the exclusion property. +id,term,,@id,,,,,,,,A synonym for @id. +language,term,,@language,,,,,,,,A synonym for @language. +type,term,,@type,,,,,,,,A synonym for @type. +value,term,,@value,,,,,,,,A synonym for @value. +,rdfs:seeAlso,,https://shexspec.github.io/shape-map/,,,,,,,, +extends,rdf:Property,extends,,Shape,ShapeExpression,,,0:N,0:N,,Base shape expressions for this shape. +QueryMap,rdfs:Class,Query Map,,,,,,,,,"A map of node selectors to shape labels, used to select the nodes to be validated against particular shapes. Node selectors are RDF nodes or triple patterns." +ShapeMap,rdfs:Class,Shape Map,QueryMap,,,,,,,,"A QueryMap in which each node selector is an RDF node; associates RDF nodes with shapes, optionally recording the validation status of each association." +node,rdf:Property,node,,QueryMap,rdfs:Resource,,,1:1,0:N,,"An RDF node, or a triple pattern which is used to select RDF nodes to be validated." +shape,rdf:Property,shape,,QueryMap,ShapeExpression,,,1:1,0:N,,"A ShEx shape expression label identifying the shape expression against which the selected nodes are validated, or the string ""START"" for the schema's start shape expression." +status,rdf:Property,status,,ShapeMap,xsd:string,,,0:1,,,"The validation status of a node/shape association: ""conformant"" or ""nonconformant"". Defaults to ""conformant""." +FOCUS,rdfs:Resource,FOCUS,,,,,,,,,"In a triple pattern used as a node selector, indicates the position (subject or object) of the nodes to be selected. A triple pattern has exactly one focus selector." +_,rdfs:Resource,wildcard,,,,,,,,,"In a triple pattern used as a node selector, a wildcard indicating that the position (subject or object) may hold any value." +ShapeDecl,rdfs:Class,Shape Declaration,,,,,,,,,"Associates a shape expression with a label, and optionally declares it abstract. The shapes in a Schema are ShapeDecls." +abstract,rdf:Property,abstract,,ShapeDecl,xsd:boolean,,,0:1,,,"Declares a ShapeDecl abstract, meaning that every reference to it must also identify at least one non-abstract shape." +imports,rdf:Property,imports,,Schema,rdfs:Resource,,@list,0:N,,,"Schemas imported by this Schema; their shape and triple expression labels are also in scope here."