swls_lang_turtle/ecs/
parse.rs1use std::collections::HashMap;
2
3use bevy_ecs::prelude::*;
4use rdf_parsers::{turtle::SyntaxKind, PrevParseInfo};
5use rowan::NodeOrToken;
6use swls_core::prelude::*;
7use swls_lang_rdf_base::traits::TurtleExt;
8use tracing::instrument;
9
10use crate::{
11 lang::parser::{parse_new, TurtleNode},
12 TurtleLang,
13};
14
15fn extract_cst_tokens(
17 syntax: &TurtleNode,
18 source: &str,
19) -> (Vec<Spanned<rowan::SyntaxKind>>, Vec<Spanned<String>>) {
20 let mut tokens = Vec::new();
21 let mut comments = Vec::new();
22
23 for node_or_token in syntax.descendants_with_tokens() {
24 if let NodeOrToken::Token(t) = node_or_token {
25 let kind = t.kind();
26 if kind == SyntaxKind::WhiteSpace {
27 continue;
28 }
29 let range = t.text_range();
30 let span = usize::from(range.start())..usize::from(range.end());
31 let rowan_kind = rowan::SyntaxKind(kind as u16);
32
33 if kind == SyntaxKind::Comment {
34 let text = t.text().to_string();
35 comments.push(spanned(text, span.clone()));
36 }
37
38 tokens.push(spanned(rowan_kind, span));
39 }
40 }
41
42 let src_len = source.len();
44 tokens.retain(|t| t.span().start <= src_len && t.span().end <= src_len);
45 comments.retain(|c| c.span().start <= src_len && c.span().end <= src_len);
46
47 (tokens, comments)
48}
49
50#[instrument(skip(query, commands, prev_infos, config), name = "parse_turtle")]
51pub fn parse_turtle_system(
52 query: Query<(Entity, &Source, &Label, Option<&Open>), (Changed<Source>, With<TurtleLang>)>,
53 mut commands: Commands,
54 mut prev_infos: Local<HashMap<String, PrevParseInfo>>,
55 config: Res<ServerConfig>,
56) {
57 if !config.config.turtle.unwrap_or(true) {
58 return;
59 }
60 for (entity, source, label, open) in &query {
61 let span = tracing::info_span!("parse_turtle", label = label.to_string());
62 let _enter = span.enter();
63
64 let prev = if open.is_none() {
66 prev_infos.get(label.as_str())
67 } else {
68 None
69 };
70 let (turtle, errors, new_prev, syntax, node) =
71 parse_new(source.0.as_str(), label.as_str(), prev);
72
73 tracing::debug!(
74 "{} triples ({} parse errors)",
75 turtle.triples.len(),
76 errors.len()
77 );
78 if open.is_some() {
79 for e in &errors {
80 tracing::debug!("Parse error {:?}: {}", e.range, e.msg);
81 }
82 }
83
84 prev_infos.insert(label.to_string(), new_prev);
85
86 let (cst_tokens, cst_comments) = extract_cst_tokens(&syntax, source.0.as_str());
87
88 let span = 0..source.0.len();
89 let element = Element(swls_core::prelude::spanned(turtle, span));
90 if errors.is_empty() {
91 commands
92 .entity(entity)
93 .insert((
94 element,
95 Errors(errors),
96 CstTokens(cst_tokens),
97 Comments(cst_comments),
98 ))
99 .insert(Wrapped(node))
100 .remove::<Dirty>();
101 } else {
102 commands.entity(entity).insert((
103 element,
104 Errors(errors),
105 CstTokens(cst_tokens),
106 Comments(cst_comments),
107 Dirty,
108 ));
109 }
110 }
111}
112
113pub fn derive_triples_system<L: Component>(
119 query: Query<(Entity, &Label, &Element), (Changed<Element>, With<L>)>,
120 mut commands: Commands,
121) {
122 use std::sync::Arc;
123
124 for (entity, label, element) in &query {
125 match element.0.value().get_simple_triples() {
126 Ok(tripl) => {
127 let triples: Vec<_> = tripl.iter().map(|x| x.to_owned()).collect();
128 commands.entity(entity).insert(Triples(Arc::new(triples)));
129 }
130 Err(e) => {
131 tracing::warn!("derive_triples: error for {}: {:?}", label.as_str(), e);
132 }
133 }
134 }
135}