lang_sparql/lang/
model.rs

1use lang_turtle::lang::{
2    context::Context,
3    model::{Based, NamedNode, Triple, TriplesBuilder, TurtlePrefix, TurtleSimpleError},
4};
5use lsp_core::prelude::{Spanned, SparqlKeyword, Token};
6
7#[derive(Clone, Debug, PartialEq, Eq)]
8pub struct Base {
9    pub token: Spanned<Token>,
10    pub iri: Spanned<NamedNode>,
11}
12
13#[derive(Clone, Debug, PartialEq, Eq)]
14pub enum Prologue {
15    Base {
16        token: Spanned<Token>,
17        iri: Spanned<NamedNode>,
18    },
19    Prefix(TurtlePrefix),
20}
21
22#[derive(Clone, Debug, PartialEq, Eq)]
23pub struct DatasetClause {
24    pub from: Spanned<SparqlKeyword>,
25    pub named: Option<Spanned<SparqlKeyword>>,
26    pub iri: Spanned<NamedNode>,
27}
28
29#[derive(Clone, Debug, PartialEq, Eq)]
30pub enum GroupGraphPattern {
31    SubSelect(Box<SubSelect>),
32    GroupGraph(Vec<Spanned<GroupGraphPatternSub>>),
33    Invalid,
34}
35impl GroupGraphPattern {
36    fn add_to_context(&self, ctx: &mut Context) {
37        match self {
38            GroupGraphPattern::SubSelect(sub_select) => {
39                sub_select.add_to_context(ctx);
40            }
41            GroupGraphPattern::GroupGraph(spanneds) => {
42                for s in spanneds {
43                    s.value().add_to_context(ctx);
44                }
45            }
46            _ => {}
47        }
48    }
49
50    pub fn ingest_triples<'a>(
51        &'a self,
52        builder: &mut TriplesBuilder<'a, Query>,
53    ) -> Result<(), TurtleSimpleError> {
54        match self {
55            GroupGraphPattern::SubSelect(sub_select) => sub_select.ingest_triples(builder)?,
56            GroupGraphPattern::GroupGraph(xs) => {
57                for x in xs {
58                    x.ingest_triples(builder)?;
59                }
60            }
61            GroupGraphPattern::Invalid => {}
62        }
63        Ok(())
64    }
65}
66
67#[derive(Clone, Debug, PartialEq, Eq)]
68pub struct WhereClause {
69    pub kwd: Option<Spanned<SparqlKeyword>>,
70    pub ggp: Spanned<GroupGraphPattern>,
71}
72impl WhereClause {
73    pub fn ingest_triples<'a>(
74        &'a self,
75        builder: &mut TriplesBuilder<'a, Query>,
76    ) -> Result<(), TurtleSimpleError> {
77        self.ggp.ingest_triples(builder)?;
78        Ok(())
79    }
80
81    fn add_to_context(&self, ctx: &mut Context) {
82        self.ggp.value().add_to_context(ctx);
83    }
84}
85
86#[derive(Clone, Debug, PartialEq, Eq)]
87pub struct Variable(pub String);
88
89#[derive(Clone, Debug, PartialEq, Eq)]
90pub struct Expression {}
91
92#[derive(Clone, Debug, PartialEq, Eq)]
93pub struct Bind {
94    pub expr: Spanned<Expression>,
95    pub kwd: Spanned<SparqlKeyword>,
96    pub var: Spanned<Variable>,
97}
98
99#[derive(Clone, Debug, PartialEq, Eq)]
100pub enum Solution {
101    All,
102    Var(Variable),
103    VarAs(Bind),
104}
105
106#[derive(Clone, Debug, PartialEq, Eq)]
107pub struct SelectClause {
108    pub kwd: Spanned<SparqlKeyword>,
109    pub modifier: Option<Spanned<SparqlKeyword>>,
110    pub solutions: Vec<Spanned<Solution>>,
111}
112
113#[derive(Clone, Debug, PartialEq, Eq)]
114pub struct ConstructClause {
115    kwd: Spanned<SparqlKeyword>,
116    template: Option<(
117        Spanned<Token>,
118        Vec<Spanned<GroupGraphPatternSub>>,
119        Spanned<Token>,
120    )>,
121}
122
123#[derive(Clone, Debug, PartialEq, Eq)]
124pub enum QueryClause {
125    Select(SelectClause),
126    Construct(ConstructClause),
127    Invalid,
128}
129
130#[derive(Clone, Debug, PartialEq, Eq)]
131pub struct SubSelect {
132    pub select: SelectClause,
133    pub where_clause: WhereClause,
134    pub modifier: Vec<Spanned<Modifier>>,
135    // TODO values
136}
137impl SubSelect {
138    fn add_to_context(&self, ctx: &mut Context) {
139        self.where_clause.add_to_context(ctx);
140    }
141
142    pub fn ingest_triples<'a>(
143        &'a self,
144        builder: &mut TriplesBuilder<'a, Query>,
145    ) -> Result<(), TurtleSimpleError> {
146        self.where_clause.ingest_triples(builder)
147    }
148}
149
150#[derive(Clone, Debug, PartialEq, Eq)]
151pub enum GraphPatternNotTriples {}
152
153#[derive(Clone, Debug, PartialEq, Eq)]
154pub enum GroupGraphPatternSub {
155    Triple(Spanned<Triple>),
156    Kwd(Spanned<SparqlKeyword>, Spanned<GroupGraphPattern>),
157    Filter(Spanned<SparqlKeyword>, ()),
158    Union(
159        Spanned<GroupGraphPattern>,
160        Vec<(Spanned<SparqlKeyword>, Spanned<GroupGraphPattern>)>,
161    ),
162    GraphOrService(
163        Spanned<SparqlKeyword>,
164        Option<Spanned<SparqlKeyword>>,
165        Spanned<NamedNode>,
166        Spanned<GroupGraphPattern>,
167    ),
168    Bind(
169        Spanned<SparqlKeyword>,
170        Spanned<Token>,
171        Spanned<Bind>,
172        Spanned<Token>,
173    ),
174    Inline(Spanned<()>),
175}
176impl GroupGraphPatternSub {
177    fn add_to_context(&self, ctx: &mut Context) {
178        match self {
179            GroupGraphPatternSub::Triple(t) => t.value().set_context(ctx),
180            GroupGraphPatternSub::Kwd(_, beta) => beta.add_to_context(ctx),
181            GroupGraphPatternSub::Union(a, b) => {
182                a.add_to_context(ctx);
183                for (_, b) in b {
184                    b.add_to_context(ctx);
185                }
186            }
187            GroupGraphPatternSub::GraphOrService(_, _, _, a) => a.add_to_context(ctx),
188            _ => {}
189        }
190    }
191
192    pub fn ingest_triples<'a>(
193        &'a self,
194        builder: &mut TriplesBuilder<'a, Query>,
195    ) -> Result<(), TurtleSimpleError> {
196        match self {
197            GroupGraphPatternSub::Triple(triple) => builder.ingest(&triple)?,
198            GroupGraphPatternSub::Kwd(_, x) => x.ingest_triples(builder)?,
199            GroupGraphPatternSub::Union(x, xs) => {
200                x.ingest_triples(builder)?;
201                for (_, x) in xs {
202                    x.ingest_triples(builder)?;
203                }
204            }
205            GroupGraphPatternSub::GraphOrService(_, _, _, x) => x.ingest_triples(builder)?,
206            _ => {}
207        }
208        Ok(())
209    }
210}
211
212#[derive(Clone, Debug, PartialEq, Eq)]
213pub enum Modifier {
214    GroupBy(Spanned<SparqlKeyword>, Spanned<SparqlKeyword>, Spanned<()>),
215    Having(Spanned<SparqlKeyword>, Spanned<()>),
216    OrderBy(Spanned<SparqlKeyword>, Spanned<SparqlKeyword>, Spanned<()>),
217    LimitOffset(Spanned<SparqlKeyword>, Spanned<String>),
218}
219
220#[derive(Clone, Debug, PartialEq, Eq)]
221pub struct Query {
222    pub base: lsp_types::Url,
223    pub prefixes: Vec<Spanned<TurtlePrefix>>,
224    pub base_statement: Option<Spanned<Base>>,
225    pub kwds: QueryClause,
226    pub datasets: Vec<Spanned<DatasetClause>>,
227    pub where_clause: Spanned<WhereClause>,
228    pub modifier: Vec<Spanned<Modifier>>,
229}
230impl Query {
231    pub fn add_to_context(&self, ctx: &mut Context) {
232        self.where_clause.add_to_context(ctx);
233    }
234
235    pub fn ingest_triples<'a>(
236        &'a self,
237        builder: &mut TriplesBuilder<'a, Query>,
238    ) -> Result<(), TurtleSimpleError> {
239        self.where_clause.ingest_triples(builder)?;
240        Ok(())
241    }
242
243    pub fn set_base(&mut self, base: lsp_types::Url) {
244        self.base = self
245            .base_statement
246            .as_ref()
247            .iter()
248            .find_map(|x| match x.iri.value() {
249                NamedNode::Full(x, _) => lsp_types::Url::parse(&x).ok(),
250                _ => None,
251            })
252            .unwrap_or_else(|| base.clone());
253    }
254
255    pub fn get_base(&self) -> &lsp_types::Url {
256        &self.base
257    }
258}
259
260impl Based for Query {
261    fn get_base(&self) -> &lsp_types::Url {
262        &self.base
263    }
264
265    fn prefixes(&self) -> &[Spanned<TurtlePrefix>] {
266        &self.prefixes
267    }
268}
269
270impl Default for Query {
271    fn default() -> Self {
272        Query {
273            base: lsp_types::Url::parse("memory://somefile.sq").unwrap(),
274            base_statement: None,
275            prefixes: vec![],
276            kwds: QueryClause::Invalid,
277            datasets: vec![],
278            where_clause: Spanned(
279                WhereClause {
280                    kwd: None,
281                    ggp: Spanned(GroupGraphPattern::Invalid, 0..0),
282                },
283                0..0,
284            ),
285            modifier: vec![],
286        }
287    }
288}
289
290#[cfg(test)]
291mod tests {
292    use lang_turtle::lang::context::Context;
293    use sophia_iri::resolve::BaseIri;
294
295    use super::*;
296    use crate::lang::{parsing::parse, tokenizer::parse_tokens_str};
297
298    fn parse_sparql(inp: &str) -> Query {
299        let context = Context::new();
300        let ctx = context.ctx();
301        let (tokens, errors) = parse_tokens_str(inp);
302        println!("Tokens");
303        for t in &tokens {
304            println!("t {:?}", t);
305        }
306
307        println!("errors");
308        for t in &errors {
309            println!("e {:?}", t);
310        }
311
312        let (jsonld, errors) = parse(
313            inp,
314            lsp_types::Url::parse("memory::myFile.sq").unwrap(),
315            tokens,
316            ctx,
317        );
318        println!("errors");
319        for t in &errors {
320            println!("e {:?}", t);
321        }
322
323        jsonld.0
324    }
325
326    #[test]
327    fn simple_sparql_1() {
328        let st = r#"
329PREFIX foaf: <http://xmlns.com/foaf/0.1/>
330PREFIX  dc:  <http://purl.org/dc/elements/1.1/>
331PREFIX  ns:  <http://example.org/ns#>
332
333SELECT  ?title ?price
334{ ?x ns:price ?p .
335  ?x dc:title ?title . 
336  ?x ns:discount ?discount .
337}
338        "#;
339
340        let query = parse_sparql(st);
341        let base = BaseIri::new(query.base.to_string()).unwrap();
342        let mut builder = TriplesBuilder::new(&query, base);
343        query.ingest_triples(&mut builder).expect("builds fine");
344
345        assert_eq!(builder.triples.len(), 3);
346    }
347
348    #[test]
349    fn simple_sparql_2() {
350        let st = r#"
351PREFIX foaf: <http://xmlns.com/foaf/0.1/>
352PREFIX  dc:  <http://purl.org/dc/elements/1.1/>
353PREFIX  ns:  <http://example.org/ns#>
354
355SELECT  ?title ?price
356{ ?x ns:price ?p .
357  ?x dc:title ?title . 
358  [ # this is one triple as well
359  ] ns:discount ?discount .
360}
361        "#;
362
363        let query = parse_sparql(st);
364        let base = BaseIri::new(query.base.to_string()).unwrap();
365        let mut builder = TriplesBuilder::new(&query, base);
366        query.ingest_triples(&mut builder).expect("builds fine");
367
368        for t in &builder.triples {
369            println!("t {}", t);
370        }
371
372        assert_eq!(builder.triples.len(), 4);
373    }
374}