oak_wit_component/builder/
mod.rs1use crate::{
2 ast::*,
3 language::WitLanguage,
4 lexer::token_type::WitTokenType,
5 parser::{WitParser, element_type::WitElementType},
6};
7use oak_core::{Builder, BuilderCache, GreenNode, OakDiagnostics, OakError, Parser, RedNode, RedTree, Source, SourceText, TextEdit, builder::BuildOutput};
8
9#[derive(Clone, Copy)]
11pub struct WitBuilder<'config> {
12 config: &'config WitLanguage,
14}
15
16impl<'config> WitBuilder<'config> {
17 pub const fn new(config: &'config WitLanguage) -> Self {
19 Self { config }
20 }
21}
22
23impl<'config> Builder<WitLanguage> for WitBuilder<'config> {
24 fn build<'a, S: oak_core::source::Source + ?Sized>(&self, source: &S, edits: &[TextEdit], _cache: &'a mut impl BuilderCache<WitLanguage>) -> BuildOutput<WitLanguage> {
25 let parser = WitParser::new(self.config);
26 let mut session = oak_core::parser::session::ParseSession::<WitLanguage>::default();
27 let parse_result = parser.parse(source, edits, &mut session);
28
29 match parse_result.result {
30 Ok(green_tree) => {
31 let source_text = SourceText::new(source.get_text_in((0..source.length()).into()).into_owned());
32 match self.build_root(green_tree, &source_text) {
33 Ok(ast_root) => OakDiagnostics { result: Ok(ast_root), diagnostics: parse_result.diagnostics },
34 Err(build_error) => {
35 let mut diagnostics = parse_result.diagnostics;
36 diagnostics.push(build_error.clone());
37 OakDiagnostics { result: Err(build_error), diagnostics }
38 }
39 }
40 }
41 Err(parse_error) => OakDiagnostics { result: Err(parse_error), diagnostics: parse_result.diagnostics },
42 }
43 }
44}
45
46impl<'config> WitBuilder<'config> {
47 fn build_root<'a>(&self, green_tree: &'a GreenNode<'a, WitLanguage>, source: &SourceText) -> Result<WitRoot, OakError> {
48 let red_root = RedNode::new(green_tree, 0);
49 let mut items = Vec::new();
50
51 for child in red_root.children() {
52 if let RedTree::Node(n) = child {
53 match n.green.kind {
54 WitElementType::PackageKw => {
55 items.push(WitItem::Package(self.build_package(n, source)?));
56 }
57 WitElementType::WorldKw => {
58 items.push(WitItem::World(self.build_world(n, source)?));
59 }
60 WitElementType::InterfaceKw => {
61 items.push(WitItem::Interface(self.build_interface(n, source)?));
62 }
63 _ => {}
64 }
65 }
66 }
67
68 Ok(WitRoot { items })
69 }
70
71 fn build_package(&self, node: RedNode<WitLanguage>, source: &SourceText) -> Result<WitPackage, OakError> {
72 let mut name = String::new();
73
74 for child in node.children() {
75 if let RedTree::Leaf(t) = child {
76 if t.kind == WitTokenType::Identifier {
77 name = source.get_text_in(t.span.clone().into()).to_string();
78 }
79 }
80 }
81
82 Ok(WitPackage { name })
83 }
84
85 fn build_world(&self, node: RedNode<WitLanguage>, source: &SourceText) -> Result<WitWorld, OakError> {
86 let mut name = String::new();
87 let mut items = Vec::new();
88
89 for child in node.children() {
90 match child {
91 RedTree::Leaf(t) => {
92 if t.kind == WitTokenType::Identifier {
93 name = source.get_text_in(t.span.clone().into()).to_string();
94 }
95 }
96 RedTree::Node(n) => match n.green.kind {
97 WitElementType::ImportKw => {
98 items.push(WitWorldItem::Import(self.build_import(n, source)?));
99 }
100 WitElementType::ExportKw => {
101 items.push(WitWorldItem::Export(self.build_export(n, source)?));
102 }
103 WitElementType::IncludeKw => {
104 items.push(WitWorldItem::Include(self.build_include(n, source)?));
105 }
106 _ => {}
107 },
108 }
109 }
110
111 Ok(WitWorld { name, items })
112 }
113
114 fn build_interface(&self, node: RedNode<WitLanguage>, source: &SourceText) -> Result<WitInterface, OakError> {
115 let mut name = String::new();
116 let mut items = Vec::new();
117
118 for child in node.children() {
119 match child {
120 RedTree::Leaf(t) => {
121 if t.kind == WitTokenType::Identifier {
122 name = source.get_text_in(t.span.clone().into()).to_string();
123 }
124 }
125 RedTree::Node(n) => match n.green.kind {
126 WitElementType::TypeKw => {
127 items.push(WitInterfaceItem::Type(self.build_type(n, source)?));
128 }
129 WitElementType::FuncKw => {
130 items.push(WitInterfaceItem::Func(self.build_func(n, source)?));
131 }
132 _ => {}
133 },
134 }
135 }
136
137 Ok(WitInterface { name, items })
138 }
139
140 fn build_import(&self, node: RedNode<WitLanguage>, source: &SourceText) -> Result<WitImport, OakError> {
141 let mut name = String::new();
142 for child in node.children() {
143 if let RedTree::Leaf(t) = child {
144 if t.kind == WitTokenType::Identifier {
145 name = source.get_text_in(t.span.clone().into()).to_string();
146 }
147 }
148 }
149 Ok(WitImport { name })
150 }
151
152 fn build_export(&self, node: RedNode<WitLanguage>, source: &SourceText) -> Result<WitExport, OakError> {
153 let mut name = String::new();
154 for child in node.children() {
155 if let RedTree::Leaf(t) = child {
156 if t.kind == WitTokenType::Identifier {
157 name = source.get_text_in(t.span.clone().into()).to_string();
158 }
159 }
160 }
161 Ok(WitExport { name })
162 }
163
164 fn build_include(&self, node: RedNode<WitLanguage>, source: &SourceText) -> Result<WitInclude, OakError> {
165 let mut name = String::new();
166 for child in node.children() {
167 if let RedTree::Leaf(t) = child {
168 if t.kind == WitTokenType::Identifier {
169 name = source.get_text_in(t.span.clone().into()).to_string();
170 }
171 }
172 }
173 Ok(WitInclude { name })
174 }
175
176 fn build_type(&self, node: RedNode<WitLanguage>, source: &SourceText) -> Result<WitType, OakError> {
177 let mut name = String::new();
178 let mut kind = WitTypeKind::Bool; for child in node.children() {
181 if let RedTree::Leaf(t) = child {
182 if t.kind == WitTokenType::Identifier {
183 name = source.get_text_in(t.span.clone().into()).to_string();
184 }
185 else if let Some(t_kind) = self.parse_type_kind(&source.get_text_in(t.span.clone().into())) {
186 kind = t_kind;
187 }
188 }
189 }
190
191 Ok(WitType { name, kind })
192 }
193
194 fn build_func(&self, node: RedNode<WitLanguage>, source: &SourceText) -> Result<WitFunc, OakError> {
195 let mut name = String::new();
196 let mut params = Vec::new();
197 let mut result = None;
198
199 for child in node.children() {
200 match child {
201 RedTree::Leaf(t) => {
202 if t.kind == WitTokenType::Identifier {
203 name = source.get_text_in(t.span.clone().into()).to_string();
204 }
205 }
206 _ => {}
207 }
208 }
209
210 Ok(WitFunc { name, params, result })
211 }
212
213 fn parse_type_kind(&self, text: &str) -> Option<WitTypeKind> {
214 match text {
215 "bool" => Some(WitTypeKind::Bool),
216 "u32" => Some(WitTypeKind::U32),
217 "string" => Some(WitTypeKind::String),
218 _ => None,
219 }
220 }
221}