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