lang_turtle/ecs/
parse.rs

1use std::collections::HashMap;
2
3use bevy_ecs::prelude::*;
4use lsp_core::prelude::*;
5use tracing::{info, instrument};
6
7use crate::{
8    lang::{
9        context::{Context, TokenIdx},
10        parser::parse_turtle,
11        tokenizer::parse_tokens_str,
12    },
13    TurtleLang,
14};
15
16#[instrument(skip(query, commands), name = "parse_source")]
17pub fn parse_source(
18    query: Query<(Entity, &Source), (Changed<Source>, With<TurtleLang>)>,
19    mut commands: Commands,
20) {
21    for (entity, source) in &query {
22        let (tok, es) = parse_tokens_str(source.0.as_str());
23        let t = Tokens(tok);
24        commands.entity(entity).insert(t);
25        commands.entity(entity).insert(Errors(es));
26    }
27}
28
29#[instrument(skip(query, commands, old), name = "parse_turtle")]
30pub fn parse_turtle_system(
31    query: Query<
32        (Entity, &Source, &Tokens, &Label, Option<&Open>),
33        (Changed<Tokens>, With<TurtleLang>),
34    >,
35    mut commands: Commands,
36    mut old: Local<HashMap<String, (Vec<Spanned<Token>>, Context)>>,
37    config: Res<ServerConfig>,
38) {
39    if !config.config.turtle.unwrap_or(true) {
40        return;
41    }
42    for (entity, source, tokens, label, open) in &query {
43        let (ref mut old_tokens, ref mut context) = old.entry(label.to_string()).or_default();
44        context.setup_current_to_prev(
45            TokenIdx { tokens: &tokens },
46            tokens.len(),
47            TokenIdx {
48                tokens: &old_tokens,
49            },
50            old_tokens.len(),
51        );
52        // First parse it without context
53        // This assures that if the model is correct, the parser will parse it correctly
54        let empty = Context::new();
55        let (turtle, es) = parse_turtle(&label.0, tokens.0.clone(), source.0.len(), empty.ctx());
56        // If that didn't work, retry with the context
57        let (turtle, es) = es.is_empty().then_some((turtle, es)).unwrap_or_else(|| {
58            parse_turtle(&label.0, tokens.0.clone(), source.0.len(), context.ctx())
59        });
60
61        let es: Vec<_> = es.into_iter().map(|e| (e.map(|PToken(t, _)| t))).collect();
62
63        info!(
64            "{} triples ({} errors)",
65            turtle.value().triples.len(),
66            es.len()
67        );
68        if open.is_some() {
69            for e in &es {
70                info!("Error {:?}", e);
71            }
72        }
73
74        *old_tokens = tokens.0.clone();
75        context.clear();
76        turtle.set_context(context);
77
78        if es.is_empty() {
79            let element = Element::<TurtleLang>(turtle);
80            commands
81                .entity(entity)
82                .insert((element, Errors(es)))
83                .remove::<Dirty>();
84        } else {
85            let element = Element::<TurtleLang>(turtle);
86            commands.entity(entity).insert((Errors(es), element, Dirty));
87        }
88    }
89}
90
91// #[instrument(skip(query, commands), name = "derive_triples")]
92pub fn derive_triples(
93    query: Query<(Entity, &Element<TurtleLang>), (Changed<Element<TurtleLang>>, With<TurtleLang>)>,
94    mut commands: Commands,
95) {
96    for (entity, turtle) in &query {
97        if let Ok(tripl) = turtle.0.get_simple_triples() {
98            let triples: Vec<_> = tripl.iter().map(|x| x.to_owned()).collect();
99            commands.entity(entity).insert(Triples(triples));
100        }
101    }
102}