codebank/parser/lang/
c.rs1use crate::{CParser, Error, FileUnit, LanguageParser, Result};
2use std::fs;
3use std::ops::{Deref, DerefMut};
4use std::path::Path;
5use tree_sitter::Parser;
6
7impl CParser {
8 pub fn try_new() -> Result<Self> {
9 let mut parser = Parser::new();
10 let language = tree_sitter_c::LANGUAGE;
11 parser
12 .set_language(&language.into())
13 .map_err(|e| Error::TreeSitter(e.to_string()))?;
14 Ok(Self { parser })
15 }
16}
17
18impl LanguageParser for CParser {
19 fn parse_file(&mut self, file_path: &Path) -> Result<FileUnit> {
20 let source_code = fs::read_to_string(file_path).map_err(Error::Io)?;
23
24 let tree = self
26 .parse(source_code.as_bytes(), None)
27 .ok_or_else(|| Error::Parse("Failed to parse file".to_string()))?;
28
29 let root_node = tree.root_node();
30
31 let mut document = None;
33 let mut cursor = root_node.walk();
34 let mut first_comments = Vec::new();
35
36 for node in root_node.children(&mut cursor) {
37 if node.kind() == "comment" {
38 if let Ok(comment) = node.utf8_text(source_code.as_bytes()) {
39 let cleaned = comment
40 .trim_start_matches("/*")
41 .trim_end_matches("*/")
42 .trim()
43 .to_string();
44 first_comments.push(cleaned);
45 }
46 } else {
47 break; }
49 }
50
51 if !first_comments.is_empty() {
52 document = Some(first_comments.join("\n"));
53 }
54
55 let mut declares = Vec::new();
57 cursor = root_node.walk();
58
59 for node in root_node.children(&mut cursor) {
60 match node.kind() {
61 "preproc_include" => {
62 if let Ok(include_text) = node.utf8_text(source_code.as_bytes()) {
63 declares.push(crate::DeclareStatements {
64 source: include_text.to_string(),
65 kind: crate::DeclareKind::Import,
66 });
67 }
68 }
69 "preproc_def" | "preproc_function_def" => {
70 if let Ok(def_text) = node.utf8_text(source_code.as_bytes()) {
71 declares.push(crate::DeclareStatements {
72 source: def_text.to_string(),
73 kind: crate::DeclareKind::Other("define".to_string()),
74 });
75 }
76 }
77 _ => continue,
78 }
79 }
80
81 Ok(FileUnit {
82 path: file_path.to_path_buf(),
83 document,
84 declares,
85 source: Some(source_code),
86 ..Default::default()
87 })
88 }
89}
90
91impl Deref for CParser {
92 type Target = Parser;
93
94 fn deref(&self) -> &Self::Target {
95 &self.parser
96 }
97}
98
99impl DerefMut for CParser {
100 fn deref_mut(&mut self) -> &mut Self::Target {
101 &mut self.parser
102 }
103}