1use crate::{
2 RustLanguage, RustParser, RustSyntaxKind,
3 ast::{RustRoot, *},
4};
5use oak_core::{
6 Arc, Builder, GreenNode, IncrementalCache, OakDiagnostics, OakError, RedNode, RedTree, SourceText, source::Source, Parser,
7};
8use std::ops::Range;
9
10impl<'config> Builder<RustLanguage> for RustParser<'config> {
11 fn build_incremental(
12 &self,
13 text: impl Source,
14 changed: usize,
15 cache: IncrementalCache<RustLanguage>,
16 ) -> OakDiagnostics<RustRoot> {
17 let source_text = SourceText::new(text.get_text_in((0..text.length()).into()));
19 let parse_result = self.parse_incremental(text, changed, cache);
21
22 match parse_result.result {
24 Ok(green_tree) => {
25 match self.build_root((*green_tree).clone(), &source_text) {
27 Ok(ast_root) => OakDiagnostics {
28 result: Ok(ast_root),
29 diagnostics: parse_result.diagnostics,
30 },
31 Err(build_error) => {
32 let mut diagnostics = parse_result.diagnostics;
33 diagnostics.push(build_error);
34 OakDiagnostics {
35 result: Err(OakError::custom_error("Failed to build AST")),
36 diagnostics,
37 }
38 }
39 }
40 }
41 Err(parse_error) => OakDiagnostics {
42 result: Err(parse_error),
43 diagnostics: parse_result.diagnostics,
44 }
45 }
46 }
47}
48
49impl<'config> RustParser<'config> {
50 pub(crate) fn build_root(&self, green_tree: GreenNode<RustSyntaxKind>, source: &SourceText) -> Result<RustRoot, OakError> {
51 let red_root = RedNode::new(Arc::new(green_tree), 0);
52 let mut items = Vec::new();
53 for child in red_root.children() {
54 match child {
55 RedTree::Node(n) => match n.green.kind {
56 RustSyntaxKind::Function => {
57 let func = self.build_function(n, source)?;
58 items.push(Item::Function(func));
59 }
60 RustSyntaxKind::LetStatement => {
61 let stmt = self.build_let(n, source)?;
62 items.push(Item::Statement(stmt));
63 }
64 RustSyntaxKind::ExpressionStatement => {
65 let stmt = self.build_expr_stmt(n, source)?;
66 items.push(Item::Statement(stmt));
67 }
68 _ => {
69 return Err(OakError::syntax_error(
70 "Unexpected item in root".to_string(),
71 source.get_location(n.span().start),
72 ));
73 }
74 },
75 RedTree::Leaf(t) => {
76 return Err(OakError::syntax_error(
77 "Unexpected token in root".to_string(),
78 source.get_location(t.span.start),
79 ));
80 }
81 }
82 }
83 Ok(RustRoot { items })
84 }
85
86 pub(crate) fn build_function(&self, node: RedNode<RustSyntaxKind>, source: &SourceText) -> Result<Function, OakError> {
89 let span = node.span();
90 let mut name = Identifier { name: String::new(), span: Default::default() };
91 let mut params = Vec::new();
92 let mut body = None;
93
94 for child in node.children() {
95 match child {
96 RedTree::Leaf(t) => {
97 if t.kind == RustSyntaxKind::Identifier {
98 name.name = text(source, t.span.clone().into());
99 name.span = t.span.clone();
100 }
101 }
102 RedTree::Node(n) => match n.green.kind {
103 RustSyntaxKind::ParameterList => {
104 params = self.build_param_list(n, source)?;
105 }
106 RustSyntaxKind::BlockExpression => {
107 body = Some(self.build_block(n, source)?);
108 }
109 _ => {
110 return Err(OakError::syntax_error(
111 "Unexpected node in function definition".to_string(),
112 source.get_location(n.span().start),
113 ));
114 }
115 },
116 }
117 }
118 if let Some(body) = body {
119 Ok(Function { name, params, body, span })
120 }
121 else {
122 Err(OakError::syntax_error(format!("Missing function body at {:?}", span), source.get_location(span.start)))
123 }
124 }
125
126 fn build_param_list(&self, node: RedNode<RustSyntaxKind>, source: &SourceText) -> Result<Vec<Param>, OakError> {
127 let mut params = Vec::new();
128 for child in node.children() {
129 if let RedTree::Node(n) = child {
130 if n.green.kind == RustSyntaxKind::Parameter {
131 params.push(self.build_param(n, source)?);
132 }
133 }
134 }
135 Ok(params)
136 }
137
138 fn build_param(&self, node: RedNode<RustSyntaxKind>, source: &SourceText) -> Result<Param, OakError> {
139 let span = node.span();
140 let mut name: Option<Identifier> = None;
141 let mut ty = None;
142 for child in node.children() {
144 match child {
145 RedTree::Leaf(t) => {
146 if t.kind == RustSyntaxKind::Identifier {
147 if name.is_none() {
148 name = Some(Identifier { name: text(source, t.span.clone().into()), span: t.span.clone() });
149 }
150 else {
151 ty = Some(text(source, t.span.clone().into()));
152 }
153 }
154 else if t.kind != RustSyntaxKind::Colon {
155 return Err(OakError::syntax_error(
156 "Unexpected token in parameter definition".to_string(),
157 source.get_location(t.span.start),
158 ));
159 }
160 }
161 _ => {
162 return Err(OakError::syntax_error(
163 "Unexpected token in parameter definition".to_string(),
164 source.get_location(child.span().start),
165 ));
166 }
167 }
168 }
169 return if let (Some(name), Some(ty)) = (name, ty) {
170 Ok(Param { name, ty, span })
171 }
172 else {
173 Err(OakError::syntax_error(
174 format!("Missing name or type in parameter at {:?}", span),
175 source.get_location(span.start),
176 ))
177 };
178 }
179
180 fn build_block(&self, node: RedNode<RustSyntaxKind>, source: &SourceText) -> Result<Block, OakError> {
181 let span = node.span();
182 let mut statements = Vec::new();
183 for child in node.children() {
184 match child {
185 RedTree::Node(n) => match n.green.kind {
186 RustSyntaxKind::LetStatement => statements.push(self.build_let(n, source)?),
187 RustSyntaxKind::ExpressionStatement => statements.push(self.build_expr_stmt(n, source)?),
188 _ => {
189 return Err(OakError::syntax_error(
190 "Unexpected statement in block".to_string(),
191 source.get_location(n.span().start),
192 ));
193 }
194 },
195 RedTree::Leaf(t) => {
196 if t.kind != RustSyntaxKind::LeftBrace && t.kind != RustSyntaxKind::RightBrace {
197 return Err(OakError::syntax_error(
198 "Unexpected token in block".to_string(),
199 source.get_location(t.span.start),
200 ));
201 }
202 }
203 }
204 }
205 Ok(Block { statements, span })
206 }
207
208 fn build_expr_stmt(&self, node: RedNode<RustSyntaxKind>, source: &SourceText) -> Result<Statement, OakError> {
209 let span = node.span();
210 let mut children_iter = node.children().peekable();
211
212 let expr_node = children_iter.next().ok_or_else(|| {
213 OakError::syntax_error("Missing expression in expression statement".to_string(), source.get_location(span.start))
214 })?;
215
216 let expr = match expr_node {
217 RedTree::Node(n) => self.build_expr(n, source)?,
218 RedTree::Leaf(t) => {
219 return Err(OakError::syntax_error(
220 "Expected an expression, found a token".to_string(),
221 source.get_location(t.span.start),
222 ));
223 }
224 };
225
226 let mut semi = false;
227 if let Some(RedTree::Leaf(t)) = children_iter.peek() {
228 if t.kind == RustSyntaxKind::Semicolon {
229 semi = true;
230 children_iter.next(); }
232 }
233
234 if let Some(unexpected_child) = children_iter.next() {
235 return Err(OakError::syntax_error(
236 "Unexpected token or expression after semicolon".to_string(),
237 source.get_location(unexpected_child.span().start),
238 ));
239 }
240
241 Ok(Statement::ExprStmt { expr, semi, span })
242 }
243
244 fn build_let(&self, node: RedNode<RustSyntaxKind>, source: &SourceText) -> Result<Statement, OakError> {
245 let span = node.span();
246 let mut children_iter = node.children().peekable();
247
248 let let_keyword = children_iter
250 .next()
251 .ok_or_else(|| OakError::syntax_error("Missing 'let' keyword".to_string(), source.get_location(span.start)))?;
252 match let_keyword {
253 RedTree::Leaf(t) if t.kind == RustSyntaxKind::Let => {}
254 _ => {
255 return Err(OakError::syntax_error(
256 "Expected 'let' keyword".to_string(),
257 source.get_location(let_keyword.span().start),
258 ));
259 }
260 }
261
262 let name_node = children_iter.next().ok_or_else(|| {
264 OakError::syntax_error("Missing identifier in let statement".to_string(), source.get_location(span.start))
265 })?;
266 let name = match name_node {
267 RedTree::Leaf(t) if t.kind == RustSyntaxKind::Identifier => {
268 Identifier { name: text(source, t.span.clone().into()), span: t.span.clone() }
269 }
270 _ => {
271 return Err(OakError::syntax_error(
272 "Expected identifier in let statement".to_string(),
273 source.get_location(name_node.span().start),
274 ));
275 }
276 };
277
278 let mut expr: Option<Expr> = None;
279
280 if let Some(RedTree::Leaf(t)) = children_iter.peek() {
282 if t.kind == RustSyntaxKind::Eq {
283 children_iter.next(); let expr_node = children_iter.next().ok_or_else(|| {
286 OakError::syntax_error(
287 "Missing expression after '=' in let statement".to_string(),
288 source.get_location(span.end),
289 )
290 })?;
291
292 expr = Some(match expr_node {
293 RedTree::Node(n) => self.build_expr(n, source)?,
294 RedTree::Leaf(t) => {
295 return Err(OakError::syntax_error(
296 "Expected an expression, found a token after '=' in let statement".to_string(),
297 source.get_location(t.span.start),
298 ));
299 }
300 });
301 }
302 }
303
304 if let Some(unexpected_child) = children_iter.next() {
305 return Err(OakError::syntax_error(
306 "Unexpected token or expression in let statement".to_string(),
307 source.get_location(unexpected_child.span().start),
308 ));
309 }
310
311 let expr = expr.ok_or_else(|| {
312 OakError::syntax_error("Missing expression in let statement".to_string(), source.get_location(span.start))
313 })?;
314
315 Ok(Statement::Let { name, expr, span })
316 }
317
318 pub(crate) fn build_expr(&self, node: RedNode<RustSyntaxKind>, source: &SourceText) -> Result<Expr, OakError> {
319 match node.green.kind {
320 RustSyntaxKind::IdentifierExpression => {
321 let span = node.span();
322 for child in node.children() {
324 if let RedTree::Leaf(t) = child {
325 if t.kind == RustSyntaxKind::Identifier {
326 return Ok(Expr::Ident(Identifier { name: text(source, t.span.clone().into()), span: t.span.clone() }));
327 }
328 }
329 }
330 Err(OakError::syntax_error(
331 format!("Missing identifier in identifier expression at {:?}", span),
332 source.get_location(span.start),
333 ))
334 }
335 RustSyntaxKind::LiteralExpression => {
336 let span = node.span();
337 for child in node.children() {
338 if let RedTree::Leaf(t) = child {
339 return Ok(Expr::Literal { value: text(source, t.span.into()), span });
340 }
341 }
342 Err(OakError::syntax_error(
343 format!("Missing literal in literal expression at {:?}", span),
344 source.get_location(span.start),
345 ))
346 }
347 RustSyntaxKind::BooleanLiteral => {
348 let span = node.span();
349 for child in node.children() {
350 if let RedTree::Leaf(t) = child {
351 return Ok(Expr::Bool { value: t.kind == RustSyntaxKind::True, span });
352 }
353 }
354 Err(OakError::syntax_error(
355 format!("Missing boolean literal in boolean literal expression at {:?}", span),
356 source.get_location(span.start),
357 ))
358 }
359 RustSyntaxKind::ParenthesizedExpression => {
360 let span = node.span();
361 for child in node.children() {
362 if let RedTree::Node(n) = child {
363 return Ok(Expr::Paren { expr: Box::new(self.build_expr(n, source)?), span });
364 }
365 }
366 Err(OakError::syntax_error(
367 format!("Missing expression in parenthesized expression at {:?}", span),
368 source.get_location(span.start),
369 ))
370 }
371 RustSyntaxKind::UnaryExpression => {
372 let span = node.span();
373 let mut op = RustSyntaxKind::Error;
374 let mut sub: Option<Expr> = None;
375 for child in node.children() {
376 match child {
377 RedTree::Leaf(t) => {
378 op = t.kind;
379 }
380 RedTree::Node(n) => {
381 sub = Some(self.build_expr(n, source)?);
382 }
383 }
384 }
385 if let Some(sub_expr) = sub {
386 Ok(Expr::Unary { op, expr: Box::new(sub_expr), span })
387 }
388 else {
389 Err(OakError::syntax_error(
390 format!("Missing operand in unary expression at {:?}", span),
391 source.get_location(span.start),
392 ))
393 }
394 }
395 RustSyntaxKind::BinaryExpression => {
396 let span = node.span();
397 let mut left: Option<Expr> = None;
398 let mut op = RustSyntaxKind::Error;
399 let mut right: Option<Expr> = None;
400 let mut idx = 0;
401 for child in node.children() {
402 match child {
403 RedTree::Node(n) => {
404 if idx == 0 {
405 left = Some(self.build_expr(n, source)?);
406 }
407 else {
408 right = Some(self.build_expr(n, source)?);
409 }
410 }
411 RedTree::Leaf(t) => {
412 op = t.kind;
413 }
414 }
415 idx += 1;
416 }
417 if let (Some(left_expr), Some(right_expr)) = (left, right) {
418 Ok(Expr::Binary { left: Box::new(left_expr), op, right: Box::new(right_expr), span })
419 }
420 else {
421 Err(OakError::syntax_error(
422 format!("Missing operands in binary expression at {:?}", span),
423 source.get_location(span.start),
424 ))
425 }
426 }
427 RustSyntaxKind::CallExpression => {
428 let span = node.span();
429 let mut callee: Option<Expr> = None;
431 let mut args: Vec<Expr> = Vec::new();
432 let mut seen_paren = false;
433 for child in node.children() {
434 match child {
435 RedTree::Node(n) => {
436 if !seen_paren && callee.is_none() {
437 callee = Some(self.build_expr(n, source)?);
438 }
439 else {
440 args.push(self.build_expr(n, source)?);
441 }
442 }
443 RedTree::Leaf(t) => {
444 if t.kind == RustSyntaxKind::LeftParen {
445 seen_paren = true;
446 }
447 }
448 }
449 }
450 if let Some(callee_expr) = callee {
451 Ok(Expr::Call { callee: Box::new(callee_expr), args, span })
452 }
453 else {
454 Err(OakError::syntax_error(
455 format!("Missing callee in call expression at {:?}", span),
456 source.get_location(span.start),
457 ))
458 }
459 }
460 RustSyntaxKind::FieldExpression => {
461 let span = node.span();
462 let mut receiver: Option<Expr> = None;
463 let mut field: Option<Identifier> = None;
464 let mut idx = 0;
465 for child in node.children() {
466 match child {
467 RedTree::Node(n) => {
468 if idx == 0 {
469 receiver = Some(self.build_expr(n, source)?);
471 }
472 }
473 RedTree::Leaf(t) => {
474 if idx == 2 && t.kind == RustSyntaxKind::Identifier {
475 field = Some(Identifier { name: text(source, t.span.clone().into()), span: t.span.clone() });
477 }
478 }
479 }
480 idx += 1;
481 }
482 if let (Some(receiver_val), Some(field_val)) = (receiver, field) {
483 Ok(Expr::Field { receiver: Box::new(receiver_val), field: field_val, span })
484 }
485 else {
486 Err(OakError::syntax_error(
487 format!("Missing receiver or field in field expression at {:?}", span),
488 source.get_location(span.start),
489 ))
490 }
491 }
492 RustSyntaxKind::IndexExpression => {
493 let span = node.span();
494 let mut base: Option<Expr> = None;
496 let mut index: Option<Expr> = None;
497 let mut idx = 0;
498 for child in node.children() {
499 match child {
500 RedTree::Node(n) => {
501 if idx == 0 {
502 base = Some(self.build_expr(n, source)?);
503 }
504 else {
505 index = Some(self.build_expr(n, source)?);
506 }
507 }
508 _ => {}
509 }
510 idx += 1;
511 }
512 if let (Some(base_expr), Some(index_expr)) = (base, index) {
513 Ok(Expr::Index { receiver: Box::new(base_expr), index: Box::new(index_expr), span })
514 }
515 else {
516 Err(OakError::syntax_error(
517 format!("Missing base or index in index expression at {:?}", span),
518 source.get_location(span.start),
519 ))
520 }
521 }
522 RustSyntaxKind::BlockExpression => Ok(Expr::Block(self.build_block(node, source)?)),
523 _ => Err(OakError::syntax_error(
524 format!("Unknown expression type at {:?}", node.span()),
525 source.get_location(node.span().start),
526 )),
527 }
528 }
529}
530
531#[inline]
532fn text(source: &SourceText, span: Range<usize>) -> String {
533 source.get_text_in(span.into()).to_string()
534}