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 }
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}