1use crate::RustParser;
2#[doc = include_str!("readme.md")]
3use crate::{ast::*, language::RustLanguage, lexer::RustTokenType, parser::RustElementType};
4use core::range::Range;
5use oak_core::{Builder, BuilderCache, GreenNode, OakDiagnostics, OakError, Parser, RedNode, RedTree, SourceText, TextEdit, builder::BuildOutput, source::Source};
6
7#[derive(Clone, Copy)]
13pub struct RustBuilder<'config> {
14 config: &'config RustLanguage,
16}
17
18impl<'config> RustBuilder<'config> {
19 pub const fn new(config: &'config RustLanguage) -> Self {
21 Self { config }
22 }
23}
24
25impl<'config> Builder<RustLanguage> for RustBuilder<'config> {
26 fn build<'a, S: Source + ?Sized>(&self, source: &S, edits: &[TextEdit], _cache: &'a mut impl BuilderCache<RustLanguage>) -> BuildOutput<RustLanguage> {
27 let parser = RustParser::new(self.config);
29
30 let mut cache = oak_core::parser::session::ParseSession::<RustLanguage>::default();
32 let parse_result = parser.parse(source, edits, &mut cache);
33
34 match parse_result.result {
36 Ok(green_tree) => {
37 let source_text = SourceText::new(source.get_text_in((0..source.length()).into()).into_owned());
39 match self.build_root(green_tree.clone(), &source_text) {
40 Ok(ast_root) => OakDiagnostics { result: Ok(ast_root), diagnostics: parse_result.diagnostics },
41 Err(build_error) => {
42 let mut diagnostics = parse_result.diagnostics;
43 diagnostics.push(build_error.clone());
44 OakDiagnostics { result: Err(build_error), diagnostics }
45 }
46 }
47 }
48 Err(parse_error) => OakDiagnostics { result: Err(parse_error), diagnostics: parse_result.diagnostics },
49 }
50 }
51}
52
53impl<'config> RustBuilder<'config> {
54 pub(crate) fn build_root(&self, green_tree: GreenNode<RustLanguage>, source: &SourceText) -> Result<RustRoot, OakError> {
56 let red_root = RedNode::new(&green_tree, 0);
57 let mut items = Vec::new();
58
59 for child in red_root.children() {
60 match child {
61 RedTree::Node(n) => match n.green.kind {
62 RustElementType::Function => {
63 let func = self.build_function(n, source)?;
64 items.push(Item::Function(func));
65 }
66 RustElementType::StructItem => {
67 let struct_def = self.build_struct(n, source)?;
68 items.push(Item::Struct(struct_def));
69 }
70 RustElementType::EnumItem => {
71 let enum_def = self.build_enum(n, source)?;
72 items.push(Item::Enum(enum_def));
73 }
74 RustElementType::Trait => {
75 let trait_def = self.build_trait(n, source)?;
76 items.push(Item::Trait(trait_def));
77 }
78 RustElementType::Impl => {
79 let impl_block = self.build_impl(n, source)?;
80 items.push(Item::Impl(impl_block));
81 }
82 RustElementType::ModuleItem => {
83 let module = self.build_module(n, source)?;
84 items.push(Item::Module(module));
85 }
86 RustElementType::UseItem => {
87 let use_decl = self.build_use(n, source)?;
88 items.push(Item::Use(use_decl));
89 }
90 RustElementType::Const => {
91 let const_def = self.build_const(n, source)?;
92 items.push(Item::Const(const_def));
93 }
94 RustElementType::Static => {
95 let static_def = self.build_static(n, source)?;
96 items.push(Item::Static(static_def));
97 }
98 RustElementType::TypeAlias => {
99 let type_alias = self.build_type_alias(n, source)?;
100 items.push(Item::TypeAlias(type_alias));
101 }
102 _ => {
103 }
105 },
106 RedTree::Leaf(_) => {
107 }
109 }
110 }
111 Ok(RustRoot { items })
112 }
113
114 pub(crate) fn build_function(&self, node: RedNode<RustLanguage>, source: &SourceText) -> Result<Function, OakError> {
116 let span = node.span();
117 let mut name = Identifier { name: String::new(), span: Range { start: 0, end: 0 } };
118 let mut params = Vec::new();
119 let mut return_type = None;
120 let mut body = None;
121 let mut is_async = false;
122 let mut is_unsafe = false;
123 let mut is_extern = false;
124
125 for child in node.children() {
126 match child {
127 RedTree::Leaf(t) => match t.kind {
128 RustTokenType::Async => is_async = true,
129 RustTokenType::Unsafe => is_unsafe = true,
130 RustTokenType::Extern => is_extern = true,
131 RustTokenType::Identifier => {
132 name.name = text(source, t.span.clone().into());
133 name.span = t.span.clone().into();
134 }
135 _ => {}
136 },
137 RedTree::Node(n) => match n.green.kind {
138 RustElementType::ParameterList => {
139 params = self.build_param_list(n, source)?;
140 }
141 RustElementType::ReturnType => {
142 return_type = Some(self.build_type(n, source)?);
143 }
144 RustElementType::BlockExpression => {
145 body = Some(self.build_block(n, source)?);
146 }
147 _ => {}
148 },
149 }
150 }
151
152 Ok(Function {
153 name,
154 params,
155 return_type,
156 body: body.unwrap_or_else(|| Block { statements: Vec::new(), block_start: 0, block_end: 0, nested: 0, span: Range { start: 0, end: 0 } }),
157 is_async,
158 is_unsafe,
159 generics: Vec::new(),
160 is_extern,
161 span: span.into(),
162 })
163 }
164
165 fn build_param_list(&self, node: RedNode<RustLanguage>, source: &SourceText) -> Result<Vec<Param>, OakError> {
167 let mut params = Vec::new();
168 for child in node.children() {
169 if let RedTree::Node(n) = child {
170 if n.green.kind == RustElementType::Parameter {
171 params.push(self.build_param(n, source)?);
172 }
173 }
174 }
175 Ok(params)
176 }
177
178 fn build_param(&self, node: RedNode<RustLanguage>, source: &SourceText) -> Result<Param, OakError> {
180 let span = node.span();
181 let mut name = Identifier { name: String::new(), span: Range { start: 0, end: 0 } };
182 let mut ty = Type::Path("_".to_string());
183
184 for child in node.children() {
185 match child {
186 RedTree::Leaf(t) => {
187 if let RustTokenType::Identifier = t.kind {
188 name.name = text(source, t.span.clone().into());
189 name.span = t.span.clone().into();
190 }
191 }
192 RedTree::Node(n) => match n.green.kind {
193 RustElementType::Type => {
194 ty = self.build_type(n, source)?;
195 }
196 _ => {}
197 },
198 }
199 }
200
201 Ok(Param { name, ty, is_mut: false, span: span.into() })
202 }
203
204 fn build_block(&self, node: RedNode<RustLanguage>, source: &SourceText) -> Result<Block, OakError> {
206 let span = node.span();
207 let mut statements = Vec::new();
208
209 for child in node.children() {
210 match child {
211 RedTree::Node(n) => match n.green.kind {
212 RustElementType::LetStatement => {
213 statements.push(self.build_let_statement(n, source)?);
214 }
215 RustElementType::ExpressionStatement => {
216 statements.push(self.build_expr_statement(n, source)?);
217 }
218 RustElementType::ItemStatement => {
219 let item = self.build_item_statement(n, source)?;
220 statements.push(Statement::Item(item));
221 }
222 _ => {
223 let span = n.span();
225 if let Ok(block_expr) = self.build_expr(n, source) {
226 statements.push(Statement::ExprStmt { expr: block_expr, semi: false, span: span.into() });
227 }
228 }
229 },
230 RedTree::Leaf(_) => {
231 }
233 }
234 }
235
236 Ok(Block { statements, block_start: span.start, block_end: span.end, nested: 0, span: span.into() })
237 }
238
239 fn build_let_statement(&self, node: RedNode<RustLanguage>, source: &SourceText) -> Result<Statement, OakError> {
241 let span = node.span();
242 let mut name = Identifier { name: String::new(), span: Range { start: 0, end: 0 } };
243 let mut ty = None;
244 let mut init = None;
245 let mut mutable = false;
246
247 for child in node.children() {
248 match child {
249 RedTree::Node(n) => match n.green.kind {
250 RustElementType::Pattern => {
251 let pattern = self.build_pattern(n, source)?;
252 match pattern {
254 Pattern::Ident(ident) => name = ident,
255 _ => {
256 return Err(OakError::syntax_error("Expected identifier in let statement".to_string(), span.start, None));
257 }
258 }
259 }
260 RustElementType::Type => {
261 ty = Some(self.build_type(n, source)?);
262 }
263 RustElementType::Expression => {
264 init = Some(self.build_expr(n, source)?);
265 }
266 _ => {}
267 },
268 RedTree::Leaf(t) => {
269 if t.kind == RustTokenType::Mut {
271 mutable = true;
272 }
273 }
274 }
275 }
276
277 Ok(Statement::Let { name, ty, expr: init, mutable, span: span.into() })
278 }
279
280 fn build_expr_statement(&self, node: RedNode<RustLanguage>, source: &SourceText) -> Result<Statement, OakError> {
282 let span = node.span();
283 let mut expr = Expr::Bool { value: false, span: span.clone().into() };
284 let mut has_semicolon = false;
285
286 for child in node.children() {
287 match child {
288 RedTree::Node(n) => {
289 if let Ok(expression) = self.build_expr(n, source) {
290 expr = expression;
291 }
292 }
293 RedTree::Leaf(t) => {
294 if t.kind == RustTokenType::Semicolon {
295 has_semicolon = true;
296 }
297 }
298 }
299 }
300
301 Ok(Statement::ExprStmt { expr, semi: has_semicolon, span: span.into() })
302 }
303
304 pub(crate) fn build_expr(&self, node: RedNode<RustLanguage>, source: &SourceText) -> Result<Expr, OakError> {
306 let span = node.span();
307
308 match node.green.kind {
309 RustElementType::IdentifierExpression => {
310 for child in node.children() {
311 if let RedTree::Leaf(t) = child {
312 if t.kind == RustTokenType::Identifier {
313 let ident = Identifier { name: text(source, t.span.clone().into()), span: t.span.clone().into() };
314 return Ok(Expr::Ident(ident));
315 }
316 }
317 }
318 Err(OakError::syntax_error("Invalid identifier expression".to_string(), span.start, None))
319 }
320 RustElementType::LiteralExpression => {
321 for child in node.children() {
322 if let RedTree::Leaf(t) = child {
323 let text = source.get_text_in(t.span.clone().into());
325 if text == "true" {
326 return Ok(Expr::Bool { value: true, span: span.into() });
327 }
328 else if text == "false" {
329 return Ok(Expr::Bool { value: false, span: span.into() });
330 }
331 else {
332 return Ok(Expr::Literal { value: text.to_string(), span: span.into() });
334 }
335 }
336 }
337 Err(OakError::syntax_error("Invalid literal expression".to_string(), span.start, None))
338 }
339 RustElementType::BinaryExpression => {
340 let mut left = None;
341 let mut op = None;
342 let mut right = None;
343
344 for child in node.children() {
345 match child {
346 RedTree::Node(n) => {
347 if left.is_none() {
348 left = Some(Box::new(self.build_expr(n, source)?));
349 }
350 else if right.is_none() {
351 right = Some(Box::new(self.build_expr(n, source)?));
352 }
353 }
354 RedTree::Leaf(t) => {
355 if op.is_none() {
356 let text = source.get_text_in(t.span.clone().into());
358 op = match text.as_ref() {
359 "+" => Some(RustTokenType::Plus),
360 "-" => Some(RustTokenType::Minus),
361 "*" => Some(RustTokenType::Star),
362 "/" => Some(RustTokenType::Slash),
363 "%" => Some(RustTokenType::Percent),
364 "==" => Some(RustTokenType::EqEq),
365 "!=" => Some(RustTokenType::Ne),
366 "<" => Some(RustTokenType::Lt),
367 "<=" => Some(RustTokenType::Le),
368 ">" => Some(RustTokenType::Gt),
369 ">=" => Some(RustTokenType::Ge),
370 "&&" => Some(RustTokenType::AndAnd),
371 "||" => Some(RustTokenType::OrOr),
372 "&" => Some(RustTokenType::Ampersand),
373 _ => None,
374 };
375 }
376 }
377 }
378 }
379
380 if let (Some(left), Some(op), Some(right)) = (left, op, right) { Ok(Expr::Binary { left, op, right, span: span.into() }) } else { Err(OakError::syntax_error("Invalid binary expression".to_string(), span.start, None)) }
381 }
382 RustElementType::UnaryExpression => {
383 let mut op = None;
384 let mut operand = None;
385
386 for child in node.children() {
387 match child {
388 RedTree::Node(n) => {
389 operand = Some(Box::new(self.build_expr(n, source)?));
390 }
391 RedTree::Leaf(t) => {
392 if op.is_none() {
393 let token_text = source.get_text_in(t.span.clone().into());
395 match token_text.as_ref() {
396 "!" => op = Some(RustTokenType::Bang),
397 "-" => op = Some(RustTokenType::Minus),
398 "+" => op = Some(RustTokenType::Plus),
399 _ => {}
400 }
401 }
402 }
403 }
404 }
405
406 if let (Some(op), Some(operand)) = (op, operand) { Ok(Expr::Unary { op, expr: operand, span: span.into() }) } else { Err(OakError::syntax_error("Invalid unary expression".to_string(), span.start, None)) }
407 }
408 RustElementType::CallExpression => {
409 let mut func = None;
410 let mut args = Vec::new();
411
412 for child in node.children() {
413 match child {
414 RedTree::Node(n) => {
415 if func.is_none() {
416 func = Some(Box::new(self.build_expr(n, source)?));
417 }
418 else if n.green.kind == RustElementType::ArgumentList {
419 args = self.build_argument_list(n, source)?;
420 }
421 }
422 _ => {}
423 }
424 }
425
426 if let Some(func) = func { Ok(Expr::Call { callee: func, args, span: span.into() }) } else { Err(OakError::syntax_error("Invalid call expression".to_string(), span.start, None)) }
427 }
428 RustElementType::FieldExpression => {
429 let mut base = None;
430 let mut field = Identifier { name: String::new(), span: Range { start: 0, end: 0 } };
431
432 for child in node.children() {
433 match child {
434 RedTree::Node(n) => {
435 base = Some(Box::new(self.build_expr(n, source)?));
436 }
437 RedTree::Leaf(t) => {
438 if t.kind == RustTokenType::Identifier {
439 field.name = text(source, t.span.clone().into());
440 field.span = t.span.clone().into();
441 }
442 }
443 }
444 }
445
446 if let Some(receiver) = base { Ok(Expr::Field { receiver, field, span: span.into() }) } else { Err(OakError::syntax_error("Invalid field expression".to_string(), span.start, None)) }
447 }
448 RustElementType::IndexExpression => {
449 let mut base = None;
450 let mut index = None;
451
452 for child in node.children() {
453 if let RedTree::Node(n) = child {
454 if base.is_none() {
455 base = Some(Box::new(self.build_expr(n, source)?));
456 }
457 else if index.is_none() {
458 index = Some(Box::new(self.build_expr(n, source)?));
459 }
460 }
461 }
462
463 if let (Some(receiver), Some(index)) = (base, index) { Ok(Expr::Index { receiver, index, span: span.into() }) } else { Err(OakError::syntax_error("Invalid index expression".to_string(), span.start, None)) }
464 }
465 RustElementType::ParenthesizedExpression => {
466 for child in node.children() {
467 if let RedTree::Node(n) = child {
468 let inner_expr = self.build_expr(n, source)?;
469 return Ok(Expr::Paren { expr: Box::new(inner_expr), span: span.into() });
470 }
471 }
472 Err(OakError::syntax_error("Invalid parenthesized expression".to_string(), span.start, None))
473 }
474 RustElementType::BlockExpression => {
475 let block = self.build_block(node, source)?;
476 Ok(Expr::Block(block))
477 }
478 _ => Err(OakError::syntax_error(format!("Unsupported expression type: {:?}", node.green.kind), span.start, None)),
479 }
480 }
481
482 fn build_struct(&self, node: RedNode<RustLanguage>, source: &SourceText) -> Result<Struct, OakError> {
484 let span = node.span();
485 let mut name = Identifier { name: String::new(), span: Range { start: 0, end: 0 } };
486
487 for child in node.children() {
488 if let RedTree::Leaf(t) = child {
489 if t.kind == RustTokenType::Identifier {
490 name.name = text(source, t.span.clone().into());
491 name.span = t.span.clone().into();
492 }
493 }
494 }
495
496 Ok(Struct { name, fields: Vec::new(), span: span.into() })
497 }
498
499 fn build_enum(&self, node: RedNode<RustLanguage>, source: &SourceText) -> Result<Enum, OakError> {
500 let span = node.span();
501 let mut name = Identifier { name: String::new(), span: Range { start: 0, end: 0 } };
502
503 for child in node.children() {
504 if let RedTree::Leaf(t) = child {
505 if t.kind == RustTokenType::Identifier {
506 name.name = text(source, t.span.clone().into());
507 name.span = t.span.clone().into();
508 }
509 }
510 }
511
512 Ok(Enum { name, variants: Vec::new(), span: span.into() })
513 }
514
515 fn build_trait(&self, node: RedNode<RustLanguage>, source: &SourceText) -> Result<Trait, OakError> {
516 let span = node.span();
517 let mut name = Identifier { name: String::new(), span: Range { start: 0, end: 0 } };
518
519 for child in node.children() {
520 if let RedTree::Leaf(t) = child {
521 if t.kind == RustTokenType::Identifier {
522 name.name = text(source, t.span.clone().into());
523 name.span = t.span.clone().into();
524 }
525 }
526 }
527
528 Ok(Trait { name, items: Vec::new(), span: span.into() })
529 }
530
531 fn build_impl(&self, node: RedNode<RustLanguage>, _source: &SourceText) -> Result<Impl, OakError> {
532 let span = node.span();
533 Ok(Impl { trait_: None, ty: Type::Path("_".to_string()), items: Vec::new(), span: span.into() })
534 }
535
536 fn build_module(&self, node: RedNode<RustLanguage>, source: &SourceText) -> Result<Module, OakError> {
537 let span = node.span();
538 let mut name = Identifier { name: String::new(), span: Range { start: 0, end: 0 } };
539
540 for child in node.children() {
541 if let RedTree::Leaf(t) = child {
542 if t.kind == RustTokenType::Identifier {
543 name.name = text(source, t.span.clone().into());
544 name.span = t.span.clone().into();
545 }
546 }
547 }
548
549 Ok(Module { name, items: Vec::new(), span: span.into() })
550 }
551
552 fn build_use(&self, node: RedNode<RustLanguage>, source: &SourceText) -> Result<UseItem, OakError> {
553 let span = node.span();
554 Ok(UseItem { path: text(source, span.clone().into()), span: span.into() })
555 }
556
557 fn build_const(&self, node: RedNode<RustLanguage>, source: &SourceText) -> Result<Const, OakError> {
558 let span = node.span();
559 let mut name = Identifier { name: String::new(), span: Range { start: 0, end: 0 } };
560
561 for child in node.children() {
562 if let RedTree::Leaf(t) = child {
563 if t.kind == RustTokenType::Identifier {
564 name.name = text(source, t.span.clone().into());
565 name.span = t.span.clone().into();
566 }
567 }
568 }
569
570 Ok(Const { name, ty: Type::Path("_".to_string()), expr: Expr::Bool { value: false, span: span.clone().into() }, span: span.into() })
571 }
572
573 fn build_static(&self, node: RedNode<RustLanguage>, source: &SourceText) -> Result<Static, OakError> {
574 let span = node.span();
575 let mut name = Identifier { name: String::new(), span: Range { start: 0, end: 0 } };
576
577 for child in node.children() {
578 if let RedTree::Leaf(t) = child {
579 if t.kind == RustTokenType::Identifier {
580 name.name = text(source, t.span.clone().into());
581 name.span = t.span.clone().into();
582 }
583 }
584 }
585
586 Ok(Static { name, ty: Type::Path("_".to_string()), expr: Expr::Bool { value: false, span: span.clone().into() }, mutable: false, span: span.into() })
587 }
588
589 fn build_type_alias(&self, node: RedNode<RustLanguage>, source: &SourceText) -> Result<TypeAlias, OakError> {
590 let span = node.span();
591 let mut name = Identifier { name: String::new(), span: Range { start: 0, end: 0 } };
592
593 for child in node.children() {
594 if let RedTree::Leaf(t) = child {
595 if t.kind == RustTokenType::Identifier {
596 name.name = text(source, t.span.clone().into());
597 name.span = t.span.clone().into();
598 }
599 }
600 }
601
602 Ok(TypeAlias { name, ty: Type::Path("_".to_string()), span: span.into() })
603 }
604
605 fn build_item_statement(&self, node: RedNode<RustLanguage>, source: &SourceText) -> Result<Item, OakError> {
606 for child in node.children() {
607 if let RedTree::Node(n) = child {
608 match n.green.kind {
609 RustElementType::Function => return Ok(Item::Function(self.build_function(n, source)?)),
610 RustElementType::StructItem => return Ok(Item::Struct(self.build_struct(n, source)?)),
611 RustElementType::EnumItem => return Ok(Item::Enum(self.build_enum(n, source)?)),
612 RustElementType::Trait => return Ok(Item::Trait(self.build_trait(n, source)?)),
613 RustElementType::Impl => return Ok(Item::Impl(self.build_impl(n, source)?)),
614 RustElementType::ModuleItem => return Ok(Item::Module(self.build_module(n, source)?)),
615 RustElementType::UseItem => return Ok(Item::Use(self.build_use(n, source)?)),
616 RustElementType::Const => return Ok(Item::Const(self.build_const(n, source)?)),
617 RustElementType::Static => return Ok(Item::Static(self.build_static(n, source)?)),
618 RustElementType::TypeAlias => return Ok(Item::TypeAlias(self.build_type_alias(n, source)?)),
619 _ => {}
620 }
621 }
622 }
623 Err(OakError::syntax_error("Invalid item statement".to_string(), node.offset, None))
624 }
625
626 fn build_type(&self, node: RedNode<RustLanguage>, source: &SourceText) -> Result<Type, OakError> {
627 let span = node.span();
628 Ok(Type::Path(text(source, span.into())))
629 }
630
631 fn build_pattern(&self, node: RedNode<RustLanguage>, source: &SourceText) -> Result<Pattern, OakError> {
632 for child in node.children() {
633 if let RedTree::Leaf(t) = child {
634 if t.kind == RustTokenType::Identifier {
635 return Ok(Pattern::Ident(Identifier { name: text(source, t.span.clone().into()), span: t.span.clone().into() }));
636 }
637 }
638 }
639 Ok(Pattern::Wildcard)
640 }
641
642 fn build_argument_list(&self, node: RedNode<RustLanguage>, source: &SourceText) -> Result<Vec<Expr>, OakError> {
643 let mut args = Vec::new();
644 for child in node.children() {
645 if let RedTree::Node(n) = child {
646 args.push(self.build_expr(n, source)?);
647 }
648 }
649 Ok(args)
650 }
651}
652
653#[inline]
655fn text(source: &SourceText, span: Range<usize>) -> String {
656 source.get_text_in(span.into()).to_string()
657}