Skip to main content

oak_msil/builder/
mod.rs

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}