1use crate::{ast::*, language::MsilLanguage, parser::MsilParser};
2use oak_core::{Builder, BuilderCache, GreenNode, OakDiagnostics, Source, SourceText, TextEdit};
3
4#[derive(Clone)]
5pub struct MsilBuilder<'config> {
6 #[allow(dead_code)]
7 config: &'config MsilLanguage,
8}
9
10impl<'config> MsilBuilder<'config> {
11 pub fn new(config: &'config MsilLanguage) -> Self {
12 Self { config }
13 }
14
15 fn build_root(&self, green_tree: &GreenNode<MsilLanguage>, source: &SourceText) -> Result<MsilRoot, oak_core::OakError> {
16 let red_root = oak_core::RedNode::new(green_tree, 0);
17
18 let mut items = Vec::new();
19 for child in red_root.children() {
20 if let oak_core::RedTree::Node(node) = child {
21 if let Some(item) = self.build_item(&node, source) {
22 items.push(item);
23 }
24 }
25 }
26
27 Ok(MsilRoot { items })
28 }
29
30 fn build_item(&self, node: &oak_core::RedNode<MsilLanguage>, source: &SourceText) -> Option<Item> {
31 use crate::kind::MsilSyntaxKind::*;
32
33 let kind = node.green.kind;
34 match kind {
35 Assembly => {
36 let mut name = "unknown".to_string();
37 for child in node.children() {
38 if let oak_core::RedTree::Node(n) = child {
39 if n.green.kind == Identifier {
40 name = source.get_text_in(n.span()).to_string();
41 break;
42 }
43 }
44 }
45 Some(Item::Assembly(crate::ast::Assembly { name, span: node.span() }))
46 }
47 Class => {
48 let mut name = "Unknown".to_string();
49 for child in node.children() {
50 if let oak_core::RedTree::Node(n) = child {
51 if n.green.kind == Identifier {
52 name = source.get_text_in(n.span()).to_string();
53 break;
54 }
55 }
56 }
57 Some(Item::Class(crate::ast::Class { name, methods: Vec::new(), span: node.span() }))
58 }
59 _ => None,
60 }
61 }
62}
63
64impl<'config> Builder<MsilLanguage> for MsilBuilder<'config> {
65 fn build<'a, S: Source + ?Sized>(&self, source: &S, edits: &[TextEdit], _cache: &'a mut impl BuilderCache<MsilLanguage>) -> OakDiagnostics<MsilRoot> {
66 let parser = MsilParser::new(self.config);
67 let lexer = crate::lexer::MsilLexer::new(&self.config);
68
69 let mut cache = oak_core::parser::session::ParseSession::<MsilLanguage>::default();
70 let parse_result = oak_core::parser::parse(&parser, &lexer, source, edits, &mut cache);
71
72 match parse_result.result {
73 Ok(green_tree) => {
74 let source_text = SourceText::new(source.get_text_in((0..source.length()).into()).into_owned());
75 OakDiagnostics { result: self.build_root(green_tree, &source_text), diagnostics: parse_result.diagnostics }
76 }
77 Err(parse_error) => OakDiagnostics { result: Err(parse_error), diagnostics: parse_result.diagnostics },
78 }
79 }
80}