From b42428fc865f503ef078fc7c1d4feafeb5b4dc05 Mon Sep 17 00:00:00 2001 From: Tpt Date: Tue, 19 Jun 2018 13:52:08 +0200 Subject: [PATCH] Splits GraphPattern in MultiSetPattern and ListPattern --- src/sparql/algebra.rs | 157 ++++++++++++++++++------------ src/sparql/parser.rs | 18 ++-- src/sparql/sparql_grammar.rustpeg | 62 ++++++------ 3 files changed, 135 insertions(+), 102 deletions(-) diff --git a/src/sparql/algebra.rs b/src/sparql/algebra.rs index 740f9f6c..121fba31 100644 --- a/src/sparql/algebra.rs +++ b/src/sparql/algebra.rs @@ -216,7 +216,7 @@ pub enum Expression { IsNumericFunctionCall(Box), RegexFunctionCall(Box, Box, Option>), CustomFunctionCall(NamedNode, Vec), - ExistsFunctionCall(Box), + ExistsFunctionCall(Box), CountAggregate(Option>, bool), SumAggregate(Box, bool), MinAggregate(Box, bool), @@ -483,7 +483,7 @@ impl<'a> fmt::Display for SparqlExpression<'a> { Expression::UnaryMinusExpression(e) => write!(f, "-{}", SparqlExpression(&*e)), Expression::UnaryNotExpression(e) => match e.as_ref() { Expression::ExistsFunctionCall(p) => { - write!(f, "NOT EXISTS {{ {} }}", SparqlGraphPattern(&*p)) + write!(f, "NOT EXISTS {{ {} }}", SparqlMultiSetPattern(&*p)) } e => write!(f, "!{}", e), }, @@ -672,7 +672,7 @@ impl<'a> fmt::Display for SparqlExpression<'a> { .join(", ") ), Expression::ExistsFunctionCall(p) => { - write!(f, "EXISTS {{ {} }}", SparqlGraphPattern(&*p)) + write!(f, "EXISTS {{ {} }}", SparqlMultiSetPattern(&*p)) } Expression::CountAggregate(e, distinct) => if *distinct { e.as_ref() @@ -736,30 +736,22 @@ impl<'a> fmt::Display for SparqlExpression<'a> { } #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)] -pub enum GraphPattern { - Multiset(Vec), +pub enum MultiSetPattern { BGP(Vec), - Join(Box, Box), - LeftJoin(Box, Box, Expression), - Filter(Expression, Box), - Union(Box, Box), - Graph(NamedNodeOrVariable, Box), - Extend(Box, Variable, Expression), - Minus(Box, Box), - Group(), - Aggregation(), - AggregateJoin(), - OrderBy(Box), - Project(Box), - Distinct(Box), - Reduced(Box), - Slice(Box, usize, usize), + Join(Box, Box), + LeftJoin(Box, Box, Expression), + Filter(Expression, Box), + Union(Box, Box), + Graph(NamedNodeOrVariable, Box), + Extend(Box, Variable, Expression), + Minus(Box, Box), + ToMultiSet(Box), } -impl fmt::Display for GraphPattern { +impl fmt::Display for MultiSetPattern { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - GraphPattern::BGP(p) => write!( + MultiSetPattern::BGP(p) => write!( f, "BGP({})", p.iter() @@ -767,36 +759,36 @@ impl fmt::Display for GraphPattern { .collect::>() .join(" . ") ), - GraphPattern::Join(a, b) => write!(f, "Join({}, {})", a, b), - GraphPattern::LeftJoin(a, b, e) => write!(f, "LeftJoin({}, {}, {})", a, b, e), - GraphPattern::Filter(e, p) => write!(f, "Filter({}, {})", e, p), - GraphPattern::Union(a, b) => write!(f, "Union({}, {})", a, b), - GraphPattern::Graph(g, p) => write!(f, "Graph({}, {})", g, p), - GraphPattern::Extend(p, v, e) => write!(f, "Extend({}), {}, {})", p, v, e), - GraphPattern::Minus(a, b) => write!(f, "Minus({}, {})", a, b), - _ => Ok(()), //TODO + MultiSetPattern::Join(a, b) => write!(f, "Join({}, {})", a, b), + MultiSetPattern::LeftJoin(a, b, e) => write!(f, "LeftJoin({}, {}, {})", a, b, e), + MultiSetPattern::Filter(e, p) => write!(f, "Filter({}, {})", e, p), + MultiSetPattern::Union(a, b) => write!(f, "Union({}, {})", a, b), + MultiSetPattern::Graph(g, p) => write!(f, "Graph({}, {})", g, p), + MultiSetPattern::Extend(p, v, e) => write!(f, "Extend({}), {}, {})", p, v, e), + MultiSetPattern::Minus(a, b) => write!(f, "Minus({}, {})", a, b), + MultiSetPattern::ToMultiSet(l) => write!(f, "{}", l), } } } -impl Default for GraphPattern { +impl Default for MultiSetPattern { fn default() -> Self { - GraphPattern::BGP(Vec::default()) + MultiSetPattern::BGP(Vec::default()) } } -impl From for GraphPattern { +impl From for MultiSetPattern { fn from(p: PropertyPathPattern) -> Self { - GraphPattern::BGP(vec![p]) + MultiSetPattern::BGP(vec![p]) } } -struct SparqlGraphPattern<'a>(&'a GraphPattern); +struct SparqlMultiSetPattern<'a>(&'a MultiSetPattern); -impl<'a> fmt::Display for SparqlGraphPattern<'a> { +impl<'a> fmt::Display for SparqlMultiSetPattern<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.0 { - GraphPattern::BGP(p) => { + MultiSetPattern::BGP(p) => { if p.is_empty() { write!(f, "{{}}") } else { @@ -810,43 +802,82 @@ impl<'a> fmt::Display for SparqlGraphPattern<'a> { ) } } - GraphPattern::Join(a, b) => { - write!(f, "{} {}", SparqlGraphPattern(&*a), SparqlGraphPattern(&*b)) - } - GraphPattern::LeftJoin(a, b, e) => write!( + MultiSetPattern::Join(a, b) => write!( + f, + "{} {}", + SparqlMultiSetPattern(&*a), + SparqlMultiSetPattern(&*b) + ), + MultiSetPattern::LeftJoin(a, b, e) => write!( f, "{} OPTIONAL {{ {} FILTER({}) }}", - SparqlGraphPattern(&*a), - SparqlGraphPattern(&*b), + SparqlMultiSetPattern(&*a), + SparqlMultiSetPattern(&*b), SparqlExpression(e) ), - GraphPattern::Filter(e, p) => write!( + MultiSetPattern::Filter(e, p) => write!( f, "{} FILTER({})", - SparqlGraphPattern(&*p), + SparqlMultiSetPattern(&*p), SparqlExpression(e) ), - GraphPattern::Union(a, b) => write!( + MultiSetPattern::Union(a, b) => write!( f, "{{ {} }} UNION {{ {} }}", - SparqlGraphPattern(&*a), - SparqlGraphPattern(&*b) + SparqlMultiSetPattern(&*a), + SparqlMultiSetPattern(&*b) ), - GraphPattern::Graph(g, p) => write!(f, "GRAPH {} {{ {} }}", g, SparqlGraphPattern(&*p)), - GraphPattern::Extend(p, v, e) => write!( + MultiSetPattern::Graph(g, p) => { + write!(f, "GRAPH {} {{ {} }}", g, SparqlMultiSetPattern(&*p)) + } + MultiSetPattern::Extend(p, v, e) => write!( f, "{} BIND({} AS {})", - SparqlGraphPattern(&*p), + SparqlMultiSetPattern(&*p), SparqlExpression(e), v ), - GraphPattern::Minus(a, b) => write!( + MultiSetPattern::Minus(a, b) => write!( f, "{} MINUS {{ {} }}", - SparqlGraphPattern(&*a), - SparqlGraphPattern(&*b) + SparqlMultiSetPattern(&*a), + SparqlMultiSetPattern(&*b) ), - _ => write!(f, "{{}}"), //TODO + MultiSetPattern::ToMultiSet(l) => write!(f, "{}", SparqlListPattern(&l)), + } + } +} + +#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)] +pub enum ListPattern { + Data(Vec), + ToList(MultiSetPattern), + Group(), + Aggregation(), + AggregateJoin(), + OrderBy(Box), + Project(Box), + Distinct(Box), + Reduced(Box), + Slice(Box, usize, usize), +} + +impl fmt::Display for ListPattern { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + ListPattern::ToList(l) => write!(f, "{}", l), + _ => Ok(()), //TODO + } + } +} + +struct SparqlListPattern<'a>(&'a ListPattern); + +impl<'a> fmt::Display for SparqlListPattern<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + ListPattern::ToList(l) => write!(f, "{}", SparqlMultiSetPattern(&l)), + _ => Ok(()), //TODO } } } @@ -957,20 +988,20 @@ pub enum Query { SelectQuery { selection: Selection, dataset: Dataset, - filter: GraphPattern, + filter: MultiSetPattern, }, ConstructQuery { construct: Vec, dataset: Dataset, - filter: GraphPattern, + filter: MultiSetPattern, }, DescribeQuery { dataset: Dataset, - filter: GraphPattern, + filter: MultiSetPattern, }, AskQuery { dataset: Dataset, - filter: GraphPattern, + filter: MultiSetPattern, }, } @@ -986,7 +1017,7 @@ impl fmt::Display for Query { "SELECT {} {} WHERE {{ {} }}", selection, dataset, - SparqlGraphPattern(&filter) + SparqlMultiSetPattern(&filter) ), Query::ConstructQuery { construct, @@ -1001,19 +1032,19 @@ impl fmt::Display for Query { .collect::>() .join(" . "), dataset, - SparqlGraphPattern(&filter) + SparqlMultiSetPattern(&filter) ), Query::DescribeQuery { dataset, filter } => write!( f, "DESCRIBE {} WHERE {{ {} }}", dataset, - SparqlGraphPattern(&filter) + SparqlMultiSetPattern(&filter) ), Query::AskQuery { dataset, filter } => write!( f, "ASK {} WHERE {{ {} }}", dataset, - SparqlGraphPattern(&filter) + SparqlMultiSetPattern(&filter) ), } } diff --git a/src/sparql/parser.rs b/src/sparql/parser.rs index 86395619..8446ad49 100644 --- a/src/sparql/parser.rs +++ b/src/sparql/parser.rs @@ -92,21 +92,21 @@ mod grammar { #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)] enum PartialGraphPattern { - Optional(GraphPattern), - Minus(GraphPattern), + Optional(MultiSetPattern), + Minus(MultiSetPattern), Bind(Expression, Variable), Filter(Expression), - Other(GraphPattern), + Other(MultiSetPattern), } - fn new_join(l: GraphPattern, r: GraphPattern) -> GraphPattern { + fn new_join(l: MultiSetPattern, r: MultiSetPattern) -> MultiSetPattern { //Avoid to output empty BGPs - if let GraphPattern::BGP(pl) = &l { + if let MultiSetPattern::BGP(pl) = &l { if pl.is_empty() { return r; } } - if let GraphPattern::BGP(pr) = &r { + if let MultiSetPattern::BGP(pr) = &r { if pr.is_empty() { return l; } @@ -114,11 +114,11 @@ mod grammar { //Merge BGPs match (l, r) { - (GraphPattern::BGP(mut pl), GraphPattern::BGP(pr)) => { + (MultiSetPattern::BGP(mut pl), MultiSetPattern::BGP(pr)) => { pl.extend_from_slice(&pr); - GraphPattern::BGP(pl) + MultiSetPattern::BGP(pl) } - (l, r) => GraphPattern::Join(Box::new(l), Box::new(r)), + (l, r) => MultiSetPattern::Join(Box::new(l), Box::new(r)), } } diff --git a/src/sparql/sparql_grammar.rustpeg b/src/sparql/sparql_grammar.rustpeg index a6a81299..ea1cb433 100644 --- a/src/sparql/sparql_grammar.rustpeg +++ b/src/sparql/sparql_grammar.rustpeg @@ -46,9 +46,9 @@ SelectQuery -> Query = s:SelectClause _ d:DatasetClauses _ f:WhereClause _ Solut } //[8] -SubSelect -> GraphPattern = s:SelectClause _ f:WhereClause _ SolutionModifier _ ValuesClause { //TODO: Modifiers - GraphPattern::default() - /*TODO GraphPattern::SubSelectPattern { +SubSelect -> MultiSetPattern = s:SelectClause _ f:WhereClause _ SolutionModifier _ ValuesClause { //TODO: Modifiers + MultiSetPattern::default() + /*TODO MultiSetPattern::SubSelectPattern { selection: s, filter: Box::new(f) }*/ @@ -81,7 +81,7 @@ ConstructQuery -> Query = Query::ConstructQuery { construct: c.clone(), dataset: d, - filter: GraphPattern::BGP(c.into_iter().map(|p| PropertyPathPattern::from(p)).collect()) + filter: MultiSetPattern::BGP(c.into_iter().map(|p| PropertyPathPattern::from(p)).collect()) } } @@ -91,7 +91,7 @@ ConstructQuery_optional_triple_template -> Vec = TriplesTemplate DescribeQuery -> Query = "DESCRIBE"i _ ('*' / (VarOrIri _)+) _ d:DatasetClauses f:WhereClause? _ SolutionModifier { Query::DescribeQuery { dataset: d, - filter: f.unwrap_or_else(GraphPattern::default) + filter: f.unwrap_or_else(MultiSetPattern::default) } } @@ -123,7 +123,7 @@ NamedGraphClause -> Dataset = "NAMED"i _ s:SourceSelector { SourceSelector -> NamedNode = iri //[17] -WhereClause -> GraphPattern = "WHERE"i? _ p:GroupGraphPattern { p } +WhereClause -> MultiSetPattern = "WHERE"i? _ p:GroupGraphPattern { p } //[18] SolutionModifier -> () = GroupClause? _ HavingClause? _ OrderClause? _ LimitOffsetClauses? @@ -158,7 +158,7 @@ LimitClause -> () = "LIMIT"i _ INTEGER OffsetClause -> () = "OFFSET"i _ INTEGER //[28] -ValuesClause -> Option = +ValuesClause -> Option = "VALUES"i _ p:DataBlock { Some(p) } / { None } @@ -169,33 +169,33 @@ TriplesTemplate -> Vec = p:TriplesTemplate_item **<1,> ('.' _) '. TriplesTemplate_item -> Vec = p:TriplesSameSubject _ { p } //[53] -GroupGraphPattern -> GraphPattern = +GroupGraphPattern -> MultiSetPattern = '{' _ p:GroupGraphPatternSub _ '}' { p } / '{' _ p:SubSelect _ '}' { p } //[54] -GroupGraphPatternSub -> GraphPattern = a:TriplesBlock? _ b:GroupGraphPatternSub_item* { - let mut p = a.map(|v| vec![PartialGraphPattern::Other(GraphPattern::BGP(v))]).unwrap_or_else(|| vec![]); +GroupGraphPatternSub -> MultiSetPattern = a:TriplesBlock? _ b:GroupGraphPatternSub_item* { + let mut p = a.map(|v| vec![PartialGraphPattern::Other(MultiSetPattern::BGP(v))]).unwrap_or_else(|| vec![]); for v in b { p.extend_from_slice(&v) } let mut filter: Option = None; - let mut g = GraphPattern::default(); + let mut g = MultiSetPattern::default(); for e in p { match e { PartialGraphPattern::Optional(p) => match p { - GraphPattern::Filter(f, a2) => { - g = GraphPattern::LeftJoin(Box::new(g), a2, f) + MultiSetPattern::Filter(f, a2) => { + g = MultiSetPattern::LeftJoin(Box::new(g), a2, f) } a => { - g = GraphPattern::LeftJoin(Box::new(g), Box::new(a), Literal::from(true).into()) + g = MultiSetPattern::LeftJoin(Box::new(g), Box::new(a), Literal::from(true).into()) } } PartialGraphPattern::Minus(p) => { - g = GraphPattern::Minus(Box::new(g), Box::new(p)) + g = MultiSetPattern::Minus(Box::new(g), Box::new(p)) } PartialGraphPattern::Bind(expr, var) => { - g = GraphPattern::Extend(Box::new(g), var, expr) + g = MultiSetPattern::Extend(Box::new(g), var, expr) } PartialGraphPattern::Filter(expr) => match filter { Some(f) => { filter = Some(Expression::AndExpression(Box::new(f), Box::new(expr))) }, @@ -205,13 +205,13 @@ GroupGraphPatternSub -> GraphPattern = a:TriplesBlock? _ b:GroupGraphPatternSub_ } } match filter { - Some(filter) => GraphPattern::Filter(filter, Box::new(g)), + Some(filter) => MultiSetPattern::Filter(filter, Box::new(g)), None => g } } GroupGraphPatternSub_item -> Vec = a:GraphPatternNotTriples _ ('.' _)? b:TriplesBlock? _ { let mut result = vec![a]; - b.map(|v| result.push(PartialGraphPattern::Other(GraphPattern::BGP(v)))); + b.map(|v| result.push(PartialGraphPattern::Other(MultiSetPattern::BGP(v)))); result } @@ -237,13 +237,13 @@ OptionalGraphPattern -> PartialGraphPattern = "OPTIONAL"i _ p:GroupGraphPattern //[58] GraphGraphPattern -> PartialGraphPattern = "GRAPH"i _ g:VarOrIri _ p:GroupGraphPattern { - PartialGraphPattern::Other(GraphPattern::Graph(g, Box::new(p))) + PartialGraphPattern::Other(MultiSetPattern::Graph(g, Box::new(p))) } //[59] ServiceGraphPattern -> PartialGraphPattern = "SERVICE"i _ "SILENT"i? _ s:VarOrIri _ p:GroupGraphPattern { - PartialGraphPattern::Other(GraphPattern::default()) - //TODO PartialGraphPattern::Other(GraphPattern::ServicePattern(s, Box::new(p))) + PartialGraphPattern::Other(MultiSetPattern::default()) + //TODO PartialGraphPattern::Other(MultiSetPattern::ServicePattern(s, Box::new(p))) } //[60] @@ -255,27 +255,29 @@ Bind -> PartialGraphPattern = "BIND"i _ '(' _ e:Expression _ "AS"i _ v:Var _ ')' InlineData -> PartialGraphPattern = "VALUES"i _ p:DataBlock { PartialGraphPattern::Other(p) } //[62] -DataBlock -> GraphPattern = InlineDataOneVar / InlineDataFull +DataBlock -> MultiSetPattern = l:(InlineDataOneVar / InlineDataFull) { + MultiSetPattern::ToMultiSet(Box::new(ListPattern::Data(l))) +} //[63] -InlineDataOneVar -> GraphPattern = var:Var _ '{' _ d:InlineDataOneVar_value* '}' { - GraphPattern::Multiset(d.into_iter().map(|val| { +InlineDataOneVar -> Vec = var:Var _ '{' _ d:InlineDataOneVar_value* '}' { + d.into_iter().map(|val| { let mut bindings = Binding::default(); val.map(|v| bindings.insert(var.clone(), v)); bindings - }).collect()) + }).collect() } InlineDataOneVar_value -> Option = t:DataBlockValue { t } //[64] -InlineDataFull -> GraphPattern = '(' _ vars:InlineDataFull_var* _ ')' _ '{' _ val:InlineDataFull_values* '}' { - GraphPattern::Multiset(val.into_iter().map(|vals| { +InlineDataFull -> Vec = '(' _ vars:InlineDataFull_var* _ ')' _ '{' _ val:InlineDataFull_values* '}' { + val.into_iter().map(|vals| { let mut bindings = Binding::default(); for (var, val) in vars.iter().zip(vals.into_iter()) { val.map(|v| bindings.insert(var.clone(), v)); } bindings - }).collect()) + }).collect() } InlineDataFull_var -> Variable = v:Var _ { v } InlineDataFull_values -> Vec> = '(' _ v:InlineDataFull_value* _ ')' _ { v } @@ -297,10 +299,10 @@ MinusGraphPattern -> PartialGraphPattern = "MINUS"i _ p: GroupGraphPattern { //[67] GroupOrUnionGraphPattern -> PartialGraphPattern = p:GroupOrUnionGraphPattern_item **<1,> ("UNION"i _) {? not_empty_fold(p.into_iter(), |a, b| { - GraphPattern::Union(Box::new(a), Box::new(b)) + MultiSetPattern::Union(Box::new(a), Box::new(b)) }).map(PartialGraphPattern::Other) } -GroupOrUnionGraphPattern_item -> GraphPattern = p:GroupGraphPattern _ { p } +GroupOrUnionGraphPattern_item -> MultiSetPattern = p:GroupGraphPattern _ { p } //[68] Filter -> PartialGraphPattern = "FILTER"i _ c:Constraint {