diff --git a/src/model/data.rs b/src/model/data.rs index 887ffc70..143471f1 100644 --- a/src/model/data.rs +++ b/src/model/data.rs @@ -2,8 +2,10 @@ ///! Inspired by [RDFjs](http://rdf.js.org/) use std::fmt; use std::option::Option; +use std::str::FromStr; use std::sync::Arc; use std::sync::Mutex; +use url::ParseError; use url::Url; /// A RDF [IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) @@ -28,6 +30,16 @@ impl fmt::Display for NamedNode { } } +impl FromStr for NamedNode { + type Err = ParseError; + + fn from_str(s: &str) -> Result { + Ok(NamedNode { + iri: Arc::new(Url::parse(s)?), + }) + } +} + /// A RDF [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) #[derive(Eq, PartialEq, Debug, Clone, Hash)] pub struct BlankNode { @@ -55,12 +67,12 @@ pub enum Literal { } lazy_static! { - static ref XSD_STRING: NamedNode = NamedNode { - iri: Arc::new(Url::parse("http://www.w3.org/2001/XMLSchema#string").unwrap()) - }; - static ref RDF_LANG_STRING: NamedNode = NamedNode { - iri: Arc::new(Url::parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#langString").unwrap()) - }; + static ref XSD_BOOLEAN: NamedNode = + NamedNode::from_str("http://www.w3.org/2001/XMLSchema#boolean").unwrap(); + static ref XSD_STRING: NamedNode = + NamedNode::from_str("http://www.w3.org/2001/XMLSchema#string").unwrap(); + static ref RDF_LANG_STRING: NamedNode = + NamedNode::from_str("http://www.w3.org/1999/02/22-rdf-syntax-ns#langString").unwrap(); } impl Literal { @@ -112,6 +124,35 @@ impl fmt::Display for Literal { } } +impl<'a> From<&'a str> for Literal { + fn from(value: &'a str) -> Self { + Literal::SimpleLiteral(value.into()) + } +} + +impl From for Literal { + fn from(value: String) -> Self { + Literal::SimpleLiteral(value) + } +} + +impl From for Literal { + fn from(value: bool) -> Self { + Literal::TypedLiteral { + value: value.to_string(), + datatype: XSD_BOOLEAN.clone(), + } + } +} + +impl FromStr for Literal { + type Err = (); + + fn from_str(s: &str) -> Result { + Ok(s.clone().into()) + } +} + /// The union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) and [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node). #[derive(Eq, PartialEq, Debug, Clone, Hash)] pub enum NamedOrBlankNode { diff --git a/src/rio/ntriples/ntriples_grammar.rustpeg b/src/rio/ntriples/ntriples_grammar.rustpeg index ade1796a..1868e97c 100644 --- a/src/rio/ntriples/ntriples_grammar.rustpeg +++ b/src/rio/ntriples/ntriples_grammar.rustpeg @@ -2,7 +2,7 @@ use std::iter::FromIterator; use std::char; -use url::Url; +use std::str::FromStr; use model::data::*; #![arguments(data_factory: &DataFactory)] @@ -15,25 +15,25 @@ triple -> Option = //[3] subject -> NamedOrBlankNode = - i: IRIREF { data_factory.named_node(i).into() } / - b: BLANK_NODE_LABEL { data_factory.blank_node(b).into() } + i: IRIREF { i.into() } / + b: BLANK_NODE_LABEL { b.into() } //[4] predicate -> NamedNode = i:IRIREF { - data_factory.named_node(i) + i } //[5] object -> Term = - i: IRIREF { data_factory.named_node(i).into() } / - b: BLANK_NODE_LABEL { data_factory.blank_node(b).into() } / + i: IRIREF { i.into() } / + b: BLANK_NODE_LABEL { b.into() } / l: literal { l.into() } //[6] literal -> Literal = - v: STRING_LITERAL_QUOTE _ "^^" _ t:IRIREF { data_factory.typed_literal(v, data_factory.named_node(t)) } / + v: STRING_LITERAL_QUOTE _ "^^" _ t:IRIREF { data_factory.typed_literal(v, t) } / v: STRING_LITERAL_QUOTE _ l:LANGTAG { data_factory.language_tagged_literal(v, l) } / - v: STRING_LITERAL_QUOTE { data_factory.simple_literal(v) } + v: STRING_LITERAL_QUOTE { v.into() } //[144s] @@ -45,10 +45,10 @@ LANGTAG -> &'input str = "@" l:$([a-zA-Z]+ ("-" [a-zA-Z0-9]+)*) { EOL = [\r\n]+ //[8] -IRIREF -> Url = "<" _ i:((_IRIREF_simple_char / UCHAR)*) _ ">" {? +IRIREF -> NamedNode = "<" _ i:((_IRIREF_simple_char / UCHAR)*) _ ">" {? let s = String::from_iter(i.into_iter()); - match Url::parse(&s) { - Ok(url) => Ok(url), + match NamedNode::from_str(&s) { + Ok(named_node) => Ok(named_node), Err(error) => Err("IRI parsing failed") } } @@ -61,8 +61,8 @@ STRING_LITERAL_QUOTE -> String = "\"" l:((STRING_LITERAL_QUOTE_simple_char / ECH STRING_LITERAL_QUOTE_simple_char -> char = c: $([^\u{0022}\u{005c}\u{000a}\u{000d}]) { c.chars().next().unwrap() } //[141s] -BLANK_NODE_LABEL -> &'input str = "_:" b:$(([0-9] / PN_CHARS_U) PN_CHARS* ("."+ PN_CHARS+)*) { - b +BLANK_NODE_LABEL -> BlankNode = "_:" b:$(([0-9] / PN_CHARS_U) PN_CHARS* ("."+ PN_CHARS+)*) { + data_factory.blank_node(b) } //[10] diff --git a/src/rio/turtle/turtle_grammar.rustpeg b/src/rio/turtle/turtle_grammar.rustpeg index 3273e3ac..6a327939 100644 --- a/src/rio/turtle/turtle_grammar.rustpeg +++ b/src/rio/turtle/turtle_grammar.rustpeg @@ -3,6 +3,7 @@ use std::char; use url::Url; use model::data::*; +use std::str::FromStr; use std::iter; use rio::turtle::ParserState; @@ -70,7 +71,7 @@ objectList -> () = object _ ("," _ object _)* //[9] verb -> NamedNode = predicate / - "a" { data_factory.named_node(Url::parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#type").unwrap()) } + "a" { NamedNode::from_str("http://www.w3.org/1999/02/22-rdf-syntax-ns#type").unwrap() } // [10] subject -> NamedOrBlankNode = @@ -115,9 +116,9 @@ blankNodePropertyList_open -> () = "[" { //[15] collection -> NamedOrBlankNode = '(' _ o:(collection_value*) ')' { - let first = data_factory.named_node(Url::parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#first").unwrap()); - let rest = data_factory.named_node(Url::parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest").unwrap()); - let mut current_list_node = NamedOrBlankNode::from(data_factory.named_node(Url::parse("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil").unwrap())); + let first = NamedNode::from_str("http://www.w3.org/1999/02/22-rdf-syntax-ns#first").unwrap(); + let rest = NamedNode::from_str("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest").unwrap(); + let mut current_list_node = NamedOrBlankNode::from(NamedNode::from_str("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil").unwrap()); for obj in o.into_iter().rev() { let new_blank_node = NamedOrBlankNode::from(data_factory.new_blank_node()); buffer.push(data_factory.triple(new_blank_node.clone(), first.clone(), obj)); @@ -130,20 +131,20 @@ collection_value -> Term = o:object_value _ { o } //[16] NumericLiteral -> Literal = - d:$(DOUBLE) { data_factory.typed_literal(d, data_factory.named_node(Url::parse("http://www.w3.org/2001/XMLSchema#double").unwrap())) } / - d:$(DECIMAL) { data_factory.typed_literal(d, data_factory.named_node(Url::parse("http://www.w3.org/2001/XMLSchema#decimal").unwrap())) } / - i:$(INTEGER) { data_factory.typed_literal(i, data_factory.named_node(Url::parse("http://www.w3.org/2001/XMLSchema#integer").unwrap())) } + d:$(DOUBLE) { data_factory.typed_literal(d, NamedNode::from_str("http://www.w3.org/2001/XMLSchema#double").unwrap()) } / + d:$(DECIMAL) { data_factory.typed_literal(d, NamedNode::from_str("http://www.w3.org/2001/XMLSchema#decimal").unwrap()) } / + i:$(INTEGER) { data_factory.typed_literal(i, NamedNode::from_str("http://www.w3.org/2001/XMLSchema#integer").unwrap()) } //[128s] RDFLiteral -> Literal = v:String _ "^^" _ t:iri { data_factory.typed_literal(v, t) } / v:String _ l:LANGTAG { data_factory.language_tagged_literal(v, l) } / - v:String { data_factory.simple_literal(v) } + v:String { v.into() } //[133s] BooleanLiteral -> Literal = - "true" { data_factory.typed_literal("true", data_factory.named_node(Url::parse("http://www.w3.org/2001/XMLSchema#boolean").unwrap())) } / - "false" { data_factory.typed_literal("false", data_factory.named_node(Url::parse("http://www.w3.org/2001/XMLSchema#boolean").unwrap())) } + "true" { true.into() } / + "false" { false.into() } //[17] String -> String = STRING_LITERAL_LONG_SINGLE_QUOTE / STRING_LITERAL_LONG_QUOTE / STRING_LITERAL_QUOTE / STRING_LITERAL_SINGLE_QUOTE