Skip to main content

swls_lang_turtle/lang/
parser.rs

1use rdf_parsers::{
2    model::Turtle,
3    turtle::{convert::convert, Lang, Rule, SyntaxKind},
4    IncrementalBias, PrevParseInfo,
5};
6use swls_core::prelude::SimpleDiagnostic;
7
8#[derive(Debug, Clone)]
9pub struct TurtleParseError {
10    pub range: std::ops::Range<usize>,
11    pub msg: String,
12}
13
14impl From<TurtleParseError> for SimpleDiagnostic {
15    fn from(e: TurtleParseError) -> Self {
16        SimpleDiagnostic::new(e.range, e.msg)
17    }
18}
19
20impl From<&TurtleParseError> for SimpleDiagnostic {
21    fn from(e: &TurtleParseError) -> Self {
22        SimpleDiagnostic::new(e.range.clone(), e.msg.clone())
23    }
24}
25
26pub type TurtleNode = rowan::SyntaxNode<Lang>;
27
28/// Parse a Turtle document using the A* error-recovering parser.
29///
30/// Returns the model, parse errors, incremental parse state, and the syntax node.
31pub fn parse_new(
32    source: &str,
33    base_url: &str,
34    prev: Option<&PrevParseInfo>,
35) -> (
36    Turtle,
37    Vec<TurtleParseError>,
38    PrevParseInfo,
39    TurtleNode,
40    rowan::GreenNode,
41) {
42    let (parse, prev_info) = rdf_parsers::parse_incremental(
43        Rule::new(SyntaxKind::TurtleDoc),
44        source,
45        prev,
46        IncrementalBias::default(),
47    );
48
49    let node: TurtleNode = parse.syntax::<Lang>();
50    let mut model = convert(&node);
51    model.set_base = Some(base_url.to_string());
52
53    let errors = collect_errors(&node);
54    (model, errors, prev_info, node, parse.green_node)
55}
56
57pub fn collect_errors(node: &TurtleNode) -> Vec<TurtleParseError> {
58    use rowan::NodeOrToken;
59    let mut errors = Vec::new();
60    let mut stack = vec![node.clone()];
61    while let Some(current) = stack.pop() {
62        for child in current.children_with_tokens() {
63            match child {
64                NodeOrToken::Node(n) => {
65                    if n.kind() == SyntaxKind::Error {
66                        let range = rdf_parsers::effective_error_span::<Lang>(&n);
67                        let msg = n
68                            .parent()
69                            .map(|p| format!("Expected: {:?}", p.kind()))
70                            .unwrap_or_else(|| format!("Unexpected: {}", n.text()));
71                        errors.push(TurtleParseError { range, msg });
72                    } else {
73                        stack.push(n);
74                    }
75                }
76                NodeOrToken::Token(t) => {
77                    if t.kind() == SyntaxKind::Error {
78                        let range = t.text_range();
79                        errors.push(TurtleParseError {
80                            range: range.start().into()..range.end().into(),
81                            msg: format!("Unexpected: {}", t.text()),
82                        });
83                    }
84                }
85            }
86        }
87    }
88    errors
89}