Fixes compatibility with latest OxIRI version

pull/836/head
Tpt 9 months ago committed by Thomas Tanon
parent ba396bad10
commit 184b8367dc
  1. 44
      Cargo.lock
  2. 27
      Cargo.toml
  3. 2
      lib/oxrdfio/Cargo.toml
  4. 2
      lib/oxrdfxml/Cargo.toml
  5. 16
      lib/oxrdfxml/src/parser.rs
  6. 2
      lib/oxttl/Cargo.toml
  7. 5
      lib/oxttl/src/lexer.rs
  8. 27
      lib/oxttl/src/n3.rs
  9. 507
      lib/oxttl/src/terse.rs

44
Cargo.lock generated

@ -559,9 +559,9 @@ dependencies = [
[[package]]
name = "fastrand"
version = "2.0.1"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984"
[[package]]
name = "flate2"
@ -810,9 +810,9 @@ dependencies = [
[[package]]
name = "json-event-parser"
version = "0.2.0-alpha.2"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b5ddd02379e99769e117ab30d21ad42dcec8ad3c12be77f9a34779e62d46346"
checksum = "f850fafca79ebacd70eab9d80cb75a33aeda38bde8f3dd784c1837cdf0bde631"
dependencies = [
"tokio",
]
@ -1033,9 +1033,9 @@ dependencies = [
[[package]]
name = "oxhttp"
version = "0.2.0-alpha.4"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bc77c20aeeab248232d09bf748d9cf59548190c128efe4edc271a1e4db2ae95"
checksum = "f3cc8fa85d054762930759faa582ba6b6dd0e115156229cdb8cca02b0e0451ae"
dependencies = [
"flate2",
"httparse",
@ -1049,7 +1049,7 @@ dependencies = [
[[package]]
name = "oxigraph"
version = "0.4.0-alpha.5"
version = "0.4.0-alpha.6-dev"
dependencies = [
"codspeed-criterion-compat",
"digest",
@ -1080,7 +1080,7 @@ dependencies = [
[[package]]
name = "oxigraph-cli"
version = "0.4.0-alpha.5"
version = "0.4.0-alpha.6-dev"
dependencies = [
"anyhow",
"assert_cmd",
@ -1099,7 +1099,7 @@ dependencies = [
[[package]]
name = "oxigraph-js"
version = "0.4.0-alpha.5"
version = "0.4.0-alpha.6-dev"
dependencies = [
"console_error_panic_hook",
"js-sys",
@ -1133,9 +1133,9 @@ dependencies = [
[[package]]
name = "oxiri"
version = "0.2.3-alpha.1"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b225dad32cfaa43a960b93f01fa7f87528ac07e794b80f6d9a0153e0222557e2"
checksum = "d05417ee46e2eb40dd9d590b4d67fc2408208b3a48a6b7f71d2bc1d7ce12a3e0"
[[package]]
name = "oxrdf"
@ -1150,7 +1150,7 @@ dependencies = [
[[package]]
name = "oxrdfio"
version = "0.1.0-alpha.4"
version = "0.1.0-alpha.5-dev"
dependencies = [
"oxrdf",
"oxrdfxml",
@ -1161,7 +1161,7 @@ dependencies = [
[[package]]
name = "oxrdfxml"
version = "0.1.0-alpha.4"
version = "0.1.0-alpha.5-dev"
dependencies = [
"oxilangtag",
"oxiri",
@ -1173,7 +1173,7 @@ dependencies = [
[[package]]
name = "oxrocksdb-sys"
version = "0.4.0-alpha.5"
version = "0.4.0-alpha.6-dev"
dependencies = [
"bindgen",
"cc",
@ -1191,7 +1191,7 @@ dependencies = [
[[package]]
name = "oxttl"
version = "0.1.0-alpha.4"
version = "0.1.0-alpha.5-dev"
dependencies = [
"memchr",
"oxilangtag",
@ -1347,9 +1347,9 @@ dependencies = [
[[package]]
name = "prettyplease"
version = "0.2.16"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5"
checksum = "8d3928fb5db768cb86f891ff014f0144589297e3c6a1aba6ed7cecfdace270c7"
dependencies = [
"proc-macro2",
"syn",
@ -1429,7 +1429,7 @@ dependencies = [
[[package]]
name = "pyoxigraph"
version = "0.4.0-alpha.5"
version = "0.4.0-alpha.6-dev"
dependencies = [
"oxigraph",
"pyo3",
@ -1486,9 +1486,9 @@ dependencies = [
[[package]]
name = "rayon"
version = "1.9.0"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"either",
"rayon-core",
@ -1820,9 +1820,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "syn"
version = "2.0.53"
version = "2.0.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032"
checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0"
dependencies = [
"proc-macro2",
"quote",

@ -19,7 +19,7 @@ members = [
resolver = "2"
[workspace.package]
version = "0.4.0-alpha.5"
version = "0.4.0-alpha.6-dev"
authors = ["Tpt <thomas@pellissier-tanon.fr>"]
license = "MIT OR Apache-2.0"
edition = "2021"
@ -45,9 +45,9 @@ json-event-parser = "0.2.0-alpha.2"
libc = "0.2.147"
md-5 = "0.10"
memchr = "2.5"
oxhttp = "0.2.0-alpha.4"
oxhttp = "0.2.0"
oxilangtag = "0.1"
oxiri = "0.2.3-alpha.1"
oxiri = "0.2.3"
peg = "0.8"
pkg-config = "0.3.25"
predicates = ">=2.0, <4.0"
@ -68,17 +68,16 @@ wasm-bindgen = "0.2.83"
zstd = ">=0.12, <0.14"
# Internal dependencies
oxigraph = { version = "0.4.0-alpha.4", path = "lib/oxigraph" }
oxrdf = { version = "0.2.0-alpha.4", path = "lib/oxrdf" }
oxrdfio = { version = "0.1.0-alpha.4", path = "lib/oxrdfio" }
oxrdfxml = { version = "0.1.0-alpha.4", path = "lib/oxrdfxml" }
oxrocksdb-sys = { version = "0.4.0-alpha.3", path = "./oxrocksdb-sys" }
oxsdatatypes = { version = "0.2.0-alpha.1", path = "lib/oxsdatatypes" }
oxttl = { version = "0.1.0-alpha.4", path = "lib/oxttl" }
sparesults = { version = "0.2.0-alpha.4", path = "lib/sparesults" }
spargebra = { version = "0.3.0-alpha.4", path = "lib/spargebra" }
sparopt = { version = "0.1.0-alpha.4", path = "lib/sparopt" }
sparql-smith = { version = "0.1.0-alpha.5", path = "lib/sparql-smith" }
oxigraph = { version = "=0.4.0-alpha.6-dev", path = "lib/oxigraph" }
oxrdf = { version = "=0.2.0-alpha.4", path = "lib/oxrdf" }
oxrdfio = { version = "=0.1.0-alpha.5-dev", path = "lib/oxrdfio" }
oxrdfxml = { version = "=0.1.0-alpha.5-dev", path = "lib/oxrdfxml" }
oxrocksdb-sys = { version = "=0.4.0-alpha.6-dev", path = "./oxrocksdb-sys" }
oxsdatatypes = { version = "=0.2.0-alpha.1", path = "lib/oxsdatatypes" }
oxttl = { version = "=0.1.0-alpha.5-dev", path = "lib/oxttl" }
sparesults = { version = "=0.2.0-alpha.4", path = "lib/sparesults" }
spargebra = { version = "=0.3.0-alpha.4", path = "lib/spargebra" }
sparopt = { version = "=0.1.0-alpha.4", path = "lib/sparopt" }
[workspace.lints.rust]
absolute_paths_not_starting_with_crate = "warn"

@ -1,6 +1,6 @@
[package]
name = "oxrdfio"
version = "0.1.0-alpha.4"
version = "0.1.0-alpha.5-dev"
authors.workspace = true
license.workspace = true
readme = "README.md"

@ -1,6 +1,6 @@
[package]
name = "oxrdfxml"
version = "0.1.0-alpha.4"
version = "0.1.0-alpha.5-dev"
authors.workspace = true
license.workspace = true
readme = "README.md"

@ -586,16 +586,13 @@ impl<R> RdfXmlReader<R> {
});
} else if attribute.key.as_ref() == b"xml:base" {
let iri = self.convert_attribute(&attribute)?;
base_iri = Some(
if self.unchecked {
base_iri = Some(if self.unchecked {
Iri::parse_unchecked(iri.clone())
} else {
Iri::parse(iri.clone())
}
.map_err(|error| {
Iri::parse(iri.clone()).map_err(|error| {
RdfXmlSyntaxError(SyntaxErrorKind::InvalidIri { iri, error })
})?,
)
})?
})
} else {
// We ignore other xml attributes
}
@ -1175,14 +1172,13 @@ impl<R> RdfXmlReader<R> {
if self.unchecked {
base_iri.resolve_unchecked(&relative_iri)
} else {
base_iri.resolve(&relative_iri)
}
.map_err(|error| {
base_iri.resolve(&relative_iri).map_err(|error| {
RdfXmlSyntaxError(SyntaxErrorKind::InvalidIri {
iri: relative_iri,
error,
})
})?
}
.into_inner(),
))
} else {

@ -1,6 +1,6 @@
[package]
name = "oxttl"
version = "0.1.0-alpha.4"
version = "0.1.0-alpha.5-dev"
authors.workspace = true
license.workspace = true
readme = "README.md"

@ -219,9 +219,10 @@ impl N3Lexer {
if self.unchecked {
base_iri.resolve_unchecked(&iri)
} else {
base_iri.resolve(&iri)
}
base_iri
.resolve(&iri)
.map_err(|e| (position, e.to_string()))?
}
.into_inner()
} else if self.unchecked {
iri

@ -785,17 +785,11 @@ impl RuleRecognizer for N3Recognizer {
}
errors.push("A dot is expected at the end of N3 statements".into());
}
N3State::BaseExpectIri => return match token {
N3Token::IriRef(iri) => {
match Iri::parse_unchecked(iri) {
Ok(iri) => {
context.lexer_options.base_iri = Some(iri);
N3State::BaseExpectIri => return if let N3Token::IriRef(iri) = token {
context.lexer_options.base_iri = Some(Iri::parse_unchecked(iri));
self
}
Err(e) => self.error(errors, format!("Invalid base IRI: {e}"))
}
}
_ => self.error(errors, "The BASE keyword should be followed by an IRI"),
} else {
self.error(errors, "The BASE keyword should be followed by an IRI")
},
N3State::PrefixExpectPrefix => return match token {
N3Token::PrefixedName { prefix, local, .. } if local.is_empty() => {
@ -806,17 +800,10 @@ impl RuleRecognizer for N3Recognizer {
self.error(errors, "The PREFIX keyword should be followed by a prefix like 'ex:'")
}
},
N3State::PrefixExpectIri { name } => return match token {
N3Token::IriRef(iri) => {
match Iri::parse_unchecked(iri) {
Ok(iri) => {
context.prefixes.insert(name, iri);
N3State::PrefixExpectIri { name } => return if let N3Token::IriRef(iri) = token {
context.prefixes.insert(name, Iri::parse_unchecked(iri));
self
}
Err(e) => self.error(errors, format!("Invalid prefix IRI: {e}"))
}
}
_ => self.error(errors, "The PREFIX declaration should be followed by a prefix and its value as an IRI"),
} else { self.error(errors, "The PREFIX declaration should be followed by a prefix and its value as an IRI")
},
// [9] triples ::= subject predicateObjectList?
N3State::Triples => {

@ -86,88 +86,99 @@ impl RuleRecognizer for TriGRecognizer {
self.stack.push(TriGState::BaseExpectIri);
self
}
N3Token::PlainKeyword(k) if k.eq_ignore_ascii_case("graph") && context.with_graph_name => {
N3Token::PlainKeyword(k)
if k.eq_ignore_ascii_case("graph") && context.with_graph_name =>
{
self.stack.push(TriGState::WrappedGraph);
self.stack.push(TriGState::GraphName);
self
}
N3Token::Punctuation("{") if context.with_graph_name => {
self.stack.push(TriGState::WrappedGraph);
self.recognize_next(token, context,results, errors)
self.recognize_next(token, context, results, errors)
}
_ => {
self.stack.push(TriGState::TriplesOrGraph);
self.recognize_next(token, context,results, errors)
self.recognize_next(token, context, results, errors)
}
}
}
},
TriGState::ExpectDot => {
self.cur_subject.pop();
if token == N3Token::Punctuation(".") {
self
} else {
errors.push("A dot is expected at the end of statements".into());
self.recognize_next(token, context,results, errors)
self.recognize_next(token, context, results, errors)
}
},
TriGState::BaseExpectIri => match token {
N3Token::IriRef(iri) => {
match Iri::parse_unchecked(iri) {
Ok(iri) => {
context.lexer_options.base_iri = Some(iri);
self
}
Err(e) => self.error(errors, format!("Invalid base IRI: {e}"))
TriGState::BaseExpectIri => {
if let N3Token::IriRef(iri) = token {
context.lexer_options.base_iri = Some(Iri::parse_unchecked(iri));
self
} else {
self.error(errors, "The BASE keyword should be followed by an IRI")
}
}
_ => self.error(errors, "The BASE keyword should be followed by an IRI"),
},
TriGState::PrefixExpectPrefix => match token {
N3Token::PrefixedName { prefix, local, .. } if local.is_empty() => {
self.stack.push(TriGState::PrefixExpectIri { name: prefix.to_owned() });
self.stack.push(TriGState::PrefixExpectIri {
name: prefix.to_owned(),
});
self
}
_ => {
self.error(errors, "The PREFIX keyword should be followed by a prefix like 'ex:'")
}
_ => self.error(
errors,
"The PREFIX keyword should be followed by a prefix like 'ex:'",
),
},
TriGState::PrefixExpectIri { name } => match token {
N3Token::IriRef(iri) => {
match Iri::parse_unchecked(iri) {
Ok(iri) => {
context.prefixes.insert(name, iri);
TriGState::PrefixExpectIri { name } => {
if let N3Token::IriRef(iri) = token {
context.prefixes.insert(name, Iri::parse_unchecked(iri));
self
} else {
self.error(errors, "The PREFIX declaration should be followed by a prefix and its value as an IRI")
}
}
Err(e) => self.error(errors, format!("Invalid prefix IRI: {e}"))
} }
_ => self.error(errors, "The PREFIX declaration should be followed by a prefix and its value as an IRI"),
},
// [3g] triplesOrGraph ::= labelOrSubject ( wrappedGraph | predicateObjectList '.' ) | quotedTriple predicateObjectList '.'
// [4g] triples2 ::= blankNodePropertyList predicateObjectList? '.' | collection predicateObjectList '.'
TriGState::TriplesOrGraph => match token {
N3Token::IriRef(iri) => {
self.stack.push(TriGState::WrappedGraphOrPredicateObjectList {
term: NamedNode::new_unchecked(iri).into()
self.stack
.push(TriGState::WrappedGraphOrPredicateObjectList {
term: NamedNode::new_unchecked(iri).into(),
});
self
}
N3Token::PrefixedName { prefix, local, might_be_invalid_iri } => match resolve_local_name(prefix, &local, might_be_invalid_iri, &context.prefixes) {
N3Token::PrefixedName {
prefix,
local,
might_be_invalid_iri,
} => match resolve_local_name(
prefix,
&local,
might_be_invalid_iri,
&context.prefixes,
) {
Ok(t) => {
self.stack.push(TriGState::WrappedGraphOrPredicateObjectList {
term: t.into()
self.stack
.push(TriGState::WrappedGraphOrPredicateObjectList {
term: t.into(),
});
self
},
Err(e) => self.error(errors, e)
}
Err(e) => self.error(errors, e),
},
N3Token::BlankNodeLabel(label) => {
self.stack.push(TriGState::WrappedGraphOrPredicateObjectList {
term: BlankNode::new_unchecked(label).into()
self.stack
.push(TriGState::WrappedGraphOrPredicateObjectList {
term: BlankNode::new_unchecked(label).into(),
});
self
}
N3Token::Punctuation("[") => {
self.stack.push(TriGState::WrappedGraphBlankNodePropertyListCurrent);
self.stack
.push(TriGState::WrappedGraphBlankNodePropertyListCurrent);
self
}
N3Token::Punctuation("(") => {
@ -186,10 +197,8 @@ impl RuleRecognizer for TriGRecognizer {
self.stack.push(TriGState::QuotedSubject);
self
}
_ => {
self.error(errors, "TOKEN is not a valid subject or graph name")
}
}
_ => self.error(errors, "TOKEN is not a valid subject or graph name"),
},
TriGState::WrappedGraphOrPredicateObjectList { term } => {
if token == N3Token::Punctuation("{") && context.with_graph_name {
self.cur_graph = term.into();
@ -199,11 +208,13 @@ impl RuleRecognizer for TriGRecognizer {
self.stack.push(TriGState::ExpectDot);
self.stack.push(TriGState::PredicateObjectList);
}
self.recognize_next(token, context,results, errors)
self.recognize_next(token, context, results, errors)
}
TriGState::WrappedGraphBlankNodePropertyListCurrent => if token == N3Token::Punctuation("]") {
self.stack.push(TriGState::WrappedGraphOrPredicateObjectList {
term: BlankNode::default().into()
TriGState::WrappedGraphBlankNodePropertyListCurrent => {
if token == N3Token::Punctuation("]") {
self.stack
.push(TriGState::WrappedGraphOrPredicateObjectList {
term: BlankNode::default().into(),
});
self
} else {
@ -211,21 +222,28 @@ impl RuleRecognizer for TriGRecognizer {
self.stack.push(TriGState::ExpectDot);
self.stack.push(TriGState::SubjectBlankNodePropertyListEnd);
self.stack.push(TriGState::PredicateObjectList);
self.recognize_next(token, context,results, errors)
self.recognize_next(token, context, results, errors)
}
}
TriGState::SubjectBlankNodePropertyListEnd => if token == N3Token::Punctuation("]") {
self.stack.push(TriGState::SubjectBlankNodePropertyListAfter );
TriGState::SubjectBlankNodePropertyListEnd => {
if token == N3Token::Punctuation("]") {
self.stack
.push(TriGState::SubjectBlankNodePropertyListAfter);
self
} else {
errors.push("blank node property lists should end with a ']'".into());
self.stack.push(TriGState::SubjectBlankNodePropertyListAfter );
self.recognize_next(token, context,results, errors)
self.stack
.push(TriGState::SubjectBlankNodePropertyListAfter);
self.recognize_next(token, context, results, errors)
}
TriGState::SubjectBlankNodePropertyListAfter => if matches!(token, N3Token::Punctuation("." | "}")) {
self.recognize_next(token, context,results, errors)
}
TriGState::SubjectBlankNodePropertyListAfter => {
if matches!(token, N3Token::Punctuation("." | "}")) {
self.recognize_next(token, context, results, errors)
} else {
self.stack.push(TriGState::PredicateObjectList);
self.recognize_next(token, context,results, errors)
self.recognize_next(token, context, results, errors)
}
}
TriGState::SubjectCollectionBeginning => {
if let N3Token::Punctuation(")") = token {
@ -238,20 +256,15 @@ impl RuleRecognizer for TriGRecognizer {
self.cur_predicate.push(rdf::FIRST.into());
self.stack.push(TriGState::SubjectCollectionPossibleEnd);
self.stack.push(TriGState::Object);
self.recognize_next(token, context,results, errors)
self.recognize_next(token, context, results, errors)
}
}
},
TriGState::SubjectCollectionPossibleEnd => {
let old = self.cur_subject.pop().unwrap();
self.cur_object.pop();
if let N3Token::Punctuation(")") = token {
self.cur_predicate.pop();
results.push(Quad::new(
old,
rdf::REST,
rdf::NIL,
self.cur_graph.clone()
));
results.push(Quad::new(old, rdf::REST, rdf::NIL, self.cur_graph.clone()));
self
} else {
let new = BlankNode::default();
@ -259,37 +272,39 @@ impl RuleRecognizer for TriGRecognizer {
old,
rdf::REST,
new.clone(),
self.cur_graph.clone()
self.cur_graph.clone(),
));
self.cur_subject.push(new.into());
self.stack.push(TriGState::ObjectCollectionPossibleEnd);
self.stack.push(TriGState::Object);
self.recognize_next(token, context,results, errors)
self.recognize_next(token, context, results, errors)
}
}
// [5g] wrappedGraph ::= '{' triplesBlock? '}'
// [6g] triplesBlock ::= triples ('.' triplesBlock?)?
TriGState::WrappedGraph => if token == N3Token::Punctuation("{") {
TriGState::WrappedGraph => {
if token == N3Token::Punctuation("{") {
self.stack.push(TriGState::WrappedGraphPossibleEnd);
self.stack.push(TriGState::Triples);
self
} else {
self.error(errors, "The GRAPH keyword should be followed by a graph name and a value in '{'")
},
}
}
TriGState::WrappedGraphPossibleEnd => {
self.cur_subject.pop();
match token {
N3Token::Punctuation("}") => {
self
}
N3Token::Punctuation("}") => self,
N3Token::Punctuation(".") => {
self.stack.push(TriGState::WrappedGraphPossibleEnd);
self.stack.push(TriGState::Triples);
self
}
_ => {
errors.push("A '}' or a '.' is expected at the end of a graph block".into());
self.recognize_next(token, context,results, errors)
errors.push(
"A '}' or a '.' is expected at the end of a graph block".into(),
);
self.recognize_next(token, context, results, errors)
}
}
}
@ -297,11 +312,12 @@ impl RuleRecognizer for TriGRecognizer {
// [10] subject ::= iri | BlankNode | collection | quotedTriple
TriGState::Triples => match token {
N3Token::Punctuation("}") => {
self.recognize_next(token, context,results, errors) // Early end
},
self.recognize_next(token, context, results, errors) // Early end
}
N3Token::Punctuation("[") => {
self.cur_subject.push(BlankNode::default().into());
self.stack.push(TriGState::TriplesBlankNodePropertyListCurrent);
self.stack
.push(TriGState::TriplesBlankNodePropertyListCurrent);
self
}
N3Token::IriRef(iri) => {
@ -309,16 +325,26 @@ impl RuleRecognizer for TriGRecognizer {
self.stack.push(TriGState::PredicateObjectList);
self
}
N3Token::PrefixedName { prefix, local, might_be_invalid_iri } => match resolve_local_name(prefix, &local, might_be_invalid_iri, &context.prefixes) {
N3Token::PrefixedName {
prefix,
local,
might_be_invalid_iri,
} => match resolve_local_name(
prefix,
&local,
might_be_invalid_iri,
&context.prefixes,
) {
Ok(t) => {
self.cur_subject.push(t.into());
self.stack.push(TriGState::PredicateObjectList);
self
},
Err(e) => self.error(errors, e)
}
Err(e) => self.error(errors, e),
},
N3Token::BlankNodeLabel(label) => {
self.cur_subject.push(BlankNode::new_unchecked(label).into());
self.cur_subject
.push(BlankNode::new_unchecked(label).into());
self.stack.push(TriGState::PredicateObjectList);
self
}
@ -336,17 +362,17 @@ impl RuleRecognizer for TriGRecognizer {
self.stack.push(TriGState::QuotedSubject);
self
}
_ => {
self.error(errors, "TOKEN is not a valid RDF subject")
}
_ => self.error(errors, "TOKEN is not a valid RDF subject"),
},
TriGState::TriplesBlankNodePropertyListCurrent => if token == N3Token::Punctuation("]") {
TriGState::TriplesBlankNodePropertyListCurrent => {
if token == N3Token::Punctuation("]") {
self.stack.push(TriGState::PredicateObjectList);
self
} else {
self.stack.push(TriGState::SubjectBlankNodePropertyListEnd);
self.stack.push(TriGState::PredicateObjectList);
self.recognize_next(token, context,results, errors)
self.recognize_next(token, context, results, errors)
}
}
// [7g] labelOrSubject ::= iri | BlankNode
TriGState::GraphName => match token {
@ -354,13 +380,22 @@ impl RuleRecognizer for TriGRecognizer {
self.cur_graph = NamedNode::new_unchecked(iri).into();
self
}
N3Token::PrefixedName { prefix, local, might_be_invalid_iri } => match resolve_local_name(prefix, &local, might_be_invalid_iri, &context.prefixes) {
N3Token::PrefixedName {
prefix,
local,
might_be_invalid_iri,
} => match resolve_local_name(
prefix,
&local,
might_be_invalid_iri,
&context.prefixes,
) {
Ok(t) => {
self.cur_graph = t.into();
self
},
Err(e) => self.error(errors, e)
}
Err(e) => self.error(errors, e),
},
N3Token::BlankNodeLabel(label) => {
self.cur_graph = BlankNode::new_unchecked(label).into();
self
@ -369,64 +404,67 @@ impl RuleRecognizer for TriGRecognizer {
self.stack.push(TriGState::GraphNameAnonEnd);
self
}
_ => {
self.error(errors, "TOKEN is not a valid graph name")
}
}
TriGState::GraphNameAnonEnd => if token == N3Token::Punctuation("]") {
_ => self.error(errors, "TOKEN is not a valid graph name"),
},
TriGState::GraphNameAnonEnd => {
if token == N3Token::Punctuation("]") {
self.cur_graph = BlankNode::default().into();
self
} else {
self.error(errors, "Anonymous blank node with a property list are not allowed as graph name")
}
}
// [7] predicateObjectList ::= verb objectList (';' (verb objectList)?)*
TriGState::PredicateObjectList => {
self.stack.push(TriGState::PredicateObjectListEnd);
self.stack.push(TriGState::ObjectsList);
self.stack.push(TriGState::Verb);
self.recognize_next(token, context,results, errors)
},
self.recognize_next(token, context, results, errors)
}
TriGState::PredicateObjectListEnd => {
self.cur_predicate.pop();
if token == N3Token::Punctuation(";") {
self.stack.push(TriGState::PredicateObjectListPossibleContinuation);
self.stack
.push(TriGState::PredicateObjectListPossibleContinuation);
self
} else {
self.recognize_next(token, context,results, errors)
self.recognize_next(token, context, results, errors)
}
},
TriGState::PredicateObjectListPossibleContinuation => if token == N3Token::Punctuation(";") {
self.stack.push(TriGState::PredicateObjectListPossibleContinuation);
}
TriGState::PredicateObjectListPossibleContinuation => {
if token == N3Token::Punctuation(";") {
self.stack
.push(TriGState::PredicateObjectListPossibleContinuation);
self
} else if matches!(token, N3Token::Punctuation("." | "}" | "]")) {
self.recognize_next(token, context,results, errors)
self.recognize_next(token, context, results, errors)
} else {
self.stack.push(TriGState::PredicateObjectListEnd);
self.stack.push(TriGState::ObjectsList);
self.stack.push(TriGState::Verb);
self.recognize_next(token, context,results, errors)
},
self.recognize_next(token, context, results, errors)
}
}
// [8] objectList ::= object annotation? ( ',' object annotation? )*
// [30t] annotation ::= '{|' predicateObjectList '|}'
TriGState::ObjectsList => {
self.stack.push(TriGState::ObjectsListEnd);
self.stack.push(TriGState::Object);
self.recognize_next(token, context,results, errors)
self.recognize_next(token, context, results, errors)
}
TriGState::ObjectsListEnd => {
match token {
TriGState::ObjectsListEnd => match token {
N3Token::Punctuation(",") => {
self.cur_object.pop();
self.stack.push(TriGState::ObjectsListEnd);
self.stack.push(TriGState::Object);
self
},
}
#[cfg(feature = "rdf-star")]
N3Token::Punctuation("{|") => {
let triple = Triple::new(
self.cur_subject.last().unwrap().clone(),
self.cur_predicate.last().unwrap().clone(),
self.cur_object.pop().unwrap()
self.cur_object.pop().unwrap(),
);
self.cur_subject.push(triple.into());
self.stack.push(TriGState::AnnotationEnd);
@ -435,8 +473,7 @@ impl RuleRecognizer for TriGRecognizer {
}
_ => {
self.cur_object.pop();
self.recognize_next(token, context,results, errors)
}
self.recognize_next(token, context, results, errors)
}
},
#[cfg(feature = "rdf-star")]
@ -448,15 +485,17 @@ impl RuleRecognizer for TriGRecognizer {
} else {
self.error(errors, "Annotations should end with '|}'")
}
},
}
#[cfg(feature = "rdf-star")]
TriGState::ObjectsListAfterAnnotation => if token == N3Token::Punctuation(",") {
TriGState::ObjectsListAfterAnnotation => {
if token == N3Token::Punctuation(",") {
self.stack.push(TriGState::ObjectsListEnd);
self.stack.push(TriGState::Object);
self
} else {
self.recognize_next(token, context,results, errors)
},
self.recognize_next(token, context, results, errors)
}
}
// [9] verb ::= predicate | 'a'
// [11] predicate ::= iri
TriGState::Verb => match token {
@ -468,17 +507,24 @@ impl RuleRecognizer for TriGRecognizer {
self.cur_predicate.push(NamedNode::new_unchecked(iri));
self
}
N3Token::PrefixedName { prefix, local, might_be_invalid_iri } => match resolve_local_name(prefix, &local, might_be_invalid_iri, &context.prefixes) {
N3Token::PrefixedName {
prefix,
local,
might_be_invalid_iri,
} => match resolve_local_name(
prefix,
&local,
might_be_invalid_iri,
&context.prefixes,
) {
Ok(t) => {
self.cur_predicate.push(t);
self
},
Err(e) => self.error(errors, e)
}
_ => {
self.error(errors, "TOKEN is not a valid predicate")
}
}
Err(e) => self.error(errors, e),
},
_ => self.error(errors, "TOKEN is not a valid predicate"),
},
// [12] object ::= iri | BlankNode | collection | blankNodePropertyList | literal | quotedTriple
// [13] literal ::= RDFLiteral | NumericLiteral | BooleanLiteral
// [14] blank ::= BlankNode | collection
@ -497,21 +543,31 @@ impl RuleRecognizer for TriGRecognizer {
self.emit_quad(results);
self
}
N3Token::PrefixedName { prefix, local, might_be_invalid_iri } => match resolve_local_name(prefix, &local, might_be_invalid_iri, &context.prefixes) {
N3Token::PrefixedName {
prefix,
local,
might_be_invalid_iri,
} => match resolve_local_name(
prefix,
&local,
might_be_invalid_iri,
&context.prefixes,
) {
Ok(t) => {
self.cur_object.push(t.into());
self.emit_quad(results);
self
},
Err(e) => self.error(errors, e)
}
Err(e) => self.error(errors, e),
},
N3Token::BlankNodeLabel(label) => {
self.cur_object.push(BlankNode::new_unchecked(label).into());
self.emit_quad(results);
self
}
N3Token::Punctuation("[") => {
self.stack.push(TriGState::ObjectBlankNodePropertyListCurrent);
self.stack
.push(TriGState::ObjectBlankNodePropertyListCurrent);
self
}
N3Token::Punctuation("(") => {
@ -519,48 +575,53 @@ impl RuleRecognizer for TriGRecognizer {
self
}
N3Token::String(value) => {
self.stack.push(TriGState::LiteralPossibleSuffix { value, emit: true });
self.stack
.push(TriGState::LiteralPossibleSuffix { value, emit: true });
self
}
N3Token::Integer(v) => {
self.cur_object.push(Literal::new_typed_literal(v, xsd::INTEGER).into());
self.cur_object
.push(Literal::new_typed_literal(v, xsd::INTEGER).into());
self.emit_quad(results);
self
}
N3Token::Decimal(v) => {
self.cur_object.push(Literal::new_typed_literal(v, xsd::DECIMAL).into());
self.cur_object
.push(Literal::new_typed_literal(v, xsd::DECIMAL).into());
self.emit_quad(results);
self
}
N3Token::Double(v) => {
self.cur_object.push(Literal::new_typed_literal(v, xsd::DOUBLE).into());
self.cur_object
.push(Literal::new_typed_literal(v, xsd::DOUBLE).into());
self.emit_quad(results);
self
}
N3Token::PlainKeyword("true") => {
self.cur_object.push(Literal::new_typed_literal("true", xsd::BOOLEAN).into());
self.cur_object
.push(Literal::new_typed_literal("true", xsd::BOOLEAN).into());
self.emit_quad(results);
self
}
N3Token::PlainKeyword("false") => {
self.cur_object.push(Literal::new_typed_literal("false", xsd::BOOLEAN).into());
self.cur_object
.push(Literal::new_typed_literal("false", xsd::BOOLEAN).into());
self.emit_quad(results);
self
}
#[cfg(feature = "rdf-star")]
N3Token::Punctuation("<<") if context.with_quoted_triples => {
self.stack.push(TriGState::ObjectQuotedTripleEnd { emit: true });
self.stack
.push(TriGState::ObjectQuotedTripleEnd { emit: true });
self.stack.push(TriGState::QuotedObject);
self.stack.push(TriGState::Verb);
self.stack.push(TriGState::QuotedSubject);
self
}
_ => {
self.error(errors, "TOKEN is not a valid RDF object")
}
}
TriGState::ObjectBlankNodePropertyListCurrent => if token == N3Token::Punctuation("]") {
_ => self.error(errors, "TOKEN is not a valid RDF object"),
},
TriGState::ObjectBlankNodePropertyListCurrent => {
if token == N3Token::Punctuation("]") {
self.cur_object.push(BlankNode::default().into());
self.emit_quad(results);
self
@ -568,16 +629,20 @@ impl RuleRecognizer for TriGRecognizer {
self.cur_subject.push(BlankNode::default().into());
self.stack.push(TriGState::ObjectBlankNodePropertyListEnd);
self.stack.push(TriGState::PredicateObjectList);
self.recognize_next(token, context,results, errors)
self.recognize_next(token, context, results, errors)
}
TriGState::ObjectBlankNodePropertyListEnd => if token == N3Token::Punctuation("]") {
}
TriGState::ObjectBlankNodePropertyListEnd => {
if token == N3Token::Punctuation("]") {
self.cur_object.push(self.cur_subject.pop().unwrap().into());
self.emit_quad(results);
self
} else {
self.error(errors, "blank node property lists should end with a ']'")
}
TriGState::ObjectCollectionBeginning => if let N3Token::Punctuation(")") = token {
}
TriGState::ObjectCollectionBeginning => {
if let N3Token::Punctuation(")") = token {
self.cur_object.push(rdf::NIL.into());
self.emit_quad(results);
self
@ -589,91 +654,109 @@ impl RuleRecognizer for TriGRecognizer {
self.cur_predicate.push(rdf::FIRST.into());
self.stack.push(TriGState::ObjectCollectionPossibleEnd);
self.stack.push(TriGState::Object);
self.recognize_next(token, context,results, errors)
},
self.recognize_next(token, context, results, errors)
}
}
TriGState::ObjectCollectionPossibleEnd => {
let old = self.cur_subject.pop().unwrap();
self.cur_object.pop();
if let N3Token::Punctuation(")") = token {
self.cur_predicate.pop();
results.push(Quad::new(old,
rdf::REST,
rdf::NIL,
self.cur_graph.clone()
));
results.push(Quad::new(old, rdf::REST, rdf::NIL, self.cur_graph.clone()));
self
}else {
} else {
let new = BlankNode::default();
results.push(Quad::new(old,
results.push(Quad::new(
old,
rdf::REST,
new.clone(),
self.cur_graph.clone()
self.cur_graph.clone(),
));
self.cur_subject.push(new.into());
self.stack.push(TriGState::ObjectCollectionPossibleEnd);
self.stack.push(TriGState::Object);
self.recognize_next(token, context,results, errors)
self.recognize_next(token, context, results, errors)
}
}
TriGState::LiteralPossibleSuffix { value, emit } => {
match token {
TriGState::LiteralPossibleSuffix { value, emit } => match token {
N3Token::LangTag(lang) => {
self.cur_object.push(Literal::new_language_tagged_literal_unchecked(value, lang.to_ascii_lowercase()).into());
self.cur_object.push(
Literal::new_language_tagged_literal_unchecked(
value,
lang.to_ascii_lowercase(),
)
.into(),
);
if emit {
self.emit_quad(results);
}
self
},
}
N3Token::Punctuation("^^") => {
self.stack.push(TriGState::LiteralExpectDatatype { value, emit });
self.stack
.push(TriGState::LiteralExpectDatatype { value, emit });
self
}
_ => {
self.cur_object.push(Literal::new_simple_literal(value).into());
self.cur_object
.push(Literal::new_simple_literal(value).into());
if emit {
self.emit_quad(results);
}
self.recognize_next(token, context,results, errors)
}
}
self.recognize_next(token, context, results, errors)
}
TriGState::LiteralExpectDatatype { value, emit } => {
match token {
},
TriGState::LiteralExpectDatatype { value, emit } => match token {
N3Token::IriRef(datatype) => {
self.cur_object.push(Literal::new_typed_literal(value, NamedNode::new_unchecked(datatype)).into());
self.cur_object.push(
Literal::new_typed_literal(value, NamedNode::new_unchecked(datatype))
.into(),
);
if emit {
self.emit_quad(results);
}
self
},
N3Token::PrefixedName { prefix, local, might_be_invalid_iri } => match resolve_local_name(prefix, &local, might_be_invalid_iri, &context.prefixes) {
}
N3Token::PrefixedName {
prefix,
local,
might_be_invalid_iri,
} => match resolve_local_name(
prefix,
&local,
might_be_invalid_iri,
&context.prefixes,
) {
Ok(t) => {
self.cur_object.push(Literal::new_typed_literal(value, t).into());
self.cur_object
.push(Literal::new_typed_literal(value, t).into());
if emit {
self.emit_quad(results);
}
self
},
Err(e) => self.error(errors, e)
}
_ => {
self.error(errors, "Expecting a datatype IRI after ^^, found TOKEN").recognize_next(token, context, results, errors)
}
}
}
Err(e) => self.error(errors, e),
},
_ => self
.error(errors, "Expecting a datatype IRI after ^^, found TOKEN")
.recognize_next(token, context, results, errors),
},
// [27t] quotedTriple ::= '<<' qtSubject verb qtObject '>>'
#[cfg(feature = "rdf-star")]
TriGState::SubjectQuotedTripleEnd => {
let triple = Triple::new(
self.cur_subject.pop().unwrap(),
self.cur_predicate.pop().unwrap(),
self.cur_object.pop().unwrap()
self.cur_object.pop().unwrap(),
);
self.cur_subject.push(triple.into());
if token == N3Token::Punctuation(">>") {
self
} else {
self.error(errors, "Expecting '>>' to close a quoted triple, found TOKEN")
self.error(
errors,
"Expecting '>>' to close a quoted triple, found TOKEN",
)
}
}
#[cfg(feature = "rdf-star")]
@ -681,7 +764,7 @@ impl RuleRecognizer for TriGRecognizer {
let triple = Triple::new(
self.cur_subject.pop().unwrap(),
self.cur_predicate.pop().unwrap(),
self.cur_object.pop().unwrap()
self.cur_object.pop().unwrap(),
);
self.cur_object.push(triple.into());
if emit {
@ -690,7 +773,10 @@ impl RuleRecognizer for TriGRecognizer {
if token == N3Token::Punctuation(">>") {
self
} else {
self.error(errors, "Expecting '>>' to close a quoted triple, found TOKEN")
self.error(
errors,
"Expecting '>>' to close a quoted triple, found TOKEN",
)
}
}
// [28t] qtSubject ::= iri | BlankNode | quotedTriple
@ -705,15 +791,25 @@ impl RuleRecognizer for TriGRecognizer {
self.cur_subject.push(NamedNode::new_unchecked(iri).into());
self
}
N3Token::PrefixedName { prefix, local, might_be_invalid_iri } => match resolve_local_name(prefix, &local, might_be_invalid_iri, &context.prefixes) {
N3Token::PrefixedName {
prefix,
local,
might_be_invalid_iri,
} => match resolve_local_name(
prefix,
&local,
might_be_invalid_iri,
&context.prefixes,
) {
Ok(t) => {
self.cur_subject.push(t.into());
self
},
Err(e) => self.error(errors, e)
}
Err(e) => self.error(errors, e),
},
N3Token::BlankNodeLabel(label) => {
self.cur_subject.push(BlankNode::new_unchecked(label).into());
self.cur_subject
.push(BlankNode::new_unchecked(label).into());
self
}
N3Token::Punctuation("<<") => {
@ -723,8 +819,11 @@ impl RuleRecognizer for TriGRecognizer {
self.stack.push(TriGState::QuotedSubject);
self
}
_ => self.error(errors, "TOKEN is not a valid RDF quoted triple subject: TOKEN")
}
_ => self.error(
errors,
"TOKEN is not a valid RDF quoted triple subject: TOKEN",
),
},
// [29t] qtObject ::= iri | BlankNode | literal | quotedTriple
#[cfg(feature = "rdf-star")]
TriGState::QuotedObject => match token {
@ -737,57 +836,75 @@ impl RuleRecognizer for TriGRecognizer {
self.cur_object.push(NamedNode::new_unchecked(iri).into());
self
}
N3Token::PrefixedName { prefix, local, might_be_invalid_iri } => match resolve_local_name(prefix, &local, might_be_invalid_iri, &context.prefixes) {
N3Token::PrefixedName {
prefix,
local,
might_be_invalid_iri,
} => match resolve_local_name(
prefix,
&local,
might_be_invalid_iri,
&context.prefixes,
) {
Ok(t) => {
self.cur_object.push(t.into());
self
},
Err(e) => self.error(errors, e)
}
Err(e) => self.error(errors, e),
},
N3Token::BlankNodeLabel(label) => {
self.cur_object.push(BlankNode::new_unchecked(label).into());
self
}
N3Token::String(value) => {
self.stack.push(TriGState::LiteralPossibleSuffix { value, emit: false });
self.stack
.push(TriGState::LiteralPossibleSuffix { value, emit: false });
self
}
N3Token::Integer(v) => {
self.cur_object.push(Literal::new_typed_literal(v, xsd::INTEGER).into());
self.cur_object
.push(Literal::new_typed_literal(v, xsd::INTEGER).into());
self
}
N3Token::Decimal(v) => {
self.cur_object.push(Literal::new_typed_literal(v, xsd::DECIMAL).into());
self.cur_object
.push(Literal::new_typed_literal(v, xsd::DECIMAL).into());
self
}
N3Token::Double(v) => {
self.cur_object.push(Literal::new_typed_literal(v, xsd::DOUBLE).into());
self.cur_object
.push(Literal::new_typed_literal(v, xsd::DOUBLE).into());
self
}
N3Token::PlainKeyword("true") => {
self.cur_object.push(Literal::new_typed_literal("true", xsd::BOOLEAN).into());
self.cur_object
.push(Literal::new_typed_literal("true", xsd::BOOLEAN).into());
self
}
N3Token::PlainKeyword("false") => {
self.cur_object.push(Literal::new_typed_literal("false", xsd::BOOLEAN).into());
self.cur_object
.push(Literal::new_typed_literal("false", xsd::BOOLEAN).into());
self
}
N3Token::Punctuation("<<") => {
self.stack.push(TriGState::ObjectQuotedTripleEnd { emit: false });
self.stack
.push(TriGState::ObjectQuotedTripleEnd { emit: false });
self.stack.push(TriGState::QuotedObject);
self.stack.push(TriGState::Verb);
self.stack.push(TriGState::QuotedSubject);
self
}
_ => self.error(errors, "TOKEN is not a valid RDF quoted triple object")
}
_ => self.error(errors, "TOKEN is not a valid RDF quoted triple object"),
},
#[cfg(feature = "rdf-star")]
TriGState::QuotedAnonEnd => if token == N3Token::Punctuation("]") {
TriGState::QuotedAnonEnd => {
if token == N3Token::Punctuation("]") {
self
} else {
self.error(errors, "Anonymous blank node with a property list are not allowed in quoted triples")
}
}
}
} else if token == N3Token::Punctuation(".") || token == N3Token::Punctuation("}") {
// TODO: be smarter depending if we are in '{' or not
self.stack.push(TriGState::TriGDoc);

Loading…
Cancel
Save