1use tree_sitter::{Language, Tree};
2
3pub trait AstParser {
13 fn parse(&mut self, source: &str, language: &Language) -> Result<Tree, ParseError>;
20}
21
22#[derive(Debug)]
23pub enum ParseError {
24 LanguageSetup,
26 ParseFailed,
28}
29
30impl std::fmt::Display for ParseError {
31 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32 match self {
33 Self::LanguageSetup => write!(f, "failed to load grammar (ABI mismatch)"),
34 Self::ParseFailed => write!(f, "parser failed to produce a syntax tree"),
35 }
36 }
37}
38
39impl std::error::Error for ParseError {}
40
41pub struct TreeSitterParser(tree_sitter::Parser);
43
44impl TreeSitterParser {
45 #[must_use]
46 pub fn new() -> Self {
47 Self(tree_sitter::Parser::new())
48 }
49}
50
51impl Default for TreeSitterParser {
52 fn default() -> Self {
53 Self::new()
54 }
55}
56
57impl AstParser for TreeSitterParser {
58 fn parse(&mut self, source: &str, language: &Language) -> Result<Tree, ParseError> {
59 self.0
60 .set_language(language)
61 .map_err(|_| ParseError::LanguageSetup)?;
62 self.0.parse(source, None).ok_or(ParseError::ParseFailed)
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn parses_valid_rust_source() {
72 let mut parser = TreeSitterParser::new();
73
74 let tree = parser.parse("fn main() {}", &tree_sitter_rust::LANGUAGE.into());
75
76 assert!(tree.is_ok());
77 }
78
79 #[test]
80 fn switches_language_between_calls() {
81 let mut parser = TreeSitterParser::new();
82
83 let rust = parser.parse("fn main() {}", &tree_sitter_rust::LANGUAGE.into());
84 let ts = parser.parse(
85 "function main() {}",
86 &tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into(),
87 );
88
89 assert!(rust.is_ok());
90 assert!(ts.is_ok());
91 }
92}