lang_turtle/lang/
model.rs

1use std::{collections::HashSet, fmt::Display, ops::Range};
2
3use lsp_core::prelude::{MyQuad, MyTerm, Spanned, StringStyle, Triples2};
4use sophia_iri::resolve::{BaseIri, IriParseError};
5use tracing::info;
6
7use super::context::{Context, ContextKind};
8
9pub trait Based {
10    fn get_base(&self) -> &lsp_types::Url;
11    fn prefixes(&self) -> &[Spanned<TurtlePrefix>];
12}
13
14#[derive(Clone, Debug, PartialEq, Eq)]
15pub struct Variable(pub String, pub usize);
16
17#[derive(Clone, Debug, PartialEq, Eq)]
18pub enum Literal {
19    RDF(RDFLiteral),
20    Boolean(bool),
21    Numeric(String),
22}
23
24impl Literal {
25    pub fn plain_string(&self) -> String {
26        match self {
27            Literal::RDF(s) => s.plain_string(),
28            Literal::Boolean(x) => x.to_string(),
29            Literal::Numeric(x) => x.clone(),
30        }
31    }
32}
33impl Display for Literal {
34    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35        match self {
36            Literal::RDF(x) => x.fmt(f),
37            Literal::Boolean(x) => write!(f, "{}", x),
38            Literal::Numeric(x) => write!(f, "{}", x),
39        }
40    }
41}
42
43#[derive(Clone, Debug, PartialEq, Eq)]
44pub struct RDFLiteral {
45    pub value: String,
46    pub quote_style: StringStyle,
47    pub lang: Option<String>,
48    pub ty: Option<NamedNode>,
49    // Span of tokens
50    pub idx: usize,
51    pub len: usize,
52}
53
54impl RDFLiteral {
55    pub fn plain_string(&self) -> String {
56        self.value.to_string()
57    }
58}
59
60impl Display for RDFLiteral {
61    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62        let quote = match self.quote_style {
63            StringStyle::DoubleLong => "\"\"\"",
64            StringStyle::Double => "\"",
65            StringStyle::SingleLong => "'''",
66            StringStyle::Single => "'",
67        };
68        match (&self.lang, &self.ty) {
69            (None, None) => write!(f, "{}{}{}", quote, self.value, quote),
70            (None, Some(t)) => write!(f, "{}{}{}^^{}", quote, self.value, quote, t),
71            (Some(l), None) => write!(f, "{}{}{}@{}", quote, self.value, quote, l),
72            (Some(l), Some(t)) => write!(f, "{}{}{}@{}^^{}", quote, self.value, quote, l, t),
73        }
74    }
75}
76
77#[derive(Clone, Debug, PartialEq, Eq)]
78pub enum NamedNode {
79    Full(String, usize),
80    Prefixed {
81        prefix: String,
82        value: String,
83        idx: usize,
84    },
85    A(usize),
86    Invalid,
87}
88
89impl NamedNode {
90    pub fn expand<T: Based>(&self, turtle: &T) -> Option<String> {
91        let base = turtle.get_base();
92        let out = self.expand_step(turtle, HashSet::new())?;
93
94        let url = base.join(&out).ok()?;
95
96        Some(url.to_string())
97    }
98
99    pub fn expand_step<'a, T: Based>(
100        &'a self,
101        turtle: &T,
102        mut done: HashSet<&'a str>,
103    ) -> Option<String> {
104        match self {
105            Self::Full(s, _) => s.clone().into(),
106            Self::Prefixed {
107                prefix,
108                value,
109                idx: _,
110            } => {
111                if done.contains(prefix.as_str()) {
112                    return None;
113                }
114                done.insert(prefix);
115                let prefix = turtle
116                    .prefixes()
117                    .iter()
118                    .find(|x| x.prefix.as_str() == prefix.as_str())?;
119
120                let expaned = prefix.value.expand_step(turtle, done)?;
121                Some(format!("{}{}", expaned, value))
122            }
123            Self::A(_) => Some("http://www.w3.org/1999/02/22-rdf-syntax-ns#type".to_string()),
124            Self::Invalid => None,
125        }
126    }
127}
128
129impl Display for NamedNode {
130    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
131        match self {
132            NamedNode::Full(x, _) => write!(f, "<{}>", x),
133            NamedNode::Prefixed {
134                prefix,
135                value,
136                idx: _,
137            } => write!(f, "{}:{}", prefix, value),
138            NamedNode::A(_) => write!(f, "a"),
139            NamedNode::Invalid => write!(f, "invalid"),
140        }
141    }
142}
143
144#[derive(Clone, Debug, PartialEq, Eq)]
145pub enum BlankNode {
146    Named(String, usize),
147    Unnamed(Vec<Spanned<PO>>, usize, usize),
148    Invalid,
149}
150
151fn rev_range(range: &std::ops::Range<usize>, len: usize) -> std::ops::Range<usize> {
152    (len - range.end)..(len - range.start)
153}
154
155impl BlankNode {
156    pub fn fix_spans(&mut self, len: usize) {
157        match self {
158            BlankNode::Unnamed(ref mut pos, _, _) => {
159                pos.iter_mut().for_each(|span| {
160                    span.1 = rev_range(&span.1, len);
161                    span.0.fix_spans(len);
162                });
163            }
164            _ => {}
165        }
166    }
167}
168
169impl Display for BlankNode {
170    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
171        match self {
172            BlankNode::Named(x, _) => write!(f, "_:{}", x),
173            BlankNode::Unnamed(pos, _, _) => {
174                if pos.len() == 0 {
175                    write!(f, "[ ]")
176                } else {
177                    write!(f, "[ ")?;
178
179                    for po in pos {
180                        write!(f, "{} ;", po.value())?;
181                    }
182
183                    write!(f, " ]")
184                }
185            }
186            BlankNode::Invalid => write!(f, "invalid"),
187        }
188    }
189}
190
191#[derive(Clone, Debug, PartialEq, Eq)]
192pub enum Term {
193    Literal(Literal),
194    BlankNode(BlankNode),
195    NamedNode(NamedNode),
196    Collection(Vec<Spanned<Term>>),
197    Variable(Variable),
198    Invalid,
199}
200
201impl Term {
202    pub fn set_context(&self, ctx: &mut Context, kind: ContextKind) {
203        match self {
204            Term::Literal(Literal::RDF(RDFLiteral { idx, len, .. })) => {
205                for i in *idx..*idx + *len {
206                    ctx.add(i, kind);
207                }
208            }
209
210            Term::BlankNode(BlankNode::Unnamed(pos, start, end)) => {
211                ctx.add(*start, kind);
212                ctx.add(*end, kind);
213                for po in pos {
214                    po.set_context(ctx);
215                }
216            }
217            Term::BlankNode(BlankNode::Named(_, idx))
218            | Term::Variable(Variable(_, idx))
219            | Term::NamedNode(NamedNode::Full(_, idx))
220            | Term::NamedNode(NamedNode::A(idx))
221            | Term::NamedNode(NamedNode::Prefixed { idx, .. }) => ctx.add(*idx, kind),
222            _ => {}
223        }
224    }
225    pub fn fix_spans(&mut self, len: usize) {
226        match self {
227            Term::BlankNode(bn) => bn.fix_spans(len),
228            Term::Collection(pos) => {
229                pos.iter_mut().for_each(|span| {
230                    span.1 = rev_range(&span.1, len);
231                    span.0.fix_spans(len);
232                });
233            }
234            _ => {}
235        }
236    }
237
238    pub fn named_node(&self) -> Option<&NamedNode> {
239        match self {
240            Term::NamedNode(nn) => Some(&nn),
241            _ => None,
242        }
243    }
244
245    pub fn is_subject(&self) -> bool {
246        match self {
247            Term::BlankNode(_) => true,
248            Term::Variable(_) => true,
249            Term::NamedNode(NamedNode::A(_)) => false,
250            Term::NamedNode(_) => true,
251            Term::Invalid => true,
252            Term::Collection(_) => true,
253            _ => false,
254        }
255    }
256    pub fn is_predicate(&self) -> bool {
257        match self {
258            Term::NamedNode(_) => true,
259            Term::Variable(_) => true,
260            Term::Invalid => true,
261            _ => false,
262        }
263    }
264
265    pub fn is_object(&self) -> bool {
266        match self {
267            Term::NamedNode(NamedNode::A(_)) => false,
268            Term::Variable(_) => true,
269            Term::Invalid => true,
270            Term::Collection(_) => true,
271            _ => true,
272        }
273    }
274    pub fn is_variable(&self) -> bool {
275        match self {
276            Term::Variable(_) => true,
277            Term::Invalid => true,
278            _ => false,
279        }
280    }
281    pub fn ty(&self) -> &'static str {
282        match self {
283            Term::Literal(_) => "literal",
284            Term::BlankNode(_) => "blank node",
285            Term::NamedNode(_) => "named node",
286            Term::Collection(_) => "collection",
287            Term::Invalid => "invalid",
288            Term::Variable(_) => "variable",
289        }
290    }
291    pub fn expand<T: Based>(&self, turtle: &T) -> Option<String> {
292        self.named_node()?.expand(turtle)
293    }
294    pub fn expand_step<'a, T: Based>(
295        &'a self,
296        turtle: &T,
297        done: HashSet<&'a str>,
298    ) -> Option<String> {
299        self.named_node()?.expand_step(turtle, done)
300    }
301}
302
303impl Display for Term {
304    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
305        match self {
306            Term::Literal(l) => l.fmt(f),
307            Term::BlankNode(b) => b.fmt(f),
308            Term::NamedNode(n) => n.fmt(f),
309            Term::Collection(n) => {
310                write!(f, "( ")?;
311                for l in n {
312                    l.fmt(f)?;
313                }
314                write!(f, "  )")?;
315                Ok(())
316            }
317            Term::Invalid => write!(f, "invalid"),
318            Term::Variable(x) => write!(f, "{}", x.0),
319        }
320    }
321}
322
323#[derive(Clone, Debug, PartialEq, Eq)]
324pub struct Triple {
325    pub subject: Spanned<Term>,
326    pub po: Vec<Spanned<PO>>,
327}
328
329impl Triple {
330    pub fn fix_spans(&mut self, len: usize) {
331        self.subject.1 = rev_range(&self.subject.1, len);
332        self.subject.0.fix_spans(len);
333
334        self.po.iter_mut().for_each(|span| {
335            span.1 = rev_range(&span.1, len);
336            span.0.fix_spans(len);
337        });
338    }
339
340    pub fn set_context(&self, ctx: &mut Context) {
341        self.subject.set_context(ctx, ContextKind::Subject);
342
343        for po in &self.po {
344            po.set_context(ctx);
345        }
346    }
347}
348
349impl Display for Triple {
350    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
351        write!(f, "{} {}", self.subject.value(), self.po[0].value())?;
352
353        for po in &self.po[1..] {
354            write!(f, "; {}", po.value())?;
355        }
356
357        write!(f, ".")
358    }
359}
360
361#[derive(Clone, Debug, PartialEq, Eq)]
362pub struct PO {
363    pub predicate: Spanned<Term>,
364    pub object: Vec<Spanned<Term>>,
365}
366impl PO {
367    pub fn fix_spans(&mut self, len: usize) {
368        self.predicate.1 = rev_range(&self.predicate.1, len);
369        self.predicate.0.fix_spans(len);
370
371        self.object.iter_mut().for_each(|span| {
372            span.1 = rev_range(&span.1, len);
373            span.0.fix_spans(len);
374        });
375    }
376
377    pub fn set_context(&self, ctx: &mut Context) {
378        self.predicate.set_context(ctx, ContextKind::Predicate);
379
380        for o in &self.object {
381            o.set_context(ctx, ContextKind::Object);
382        }
383    }
384}
385
386impl Display for PO {
387    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
388        write!(f, "{} {}", self.predicate.value(), self.object[0].value())?;
389
390        for po in &self.object[1..] {
391            write!(f, ", {}", po.value())?;
392        }
393
394        Ok(())
395    }
396}
397
398#[derive(Clone, Debug, PartialEq, Eq)]
399pub struct Base(pub Range<usize>, pub Spanned<NamedNode>);
400impl Display for Base {
401    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
402        write!(f, "@base {} .", self.1.value())
403    }
404}
405impl Base {
406    pub fn fix_spans(&mut self, len: usize) {
407        self.1 .1 = rev_range(&self.1 .1, len);
408    }
409    pub fn resolve_location(&mut self, location: &lsp_types::Url) {
410        match self.1.value_mut() {
411            NamedNode::Full(s, _) => {
412                if let Some(ns) = location.join(&s).ok() {
413                    *s = ns.to_string();
414                }
415            }
416            _ => {}
417        }
418    }
419}
420#[derive(Clone, Debug, PartialEq, Eq)]
421pub struct TurtlePrefix {
422    pub span: Range<usize>,
423    pub prefix: Spanned<String>,
424    pub value: Spanned<NamedNode>,
425}
426impl TurtlePrefix {
427    fn shorten<T: Based>(&self, turtle: &T, url: &str) -> Option<String> {
428        let prefix_url = self.value.expand(turtle)?;
429        let short = url.strip_prefix(&prefix_url)?;
430        Some(format!("{}:{}", self.prefix.value(), short))
431    }
432
433    pub fn fix_spans(&mut self, len: usize) {
434        self.span = rev_range(&self.span, len);
435        self.prefix.1 = rev_range(&self.prefix.1, len);
436        self.value.1 = rev_range(&self.value.1, len);
437    }
438}
439impl Display for TurtlePrefix {
440    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
441        write!(
442            f,
443            "@prefix {}: {} .",
444            self.prefix.value(),
445            self.value.value()
446        )
447    }
448}
449
450#[derive(Debug)]
451pub enum TurtleSimpleError {
452    Parse(IriParseError),
453    UnexpectedBase(&'static str),
454    UnexpectedBaseString(String),
455}
456
457#[derive(Clone, Debug, PartialEq, Eq)]
458pub struct Turtle {
459    pub base: Option<Spanned<Base>>,
460    pub set_base: lsp_types::Url,
461    pub prefixes: Vec<Spanned<TurtlePrefix>>,
462    pub triples: Vec<Spanned<Triple>>,
463}
464impl Based for Turtle {
465    fn get_base(&self) -> &lsp_types::Url {
466        &self.set_base
467    }
468
469    fn prefixes(&self) -> &[Spanned<TurtlePrefix>] {
470        &self.prefixes
471    }
472}
473
474impl Turtle {
475    pub fn fix_spans(&mut self, len: usize) {
476        self.base.iter_mut().for_each(|base| {
477            base.1 = rev_range(&base.1, len);
478            base.0.fix_spans(len);
479        });
480        self.prefixes.iter_mut().for_each(|base| {
481            base.1 = rev_range(&base.1, len);
482            base.0.fix_spans(len);
483        });
484        self.triples.iter_mut().for_each(|base| {
485            base.1 = rev_range(&base.1, len);
486            base.0.fix_spans(len);
487        });
488    }
489
490    pub fn into_triples<'a>(&self, triples: Vec<MyQuad<'a>>) -> Triples2<'a> {
491        let base = match &self.base {
492            Some(Spanned(Base(_, Spanned(named_node, span)), _)) => named_node
493                .expand_step(self, HashSet::new())
494                .map(|st| MyTerm::named_node(st, span.clone())),
495            None => Some(MyTerm::named_node(self.set_base.as_str().to_string(), 0..0)),
496        };
497
498        let base_url = self.set_base.to_string();
499        Triples2 {
500            triples,
501            base,
502            base_url,
503        }
504    }
505}
506
507pub struct TriplesBuilder<'a, T> {
508    pub triples: Vec<MyQuad<'a>>,
509    blank_node: Box<dyn FnMut(std::ops::Range<usize>) -> MyTerm<'a>>,
510    base: BaseIri<String>,
511    based: &'a T,
512}
513
514impl<'a, T: Based> TriplesBuilder<'a, T> {
515    pub fn new(based: &'a T, base: BaseIri<String>) -> Self {
516        let mut count = 0;
517        let blank_node = Box::new(move |span: std::ops::Range<usize>| {
518            count += 1;
519            MyTerm::blank_node(format!("internal_bnode_{}", count), span)
520        });
521        Self {
522            triples: vec![],
523            blank_node,
524            base,
525            based,
526        }
527    }
528
529    fn handle_po(
530        &mut self,
531        pos: &'a [Spanned<PO>],
532        span: std::ops::Range<usize>,
533        subject: MyTerm<'a>,
534    ) -> Result<(), TurtleSimpleError> {
535        if pos.is_empty() {
536            let predicate = MyTerm::named_node("TestPredicate", 0..0);
537            let object = MyTerm::named_node("TestObject", 0..0);
538
539            let quad = MyQuad {
540                subject: subject.clone(),
541                predicate: predicate.clone(),
542                object,
543                span: span.clone(),
544            };
545
546            self.triples.push(quad);
547        }
548        let mut first = true;
549
550        for Spanned(PO { predicate, object }, span2) in pos.iter() {
551            let this_span = if first {
552                first = false;
553                span.clone()
554            } else {
555                span2.clone()
556            };
557
558            let predicate = if let Ok(node) = predicate
559                .value()
560                .expand_step(self.based, HashSet::new())
561                .ok_or(TurtleSimpleError::UnexpectedBase(
562                    "Expected valid named node for object",
563                ))
564                .and_then(|n| {
565                    self.base
566                        .resolve(n.as_str())
567                        .map_err(|e| TurtleSimpleError::Parse(e))
568                })
569                .map(|x| x.unwrap())
570            {
571                MyTerm::named_node(node, predicate.span().clone())
572            } else {
573                MyTerm::invalid(predicate.span().clone())
574            };
575
576            let mut first_object = true;
577            for o in object.iter() {
578                let this_span = if first_object {
579                    first_object = false;
580                    this_span.clone()
581                } else {
582                    o.span().clone()
583                };
584                let object = self.term_to_my_term(Ok(o.as_ref()))?;
585
586                let quad = MyQuad {
587                    subject: subject.clone(),
588                    predicate: predicate.clone(),
589                    object,
590                    span: this_span,
591                };
592
593                self.triples.push(quad);
594            }
595        }
596        Ok(())
597    }
598
599    fn term_to_my_term(
600        &mut self,
601        term: Result<Spanned<&'a Term>, MyTerm<'a>>,
602    ) -> Result<MyTerm<'a>, TurtleSimpleError> {
603        let object = match term {
604            Ok(Spanned(Term::Variable(Variable(var, _)), span)) => MyTerm::variable(var, span),
605            Ok(Spanned(Term::NamedNode(NamedNode::Invalid), span)) => MyTerm::invalid(span),
606            Ok(Spanned(Term::NamedNode(nn), span)) => MyTerm::named_node(
607                nn.expand_step(self.based, HashSet::new())
608                    .ok_or(TurtleSimpleError::UnexpectedBase(
609                        "Expected valid named node for object",
610                    ))
611                    .and_then(|n| {
612                        self.base
613                            .resolve(n.as_str())
614                            .map_err(|e| TurtleSimpleError::Parse(e))
615                    })
616                    .map(|x| x.unwrap())?,
617                span,
618            ),
619            Ok(Spanned(Term::Literal(literal), span)) => {
620                MyTerm::literal(literal.plain_string(), span)
621            }
622            Ok(Spanned(Term::BlankNode(bn), span)) => match bn {
623                BlankNode::Named(v, _) => MyTerm::blank_node(v, span),
624                BlankNode::Unnamed(v, _, _) => {
625                    let out = (self.blank_node)(span.clone());
626                    self.handle_po(v, span, out.clone())?;
627                    out
628                }
629                BlankNode::Invalid => {
630                    return Err(TurtleSimpleError::UnexpectedBase(
631                        "Unexpected invalid blank for object",
632                    ))
633                }
634            },
635            Ok(Spanned(Term::Collection(terms), span)) => self.handle_collection(&terms, span)?,
636            Ok(Spanned(Term::Invalid, span)) => MyTerm::invalid(span),
637            Err(x) => x,
638        };
639
640        Ok(object)
641    }
642
643    fn handle_collection(
644        &mut self,
645        collection: &'a [Spanned<Term>],
646        span: std::ops::Range<usize>,
647    ) -> Result<MyTerm<'a>, TurtleSimpleError> {
648        let mut prev = MyTerm::named_node(
649            "http://www.w3.org/1999/02/22-rdf-syntax-ns#nil",
650            span.end..span.end,
651        );
652
653        for Spanned(term, s) in collection.iter().rev() {
654            let next = (self.blank_node)(s.clone());
655
656            let quad = MyQuad {
657                subject: next.clone(),
658                predicate: MyTerm::named_node(
659                    "http://www.w3.org/1999/02/22-rdf-syntax-ns#first",
660                    prev.span.start..prev.span.start,
661                ),
662                object: self.term_to_my_term(Ok(Spanned(term, s.clone())))?,
663                span: span.clone(),
664            };
665
666            self.triples.push(quad);
667
668            let quad = MyQuad {
669                subject: next.clone(),
670                predicate: MyTerm::named_node(
671                    "http://www.w3.org/1999/02/22-rdf-syntax-ns#rest",
672                    s.start..s.start,
673                ),
674                object: prev,
675                span: s.clone(),
676            };
677
678            self.triples.push(quad);
679            prev = next;
680        }
681
682        Ok(prev)
683    }
684
685    pub fn ingest(
686        &mut self,
687        Spanned(ref triple, span): &'a Spanned<Triple>,
688    ) -> Result<(), TurtleSimpleError> {
689        let sub = match triple.subject.value() {
690            Term::BlankNode(BlankNode::Named(vs, _)) => {
691                MyTerm::blank_node(vs, triple.subject.span().clone())
692            }
693            Term::BlankNode(BlankNode::Unnamed(vs, _, _)) => {
694                let out = (self.blank_node)(triple.subject.span().clone());
695                self.handle_po(&vs, triple.subject.span().clone(), out.clone())?;
696                out
697            }
698            Term::NamedNode(NamedNode::Invalid) => MyTerm::invalid(triple.subject.span().clone()),
699            Term::NamedNode(nn) => MyTerm::named_node(
700                nn.expand_step(self.based, HashSet::new())
701                    .ok_or(TurtleSimpleError::UnexpectedBase(
702                        "Expected valid named node for object",
703                    ))
704                    .and_then(|n| {
705                        self.base
706                            .resolve(n.as_str())
707                            .map_err(|e| TurtleSimpleError::Parse(e))
708                    })
709                    .map(|x| x.unwrap())?,
710                triple.subject.span().clone(),
711            ),
712            Term::Invalid => MyTerm::invalid(triple.subject.span().clone()),
713            Term::Variable(var) => MyTerm::variable(&var.0, triple.subject.span().clone()),
714
715            x => {
716                info!("Failed, unexpected {}", x.ty());
717                return Err(TurtleSimpleError::UnexpectedBaseString(format!(
718                    "Unexpected {}",
719                    x.ty()
720                )));
721            }
722        };
723
724        self.handle_po(&triple.po, span.clone(), sub.clone())?;
725
726        Ok(())
727    }
728}
729
730impl Turtle {
731    pub fn empty(location: &lsp_types::Url) -> Self {
732        Self::new(None, Vec::new(), Vec::new(), location)
733    }
734
735    pub fn get_simple_triples<'a>(&'a self) -> Result<Triples2<'a>, TurtleSimpleError> {
736        let base = match &self.base {
737            Some(Spanned(Base(_, Spanned(named_node, _)), _)) => {
738                let nn = named_node.expand_step(self, HashSet::new()).ok_or(
739                    TurtleSimpleError::UnexpectedBase("Expected valid named node base"),
740                )?;
741                BaseIri::new(nn).map_err(TurtleSimpleError::Parse)?
742            }
743            None => BaseIri::new(self.set_base.as_str().to_string())
744                .map_err(TurtleSimpleError::Parse)?,
745        };
746
747        let mut builder = TriplesBuilder::new(self, base);
748
749        for t in &self.triples {
750            builder.ingest(&t)?;
751        }
752
753        Ok(self.into_triples(builder.triples))
754    }
755}
756
757impl Turtle {
758    pub fn new(
759        mut base: Option<Spanned<Base>>,
760        prefixes: Vec<Spanned<TurtlePrefix>>,
761        triples: Vec<Spanned<Triple>>,
762        location: &lsp_types::Url,
763    ) -> Self {
764        if let Some(b) = base.as_mut() {
765            b.resolve_location(location);
766        }
767        Self {
768            base,
769            prefixes,
770            triples,
771            set_base: location.clone(),
772        }
773    }
774
775    pub fn set_context(&self, ctx: &mut Context) {
776        for t in &self.triples {
777            t.set_context(ctx);
778        }
779    }
780
781    pub fn get_base(&self) -> &lsp_types::Url {
782        &self.set_base
783    }
784
785    pub fn shorten(&self, url: &str) -> Option<String> {
786        self.prefixes
787            .iter()
788            .flat_map(|pref| pref.shorten(self, url))
789            .next()
790    }
791}
792
793impl Display for Turtle {
794    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
795        if let Some(b) = &self.base {
796            writeln!(f, "{}", b.value())?;
797        }
798
799        self.prefixes
800            .iter()
801            .map(|x| x.value())
802            .try_for_each(|x| writeln!(f, "{}", x))?;
803
804        self.triples
805            .iter()
806            .map(|x| x.value())
807            .try_for_each(|x| writeln!(f, "{}", x))?;
808
809        Ok(())
810    }
811}
812
813#[cfg(test)]
814mod test {
815    use std::{collections::HashSet, str::FromStr};
816
817    use lsp_core::prelude::{spanned, MyQuad, Spanned};
818
819    use super::Turtle;
820    use crate::lang::{context::Context, parser as parser2, tokenizer::parse_tokens_str_safe};
821
822    #[derive(Debug)]
823    pub enum Err {
824        Tokenizing,
825    }
826
827    fn parse_turtle(
828        inp: &str,
829        url: &lsp_types::Url,
830    ) -> Result<(Turtle, Vec<Spanned<String>>), Err> {
831        let context = Context::new();
832        let ctx = context.ctx();
833        let tokens = parse_tokens_str_safe(inp).map_err(|e| Err::Tokenizing)?;
834
835        let mut comments: Vec<_> = tokens
836            .iter()
837            .filter(|x| x.0.is_comment())
838            .cloned()
839            .map(|x| spanned(x.0.to_comment(), x.1))
840            .collect();
841        comments.sort_by_key(|x| x.1.start);
842
843        let (turtle, errs) = parser2::parse_turtle(&url, tokens, inp.len(), ctx);
844        for e in errs {
845            println!("Error {:?}", e);
846        }
847
848        Ok((turtle.into_value(), comments))
849    }
850
851    #[test]
852    fn easy_triples() {
853        let txt = r#"
854@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
855@prefix foaf: <http://xmlns.com/foaf/0.1/> .
856# @base <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
857
858[] a foaf:Name;
859   foaf:knows <abc>;.
860"#;
861
862        let url = lsp_types::Url::from_str("http://example.com/ns#").unwrap();
863        let (output, _) = parse_turtle(txt, &url).expect("Simple");
864        let triples = output.get_simple_triples().expect("Triples found");
865
866        assert_eq!(triples.triples.len(), 3);
867        println!("{:?}", triples);
868    }
869
870    #[test]
871    fn easy_triples_2() {
872        let txt = r#"
873@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
874@prefix foaf: <http://xmlns.com/foaf/0.1/> .
875# @base <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
876
877[ foaf:knows <abc>; ] 
878    a foaf:Name;
879    foaf:knows [
880        a foaf:Name;
881        foaf:knows [
882            a foaf:Name; ] ].
883"#;
884
885        let url = lsp_types::Url::from_str("http://example.com/ns#").unwrap();
886        let (output, _) = parse_turtle(txt, &url).expect("Simple");
887        let triples = output.get_simple_triples().expect("Triples found");
888
889        assert_eq!(triples.triples.len(), 6);
890    }
891
892    #[test]
893    fn triples_collection() {
894        let txt = r#"
895<e> <pred> (<a> <b> <c>).
896"#;
897
898        let url = lsp_types::Url::from_str("http://example.com/ns#").unwrap();
899        let (output, _) = parse_turtle(txt, &url).expect("Simple collection");
900        let triples = output.get_simple_triples().expect("Triples found");
901
902        let a: &Vec<MyQuad<'_>> = &triples;
903
904        let quads: HashSet<String> = a
905            .iter()
906            .map(|triple| format!("{} {} {}.", triple.subject, triple.predicate, triple.object))
907            .collect();
908
909        let expected_quads: HashSet<String> = "<http://example.com/e> <http://example.com/pred> _:internal_bnode_3.
910_:internal_bnode_3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:internal_bnode_2.
911_:internal_bnode_3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> <http://example.com/a>.
912_:internal_bnode_2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:internal_bnode_1.
913_:internal_bnode_2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> <http://example.com/b>.
914_:internal_bnode_1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil>.
915_:internal_bnode_1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> <http://example.com/c>.".split("\n").map(|x|x.trim()).map(String::from).collect();
916
917        for t in &quads {
918            println!("{}", t);
919        }
920        assert_eq!(quads, expected_quads);
921
922        println!("triples {:?}", triples);
923
924        assert_eq!(triples.triples.len(), 7);
925    }
926
927    #[test]
928    fn owl_is_valid() {
929        let txt = include_str!("../../../lov/prefixes/owl.ttl");
930
931        let url = lsp_types::Url::from_str("http://example.com/ns#").unwrap();
932        let (output, _) = parse_turtle(txt, &url).expect("Simple collection");
933        let triples = output.get_simple_triples().expect("Triples found");
934    }
935
936    #[test]
937    fn owl_is_valid_2() {
938        let txt = r#"
939@prefix dc:    <http://purl.org/dc/elements/1.1/> .
940@prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#> .
941@prefix owl:   <http://www.w3.org/2002/07/owl#> .
942@prefix xsd:   <http://www.w3.org/2001/XMLSchema#> .
943@prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
944@prefix xml:   <http://www.w3.org/XML/1998/namespace> .
945@prefix grddl: <http://www.w3.org/2003/g/data-view#> .
946
947<http://www.w3.org/2002/07/owl>
948        a                              owl:Ontology ;
949        rdfs:comment                   "\r\n  This ontology partially describes the built-in " ; .
950            "#;
951
952        let url = lsp_types::Url::from_str("http://example.com/ns#").unwrap();
953        let (output, _) = parse_turtle(txt, &url).expect("Simple collection");
954        output.get_simple_triples().expect("Triples found");
955    }
956}