1use crate::{
2 ast::*,
3 language::MsilLanguage,
4 parser::{MsilParser, element_type::MsilElementType},
5};
6use oak_core::{Builder, BuilderCache, GreenNode, OakDiagnostics, Source, SourceText, TextEdit};
7
8#[derive(Clone)]
9pub struct MsilBuilder<'config> {
10 #[allow(dead_code)]
11 config: &'config MsilLanguage,
12}
13
14impl<'config> MsilBuilder<'config> {
15 pub fn new(config: &'config MsilLanguage) -> Self {
16 Self { config }
17 }
18
19 fn build_root(&self, green_tree: &GreenNode<MsilLanguage>, source: &SourceText) -> Result<MsilRoot, oak_core::OakError> {
20 let red_root = oak_core::RedNode::new(green_tree, 0);
21
22 let mut items = Vec::new();
23 for child in red_root.children() {
24 if let oak_core::RedTree::Node(node) = child {
25 if let Some(item) = self.build_item(&node, source) {
26 items.push(item)
27 }
28 }
29 }
30
31 Ok(MsilRoot { items })
32 }
33
34 fn build_item(&self, node: &oak_core::RedNode<MsilLanguage>, source: &SourceText) -> Option<Item> {
35 let kind = node.green.kind;
36 match kind {
37 MsilElementType::Assembly => {
38 let mut name = "unknown".to_string();
39 for child in node.children() {
40 if let oak_core::RedTree::Node(n) = child {
41 if n.green.kind == MsilElementType::Identifier {
42 name = source.get_text_in(n.span()).to_string();
43 break;
44 }
45 }
46 }
47 Some(Item::Assembly(crate::ast::Assembly { name, span: node.span() }))
48 }
49 MsilElementType::AssemblyExtern => {
50 let mut name = "unknown".to_string();
51 for child in node.children() {
52 if let oak_core::RedTree::Node(n) = child {
53 if n.green.kind == MsilElementType::Identifier {
54 name = source.get_text_in(n.span()).to_string();
55 break;
56 }
57 }
58 }
59 Some(Item::AssemblyExtern(name))
60 }
61 MsilElementType::Module => {
62 let mut name = "unknown".to_string();
63 for child in node.children() {
64 if let oak_core::RedTree::Node(n) = child {
65 if n.green.kind == MsilElementType::Identifier {
66 name = source.get_text_in(n.span()).to_string();
67 break;
68 }
69 }
70 }
71 Some(Item::Module(name))
72 }
73 MsilElementType::Class => {
74 let mut name = "Unknown".to_string();
75 let mut methods = Vec::new();
76 for child in node.children() {
77 if let oak_core::RedTree::Node(n) = child {
78 if n.green.kind == MsilElementType::Identifier {
79 name = source.get_text_in(n.span()).to_string()
80 }
81 else if n.green.kind == MsilElementType::Method {
82 if let Some(method) = self.build_method(&n, source) {
83 methods.push(method)
84 }
85 }
86 }
87 }
88 Some(Item::Class(crate::ast::Class { name, methods, span: node.span() }))
89 }
90 _ => None,
91 }
92 }
93
94 fn build_method(&self, node: &oak_core::RedNode<MsilLanguage>, source: &SourceText) -> Option<crate::ast::Method> {
95 let mut name = "Unknown".to_string();
96 for child in node.children() {
97 if let oak_core::RedTree::Node(n) = child {
98 if n.green.kind == MsilElementType::Identifier {
99 name = source.get_text_in(n.span()).to_string();
100 break;
101 }
102 }
103 }
104
105 Some(crate::ast::Method {
106 name,
107 instructions: Vec::new(), span: node.span(),
109 })
110 }
111}
112
113impl<'config> Builder<MsilLanguage> for MsilBuilder<'config> {
114 fn build<'a, S: Source + ?Sized>(&self, source: &S, edits: &[TextEdit], _cache: &'a mut impl BuilderCache<MsilLanguage>) -> OakDiagnostics<MsilRoot> {
115 let parser = MsilParser::new(self.config);
116 let lexer = crate::lexer::MsilLexer::new(&self.config);
117
118 let mut cache = oak_core::parser::session::ParseSession::<MsilLanguage>::default();
119 let parse_result = oak_core::parser::parse(&parser, &lexer, source, edits, &mut cache);
120
121 match parse_result.result {
122 Ok(green_tree) => {
123 let source_text = SourceText::new(source.get_text_in((0..source.length()).into()).into_owned());
124 OakDiagnostics { result: self.build_root(green_tree, &source_text), diagnostics: parse_result.diagnostics }
125 }
126 Err(parse_error) => OakDiagnostics { result: Err(parse_error), diagnostics: parse_result.diagnostics },
127 }
128 }
129}