1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
pub use rust_sitter_macro::*;
pub use tree_sitter::*;
pub trait Extract {
fn extract(node: tree_sitter::Node, source: &[u8]) -> Self;
}
pub mod errors {
#[derive(Debug)]
pub enum ParseErrorReason {
UnexpectedToken(String),
FailedNode(Vec<ParseError>),
MissingToken(String),
}
#[derive(Debug)]
pub struct ParseError {
pub reason: ParseErrorReason,
pub start: usize,
pub end: usize,
}
pub fn collect_parsing_errors(
node: &tree_sitter::Node,
source: &[u8],
errors: &mut Vec<ParseError>,
) {
if node.is_error() {
if node.child(0).is_some() {
let mut inner_errors = vec![];
let mut cursor = node.walk();
node.children(&mut cursor)
.for_each(|c| collect_parsing_errors(&c, source, &mut inner_errors));
errors.push(ParseError {
reason: ParseErrorReason::FailedNode(inner_errors),
start: node.start_byte(),
end: node.end_byte(),
})
} else {
let sexp = node.to_sexp();
if sexp.starts_with("(UNEXPECTED") {
let mut tok_getter = sexp.chars();
for _ in 0.."(UNEXPECTED '".len() {
tok_getter.next();
}
for _ in 0.."')".len() {
tok_getter.next_back();
}
let tok = tok_getter.as_str();
errors.push(ParseError {
reason: ParseErrorReason::UnexpectedToken(tok.to_string()),
start: node.start_byte(),
end: node.end_byte(),
})
} else {
errors.push(ParseError {
reason: ParseErrorReason::FailedNode(vec![]),
start: node.start_byte(),
end: node.end_byte(),
})
}
}
} else if node.is_missing() {
errors.push(ParseError {
reason: ParseErrorReason::MissingToken(node.kind().to_string()),
start: node.start_byte(),
end: node.end_byte(),
})
} else {
let mut cursor = node.walk();
node.children(&mut cursor)
.for_each(|c| collect_parsing_errors(&c, source, errors));
}
}
}