diff --git a/spargebra/src/parser.rs b/spargebra/src/parser.rs index 2a4c5d3b..a20f7097 100644 --- a/spargebra/src/parser.rs +++ b/spargebra/src/parser.rs @@ -28,7 +28,7 @@ pub fn parse_query(query: &str, base_iri: Option<&str>) -> Result) -> Result)>, +} + +#[derive(Default)] struct FocusedTriplePattern { focus: F, patterns: Vec, @@ -98,16 +104,7 @@ impl FocusedTriplePattern { fn new(focus: F) -> Self { Self { focus, - patterns: Vec::default(), - } - } -} - -impl Default for FocusedTriplePattern { - fn default() -> Self { - Self { - focus: F::default(), - patterns: Vec::default(), + patterns: Vec::new(), } } } @@ -133,41 +130,112 @@ impl From for VariableOrPropertyPath { } } +impl From for VariableOrPropertyPath { + fn from(pattern: NamedNodePattern) -> Self { + match pattern { + NamedNodePattern::NamedNode(node) => PropertyPathExpression::from(node).into(), + NamedNodePattern::Variable(v) => v.into(), + } + } +} + impl From for VariableOrPropertyPath { fn from(path: PropertyPathExpression) -> Self { VariableOrPropertyPath::PropertyPath(path) } } +fn add_to_triple_patterns( + subject: TermPattern, + predicate: NamedNodePattern, + object: AnnotatedTerm, + patterns: &mut Vec, +) { + let triple = TriplePattern::new(subject, predicate, object.term); + for (p, os) in object.annotations { + for o in os { + add_to_triple_patterns(triple.clone().into(), p.clone(), o, patterns) + } + } + patterns.push(triple) +} + fn add_to_triple_or_path_patterns( subject: TermPattern, predicate: impl Into, - object: TermPattern, + object: AnnotatedTermPath, patterns: &mut Vec, -) { +) -> Result<(), &'static str> { match predicate.into() { VariableOrPropertyPath::Variable(p) => { - patterns.push(TriplePattern::new(subject, p, object).into()) + add_triple_to_triple_or_path_patterns(subject, p, object, patterns)?; } VariableOrPropertyPath::PropertyPath(p) => match p { PropertyPathExpression::NamedNode(p) => { - patterns.push(TriplePattern::new(subject, p, object).into()) - } - PropertyPathExpression::Reverse(p) => { - add_to_triple_or_path_patterns(object, *p, subject, patterns) + add_triple_to_triple_or_path_patterns(subject, p, object, patterns)?; } + PropertyPathExpression::Reverse(p) => add_to_triple_or_path_patterns( + object.term, + *p, + AnnotatedTermPath { + term: subject, + annotations: object.annotations, + }, + patterns, + )?, PropertyPathExpression::Sequence(a, b) => { + if !object.annotations.is_empty() { + return Err("Annotations are not allowed on property paths"); + } let middle = bnode(); - add_to_triple_or_path_patterns(subject, *a, middle.clone().into(), patterns); - add_to_triple_or_path_patterns(middle.into(), *b, object, patterns); + add_to_triple_or_path_patterns( + subject, + *a, + AnnotatedTermPath { + term: middle.clone().into(), + annotations: Vec::new(), + }, + patterns, + )?; + add_to_triple_or_path_patterns( + middle.into(), + *b, + AnnotatedTermPath { + term: object.term, + annotations: Vec::new(), + }, + patterns, + )?; + } + path => { + if !object.annotations.is_empty() { + return Err("Annotations are not allowed on property paths"); + } + patterns.push(TripleOrPathPattern::Path { + subject, + path, + object: object.term, + }) } - path => patterns.push(TripleOrPathPattern::Path { - subject, - path, - object, - }), }, } + Ok(()) +} + +fn add_triple_to_triple_or_path_patterns( + subject: TermPattern, + predicate: impl Into, + object: AnnotatedTermPath, + patterns: &mut Vec, +) -> Result<(), &'static str> { + let triple = TriplePattern::new(subject, predicate, object.term); + for (p, os) in object.annotations { + for o in os { + add_to_triple_or_path_patterns(triple.clone().into(), p.clone(), o, patterns)? + } + } + patterns.push(triple.into()); + Ok(()) } fn build_bgp(patterns: Vec) -> GraphPattern { @@ -212,6 +280,30 @@ impl From for TripleOrPathPattern { } } +struct AnnotatedTermPath { + term: TermPattern, + annotations: Vec<(VariableOrPropertyPath, Vec)>, +} + +impl From for AnnotatedTermPath { + fn from(term: AnnotatedTerm) -> Self { + Self { + term: term.term, + annotations: term + .annotations + .into_iter() + .map(|(p, o)| { + ( + p.into(), + o.into_iter().map(AnnotatedTermPath::from).collect(), + ) + }) + .collect(), + } + } +} + +#[derive(Default)] struct FocusedTripleOrPathPattern { focus: F, patterns: Vec, @@ -221,16 +313,7 @@ impl FocusedTripleOrPathPattern { fn new(focus: F) -> Self { Self { focus, - patterns: Vec::default(), - } - } -} - -impl Default for FocusedTripleOrPathPattern { - fn default() -> Self { - Self { - focus: F::default(), - patterns: Vec::default(), + patterns: Vec::new(), } } } @@ -398,7 +481,7 @@ fn build_select( } //SELECT - let mut pv: Vec = Vec::default(); + let mut pv: Vec = Vec::new(); match select.variables { Some(sel_items) => { for sel_item in sel_items { @@ -785,7 +868,7 @@ parser! { } } rule Selection_init() = { - state.aggregates.push(Vec::default()) + state.aggregates.push(Vec::new()) } rule SelectClause_option() -> SelectionOption = i("DISTINCT") { SelectionOption::Distinct } / @@ -821,7 +904,7 @@ parser! { } } - rule ConstructQuery_optional_triple_template() -> Vec = TriplesTemplate() / { Vec::default() } + rule ConstructQuery_optional_triple_template() -> Vec = TriplesTemplate() / { Vec::new() } //[11] rule DescribeQuery() -> Query = @@ -897,7 +980,7 @@ parser! { //[19] rule GroupClause() -> (Vec, Vec<(Expression,Variable)>) = i("GROUP") _ i("BY") _ c:GroupCondition_item()+ { - let mut projections: Vec<(Expression,Variable)> = Vec::default(); + let mut projections: Vec<(Expression,Variable)> = Vec::new(); let clauses = c.into_iter().map(|(e, vo)| { if let Expression::Variable(v) = e { v @@ -1343,7 +1426,7 @@ parser! { //[72] rule ExpressionList() -> Vec = "(" _ e:ExpressionList_item() **<1,> ("," _) ")" { e } / - NIL() { Vec::default() } + NIL() { Vec::new() } rule ExpressionList_item() -> Expression = e:Expression() _ { e } //[73] @@ -1361,7 +1444,7 @@ parser! { let mut patterns = po.patterns; for (p, os) in po.focus { for o in os { - patterns.push(TriplePattern::new(s.clone(), p.clone(), o)) + add_to_triple_patterns(s.clone(), p.clone(), o, &mut patterns) } } patterns @@ -1371,26 +1454,26 @@ parser! { patterns.extend(po.patterns); for (p, os) in po.focus { for o in os { - patterns.push(TriplePattern::new(s.focus.clone(), p.clone(), o)) + add_to_triple_patterns(s.focus.clone(), p.clone(), o, &mut patterns) } } patterns } //[76] - rule PropertyList() -> FocusedTriplePattern)>> = + rule PropertyList() -> FocusedTriplePattern)>> = PropertyListNotEmpty() / { FocusedTriplePattern::default() } //[77] - rule PropertyListNotEmpty() -> FocusedTriplePattern)>> = l:PropertyListNotEmpty_item() **<1,> (";" _) { - l.into_iter().fold(FocusedTriplePattern::)>>::default(), |mut a, b| { + rule PropertyListNotEmpty() -> FocusedTriplePattern)>> = l:PropertyListNotEmpty_item() **<1,> (";" _) { + l.into_iter().fold(FocusedTriplePattern::)>>::default(), |mut a, b| { a.focus.push(b.focus); a.patterns.extend(b.patterns); a }) } - rule PropertyListNotEmpty_item() -> FocusedTriplePattern<(NamedNodePattern,Vec)> = p:Verb() _ o:ObjectList() _ { + rule PropertyListNotEmpty_item() -> FocusedTriplePattern<(NamedNodePattern,Vec)> = p:Verb() _ o:ObjectList() _ { FocusedTriplePattern { focus: (p, o.focus), patterns: o.patterns @@ -1401,47 +1484,67 @@ parser! { rule Verb() -> NamedNodePattern = VarOrIri() / "a" { iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#type").into() } //[79] - rule ObjectList() -> FocusedTriplePattern> = o:ObjectList_item() **<1,> ("," _) { - o.into_iter().fold(FocusedTriplePattern::>::default(), |mut a, b| { + rule ObjectList() -> FocusedTriplePattern> = o:ObjectList_item() **<1,> ("," _) { + o.into_iter().fold(FocusedTriplePattern::>::default(), |mut a, b| { a.focus.push(b.focus); a.patterns.extend_from_slice(&b.patterns); a }) } - rule ObjectList_item() -> FocusedTriplePattern = o:Object() _ { o } + rule ObjectList_item() -> FocusedTriplePattern = o:Object() _ { o } //[80] - rule Object() -> FocusedTriplePattern = GraphNode() + rule Object() -> FocusedTriplePattern = g:GraphNode() _ a:AnnotationPattern()? { + if let Some(a) = a { + let mut patterns = g.patterns; + patterns.extend(a.patterns); + FocusedTriplePattern { + focus: AnnotatedTerm { + term: g.focus, + annotations: a.focus + }, + patterns + } + } else { + FocusedTriplePattern { + focus: AnnotatedTerm { + term: g.focus, + annotations: Vec::new() + }, + patterns: g.patterns + } + } + } //[81] rule TriplesSameSubjectPath() -> Vec = - s:VarOrTermOrEmbTP() _ po:PropertyListPathNotEmpty() { + s:VarOrTermOrEmbTP() _ po:PropertyListPathNotEmpty() {? let mut patterns = po.patterns; for (p, os) in po.focus { for o in os { - add_to_triple_or_path_patterns(s.clone(), p.clone(), o, &mut patterns); + add_to_triple_or_path_patterns(s.clone(), p.clone(), o, &mut patterns)?; } } - patterns + Ok(patterns) } / - s:TriplesNodePath() _ po:PropertyListPath() { + s:TriplesNodePath() _ po:PropertyListPath() {? let mut patterns = s.patterns; patterns.extend(po.patterns); for (p, os) in po.focus { for o in os { - add_to_triple_or_path_patterns(s.focus.clone(), p.clone(), o, &mut patterns); + add_to_triple_or_path_patterns(s.focus.clone(), p.clone(), o, &mut patterns)?; } } - patterns + Ok(patterns) } //[82] - rule PropertyListPath() -> FocusedTripleOrPathPattern)>> = + rule PropertyListPath() -> FocusedTripleOrPathPattern)>> = PropertyListPathNotEmpty() / { FocusedTripleOrPathPattern::default() } //[83] - rule PropertyListPathNotEmpty() -> FocusedTripleOrPathPattern)>> = hp:(VerbPath() / VerbSimple()) _ ho:ObjectListPath() _ t:PropertyListPathNotEmpty_item()* { + rule PropertyListPathNotEmpty() -> FocusedTripleOrPathPattern)>> = hp:(VerbPath() / VerbSimple()) _ ho:ObjectListPath() _ t:PropertyListPathNotEmpty_item()* { t.into_iter().flat_map(|e| e.into_iter()).fold(FocusedTripleOrPathPattern { focus: vec![(hp, ho.focus)], patterns: ho.patterns @@ -1451,12 +1554,12 @@ parser! { a }) } - rule PropertyListPathNotEmpty_item() -> Option)>> = ";" _ c:PropertyListPathNotEmpty_item_content()? { + rule PropertyListPathNotEmpty_item() -> Option)>> = ";" _ c:PropertyListPathNotEmpty_item_content()? { c } - rule PropertyListPathNotEmpty_item_content() -> FocusedTriplePattern<(VariableOrPropertyPath,Vec)> = p:(VerbPath() / VerbSimple()) _ o:ObjectList() _ { + rule PropertyListPathNotEmpty_item_content() -> FocusedTriplePattern<(VariableOrPropertyPath,Vec)> = p:(VerbPath() / VerbSimple()) _ o:ObjectList() _ { FocusedTriplePattern { - focus: (p, o.focus), + focus: (p, o.focus.into_iter().map(AnnotatedTermPath::from).collect()), patterns: o.patterns } } @@ -1472,17 +1575,37 @@ parser! { } //[86] - rule ObjectListPath() -> FocusedTripleOrPathPattern> = o:ObjectPath_item() **<1,> ("," _) { - o.into_iter().fold(FocusedTripleOrPathPattern::>::default(), |mut a, b| { + rule ObjectListPath() -> FocusedTripleOrPathPattern> = o:ObjectListPath_item() **<1,> ("," _) { + o.into_iter().fold(FocusedTripleOrPathPattern::>::default(), |mut a, b| { a.focus.push(b.focus); a.patterns.extend(b.patterns); a }) } - rule ObjectPath_item() -> FocusedTripleOrPathPattern = o:ObjectPath() _ { o } + rule ObjectListPath_item() -> FocusedTripleOrPathPattern = o:ObjectPath() _ { o } //[87] - rule ObjectPath() -> FocusedTripleOrPathPattern = GraphNodePath() + rule ObjectPath() -> FocusedTripleOrPathPattern = g:GraphNodePath() _ a:AnnotationPatternPath()? { + if let Some(a) = a { + let mut patterns = g.patterns; + patterns.extend(a.patterns); + FocusedTripleOrPathPattern { + focus: AnnotatedTermPath { + term: g.focus, + annotations: a.focus + }, + patterns + } + } else { + FocusedTripleOrPathPattern { + focus: AnnotatedTermPath { + term: g.focus, + annotations: Vec::new() + }, + patterns: g.patterns + } + } + } //[88] rule Path() -> PropertyPathExpression = PathAlternative() @@ -1525,8 +1648,8 @@ parser! { //[95] rule PathNegatedPropertySet() -> PropertyPathExpression = "(" _ p:PathNegatedPropertySet_item() **<1,> ("|" _) ")" { - let mut direct = Vec::default(); - let mut inverse = Vec::default(); + let mut direct = Vec::new(); + let mut inverse = Vec::new(); for e in p { match e { Either::Left(a) => direct.push(a), @@ -1564,11 +1687,11 @@ parser! { //[99] rule BlankNodePropertyList() -> FocusedTriplePattern = "[" _ po:PropertyListNotEmpty() _ "]" { - let mut patterns: Vec = Vec::default(); + let mut patterns = po.patterns; let mut bnode = TermPattern::from(bnode()); for (p, os) in po.focus { for o in os { - patterns.push(TriplePattern::new(bnode.clone(), p.clone(), o)); + add_to_triple_patterns(bnode.clone(), p.clone(), o, &mut patterns) } } FocusedTriplePattern { @@ -1581,23 +1704,23 @@ parser! { rule TriplesNodePath() -> FocusedTripleOrPathPattern = CollectionPath() / BlankNodePropertyListPath() //[101] - rule BlankNodePropertyListPath() -> FocusedTripleOrPathPattern = "[" _ po:PropertyListPathNotEmpty() _ "]" { - let mut patterns: Vec = Vec::default(); + rule BlankNodePropertyListPath() -> FocusedTripleOrPathPattern = "[" _ po:PropertyListPathNotEmpty() _ "]" {? + let mut patterns: Vec = Vec::new(); let mut bnode = TermPattern::from(bnode()); for (p, os) in po.focus { for o in os { - add_to_triple_or_path_patterns(bnode.clone(), p.clone(), o, &mut patterns); + add_to_triple_or_path_patterns(bnode.clone(), p.clone(), o, &mut patterns)?; } } - FocusedTripleOrPathPattern { + Ok(FocusedTripleOrPathPattern { focus: bnode, patterns - } + }) } //[102] rule Collection() -> FocusedTriplePattern = "(" _ o:Collection_item()+ ")" { - let mut patterns: Vec = Vec::default(); + let mut patterns: Vec = Vec::new(); let mut current_list_node = TermPattern::from(iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil")); for objWithPatterns in o.into_iter().rev() { let new_blank_node = TermPattern::from(bnode()); @@ -1615,7 +1738,7 @@ parser! { //[103] rule CollectionPath() -> FocusedTripleOrPathPattern = "(" _ o:CollectionPath_item()+ _ ")" { - let mut patterns: Vec = Vec::default(); + let mut patterns: Vec = Vec::new(); let mut current_list_node = TermPattern::from(iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil")); for objWithPatterns in o.into_iter().rev() { let new_blank_node = TermPattern::from(bnode()); @@ -2095,6 +2218,12 @@ parser! { t:GraphTerm() { t.into() } / t:EmbTP() { t.into() } + //[179] + rule AnnotationPattern() -> FocusedTriplePattern)>> = "{|" _ a:PropertyListNotEmpty() _ "|}" { a } + + //[180] + rule AnnotationPatternPath() -> FocusedTripleOrPathPattern)>> = "{|" _ a: PropertyListPathNotEmpty() _ "|}" { a } + // Extra rule not yet in the spec rule TripleExpression() -> Expression = "<<" _ s:Expression() _ p:Expression() _ o:Expression() _ ">>" { Expression::FunctionCall(Function::Triple, vec![s, p, o]) diff --git a/testsuite/tests/sparql.rs b/testsuite/tests/sparql.rs index 79d439fd..cc7ce8be 100644 --- a/testsuite/tests/sparql.rs +++ b/testsuite/tests/sparql.rs @@ -133,24 +133,6 @@ fn sparql11_tsv_w3c_evaluation_testsuite() -> Result<()> { fn sparql_star_query_syntax_testsuite() -> Result<()> { run_testsuite( "https://w3c.github.io/rdf-star/tests/sparql/syntax/manifest.ttl", - vec![ - // Annotation syntax is not implemented yet - "https://w3c.github.io/rdf-star/tests/sparql/syntax#sparql-star-ann-01", - "https://w3c.github.io/rdf-star/tests/sparql/syntax#sparql-star-ann-02", - "https://w3c.github.io/rdf-star/tests/sparql/syntax#sparql-star-ann-03", - "https://w3c.github.io/rdf-star/tests/sparql/syntax#sparql-star-ann-04", - "https://w3c.github.io/rdf-star/tests/sparql/syntax#sparql-star-ann-05", - "https://w3c.github.io/rdf-star/tests/sparql/syntax#sparql-star-ann-06", - "https://w3c.github.io/rdf-star/tests/sparql/syntax#sparql-star-ann-07", - "https://w3c.github.io/rdf-star/tests/sparql/syntax#sparql-star-ann-08", - "https://w3c.github.io/rdf-star/tests/sparql/syntax#sparql-star-ann-09", - "https://w3c.github.io/rdf-star/tests/sparql/syntax#sparql-star-update-2", - "https://w3c.github.io/rdf-star/tests/sparql/syntax#sparql-star-update-3", - "https://w3c.github.io/rdf-star/tests/sparql/syntax#sparql-star-update-4", - "https://w3c.github.io/rdf-star/tests/sparql/syntax#sparql-star-update-5", - "https://w3c.github.io/rdf-star/tests/sparql/syntax#sparql-star-update-6", - "https://w3c.github.io/rdf-star/tests/sparql/syntax#sparql-star-update-7", - "https://w3c.github.io/rdf-star/tests/sparql/syntax#sparql-star-update-8", - ], + vec![], ) }