oak_rust/builder/
mod.rs

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        // 提前构造 SourceText 引用以便后续 AST 构建
18        let source_text = SourceText::new(text.get_text_in((0..text.length()).into()));
19        // 解析源代码获得语法树
20        let parse_result = self.parse_incremental(text, changed, cache);
21        
22        // 检查解析是否成功
23        match parse_result.result {
24            Ok(green_tree) => {
25                // 构建 AST
26                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    /// 从红绿树提取强类型 AST
87
88    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        // children: IDENT ':' IDENT
143        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(); // Consume the semicolon
231            }
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        // Expect 'let' keyword
249        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        // Expect identifier
263        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        // Check for optional '=' and expression
281        if let Some(RedTree::Leaf(t)) = children_iter.peek() {
282            if t.kind == RustSyntaxKind::Eq {
283                children_iter.next(); // Consume '=' token
284
285                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                // child: IDENT
323                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                // children: callee '(' args... ')' with commas
430                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                                // The first node is the receiver
470                                receiver = Some(self.build_expr(n, source)?);
471                            }
472                        }
473                        RedTree::Leaf(t) => {
474                            if idx == 2 && t.kind == RustSyntaxKind::Identifier {
475                                // The third child (leaf) is the identifier
476                                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                // children: base '[' index ']'
495                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}