Skip to main content

oak_lua/builder/
mod.rs

1use crate::{
2    ast::*,
3    language::LuaLanguage,
4    lexer::{LuaLexer, token_type::LuaTokenType},
5    parser::{LuaElementType, LuaParser},
6};
7use oak_core::{
8    Builder, BuilderCache, Lexer, Parser, Source, TextEdit,
9    builder::BuildOutput,
10    parser::session::ParseSession,
11    tree::{GreenNode, GreenTree},
12};
13
14/// Lua AST 构建器
15#[derive(Clone)]
16pub struct LuaBuilder<'config> {
17    config: &'config LuaLanguage,
18}
19
20impl<'config> LuaBuilder<'config> {
21    pub fn new(config: &'config LuaLanguage) -> Self {
22        Self { config }
23    }
24}
25
26impl<'config> Builder<LuaLanguage> for LuaBuilder<'config> {
27    fn build<'a, S: Source + ?Sized>(&self, source: &S, edits: &[TextEdit], _cache: &'a mut impl BuilderCache<LuaLanguage>) -> BuildOutput<LuaLanguage> {
28        let parser = LuaParser::new(self.config);
29        let lexer = LuaLexer::new(self.config);
30
31        let mut session = ParseSession::<LuaLanguage>::default();
32        lexer.lex(source, edits, &mut session);
33        let parse_result = parser.parse(source, edits, &mut session);
34
35        match parse_result.result {
36            Ok(green_tree) => match self.build_root(green_tree.clone(), source) {
37                Ok(ast_root) => oak_core::errors::OakDiagnostics { result: Ok(ast_root), diagnostics: parse_result.diagnostics },
38                Err(build_error) => {
39                    let mut diagnostics = parse_result.diagnostics;
40                    diagnostics.push(build_error.clone());
41                    oak_core::errors::OakDiagnostics { result: Err(build_error), diagnostics }
42                }
43            },
44            Err(parse_error) => oak_core::errors::OakDiagnostics { result: Err(parse_error), diagnostics: parse_result.diagnostics },
45        }
46    }
47}
48
49impl<'config> LuaBuilder<'config> {
50    fn build_root<S: Source + ?Sized>(&self, green_tree: GreenNode<LuaLanguage>, source: &S) -> Result<LuaRoot, oak_core::OakError> {
51        let mut statements = Vec::new();
52        let mut offset = 0;
53        for child in green_tree.children() {
54            match child {
55                GreenTree::Node(node) => {
56                    if let Some(stmt) = self.build_statement(node, source, offset)? {
57                        statements.push(stmt)
58                    }
59                }
60                GreenTree::Leaf(_) => {}
61            }
62            offset += child.len() as usize
63        }
64        Ok(LuaRoot { statements, span: (0..offset).into() })
65    }
66
67    fn build_statement<S: Source + ?Sized>(&self, node: &GreenNode<LuaLanguage>, source: &S, offset: usize) -> Result<Option<LuaStatement>, oak_core::OakError> {
68        match node.kind {
69            LuaElementType::LocalStatement => {
70                let mut names = Vec::new();
71                let mut values = Vec::new();
72                let mut child_offset = offset;
73                for child in node.children() {
74                    match child {
75                        GreenTree::Leaf(leaf) if leaf.kind == LuaTokenType::Identifier => names.push(source.get_text_in(oak_core::Range { start: child_offset, end: child_offset + leaf.length as usize }).to_string()),
76                        GreenTree::Node(child_node) => {
77                            if let Some(expr) = self.build_expression(child_node, source, child_offset)? {
78                                values.push(expr)
79                            }
80                        }
81                        _ => {}
82                    }
83                    child_offset += child.len() as usize
84                }
85                Ok(Some(LuaStatement::Local(LuaLocalStatement { names, values })))
86            }
87            LuaElementType::AssignmentStatement => {
88                let mut targets = Vec::new();
89                let mut values = Vec::new();
90                let mut child_offset = offset;
91                let mut after_eq = false;
92                for child in node.children() {
93                    match child {
94                        GreenTree::Node(child_node) => {
95                            if let Some(expr) = self.build_expression(child_node, source, child_offset)? {
96                                if after_eq { values.push(expr) } else { targets.push(expr) }
97                            }
98                        }
99                        GreenTree::Leaf(leaf) if leaf.kind == LuaTokenType::Eq => after_eq = true,
100                        _ => {}
101                    }
102                    child_offset += child.len() as usize
103                }
104                Ok(Some(LuaStatement::Assignment(LuaAssignmentStatement { targets, values })))
105            }
106            LuaElementType::ExpressionStatement => {
107                let mut child_offset = offset;
108                for child in node.children() {
109                    if let GreenTree::Node(child_node) = child {
110                        if let Some(expr) = self.build_expression(child_node, source, child_offset)? {
111                            return Ok(Some(LuaStatement::Expression(expr)));
112                        }
113                    }
114                    child_offset += child.len() as usize
115                }
116                Ok(None)
117            }
118            LuaElementType::ReturnStatement => {
119                let mut values = Vec::new();
120                let mut child_offset = offset;
121                for child in node.children() {
122                    if let GreenTree::Node(child_node) = child {
123                        if let Some(expr) = self.build_expression(child_node, source, child_offset)? {
124                            values.push(expr)
125                        }
126                    }
127                    child_offset += child.len() as usize
128                }
129                Ok(Some(LuaStatement::Return(LuaReturnStatement { values })))
130            }
131            LuaElementType::BreakStatement => Ok(Some(LuaStatement::Break)),
132            LuaElementType::GotoStatement => {
133                let mut child_offset = offset;
134                for child in node.children() {
135                    if let GreenTree::Leaf(leaf) = child {
136                        if leaf.kind == LuaTokenType::Identifier {
137                            let text = source.get_text_in(oak_core::Range { start: child_offset, end: child_offset + leaf.length as usize });
138                            return Ok(Some(LuaStatement::Goto(text.to_string())));
139                        }
140                    }
141                    child_offset += child.len() as usize
142                }
143                Ok(None)
144            }
145            LuaElementType::LabelStatement => {
146                let mut child_offset = offset;
147                for child in node.children() {
148                    if let GreenTree::Leaf(leaf) = child {
149                        if leaf.kind == LuaTokenType::Identifier {
150                            let text = source.get_text_in(oak_core::Range { start: child_offset, end: child_offset + leaf.length as usize });
151                            return Ok(Some(LuaStatement::Label(text.to_string())));
152                        }
153                    }
154                    child_offset += child.len() as usize
155                }
156                Ok(None)
157            }
158            LuaElementType::IfStatement => {
159                let mut condition = None;
160                let mut then_block = Vec::new();
161                let mut else_ifs = Vec::new();
162                let mut else_block = None;
163
164                let mut child_offset = offset;
165                let mut state = 0; // 0: if-cond, 1: then-block, 2: elseif-cond, 3: elseif-block, 4: else-block
166
167                for child in node.children() {
168                    match child {
169                        GreenTree::Leaf(leaf) => match leaf.kind {
170                            LuaTokenType::If => state = 0,
171                            LuaTokenType::Then => {
172                                if state == 0 {
173                                    state = 1
174                                }
175                                else if state == 2 {
176                                    state = 3
177                                }
178                            }
179                            LuaTokenType::Elseif => state = 2,
180                            LuaTokenType::Else => {
181                                state = 4;
182                                else_block = Some(Vec::new())
183                            }
184                            _ => {}
185                        },
186                        GreenTree::Node(child_node) => match state {
187                            0 => {
188                                if let Some(expr) = self.build_expression(child_node, source, child_offset)? {
189                                    condition = Some(expr)
190                                }
191                            }
192                            1 => {
193                                if let Some(stmt) = self.build_statement(child_node, source, child_offset)? {
194                                    then_block.push(stmt)
195                                }
196                            }
197                            2 => {
198                                if let Some(expr) = self.build_expression(child_node, source, child_offset)? {
199                                    else_ifs.push((expr, Vec::new()))
200                                }
201                            }
202                            3 => {
203                                if let Some(stmt) = self.build_statement(child_node, source, child_offset)? {
204                                    if let Some(last) = else_ifs.last_mut() {
205                                        last.1.push(stmt)
206                                    }
207                                }
208                            }
209                            4 => {
210                                if let Some(stmt) = self.build_statement(child_node, source, child_offset)? {
211                                    if let Some(block) = &mut else_block {
212                                        block.push(stmt)
213                                    }
214                                }
215                            }
216                            _ => {}
217                        },
218                    }
219                    child_offset += child.len() as usize
220                }
221
222                if let Some(cond) = condition { Ok(Some(LuaStatement::If(LuaIfStatement { condition: cond, then_block, else_ifs, else_block }))) } else { Ok(None) }
223            }
224            LuaElementType::WhileStatement => {
225                let mut condition = None;
226                let mut block = Vec::new();
227                let mut child_offset = offset;
228                let mut in_block = false;
229
230                for child in node.children() {
231                    match child {
232                        GreenTree::Leaf(leaf) if leaf.kind == LuaTokenType::Do => in_block = true,
233                        GreenTree::Node(child_node) => {
234                            if in_block {
235                                if let Some(stmt) = self.build_statement(child_node, source, child_offset)? {
236                                    block.push(stmt)
237                                }
238                            }
239                            else {
240                                if let Some(expr) = self.build_expression(child_node, source, child_offset)? {
241                                    condition = Some(expr)
242                                }
243                            }
244                        }
245                        _ => {}
246                    }
247                    child_offset += child.len() as usize
248                }
249                if let Some(cond) = condition { Ok(Some(LuaStatement::While(LuaWhileStatement { condition: cond, block }))) } else { Ok(None) }
250            }
251            LuaElementType::ForStatement => {
252                let mut variables = Vec::new();
253                let mut expressions = Vec::new();
254                let mut block = Vec::new();
255                let mut child_offset = offset;
256                let mut in_block = false;
257                let mut after_in = false;
258                let mut after_eq = false;
259
260                for child in node.children() {
261                    match child {
262                        GreenTree::Leaf(leaf) => match leaf.kind {
263                            LuaTokenType::Identifier => variables.push(source.get_text_in(oak_core::Range { start: child_offset, end: child_offset + leaf.length as usize }).to_string()),
264                            LuaTokenType::Eq => after_eq = true,
265                            LuaTokenType::In => after_in = true,
266                            LuaTokenType::Do => in_block = true,
267                            _ => {}
268                        },
269                        GreenTree::Node(child_node) => {
270                            if in_block {
271                                if let Some(stmt) = self.build_statement(child_node, source, child_offset)? {
272                                    block.push(stmt)
273                                }
274                            }
275                            else {
276                                if let Some(expr) = self.build_expression(child_node, source, child_offset)? {
277                                    expressions.push(expr)
278                                }
279                            }
280                        }
281                    }
282                    child_offset += child.len() as usize
283                }
284
285                if after_in {
286                    Ok(Some(LuaStatement::For(LuaForStatement::Generic { variables, iterators: expressions, block })))
287                }
288                else if after_eq && !variables.is_empty() && expressions.len() >= 2 {
289                    Ok(Some(LuaStatement::For(LuaForStatement::Numeric { variable: variables[0].clone(), start: expressions[0].clone(), end: expressions[1].clone(), step: expressions.get(2).cloned(), block })))
290                }
291                else {
292                    Ok(None)
293                }
294            }
295            LuaElementType::RepeatStatement => {
296                let mut block = Vec::new();
297                let mut condition = None;
298                let mut child_offset = offset;
299                let mut after_until = false;
300
301                for child in node.children() {
302                    match child {
303                        GreenTree::Leaf(leaf) if leaf.kind == LuaTokenType::Until => after_until = true,
304                        GreenTree::Node(child_node) => {
305                            if after_until {
306                                if let Some(expr) = self.build_expression(child_node, source, child_offset)? {
307                                    condition = Some(expr)
308                                }
309                            }
310                            else {
311                                if let Some(stmt) = self.build_statement(child_node, source, child_offset)? {
312                                    block.push(stmt)
313                                }
314                            }
315                        }
316                        _ => {}
317                    }
318                    child_offset += child.len() as usize
319                }
320                if let Some(cond) = condition { Ok(Some(LuaStatement::Repeat(LuaRepeatStatement { block, condition: cond }))) } else { Ok(None) }
321            }
322            LuaElementType::DoStatement => {
323                let mut block = Vec::new();
324                let mut child_offset = offset;
325                for child in node.children() {
326                    if let GreenTree::Node(child_node) = child {
327                        if let Some(stmt) = self.build_statement(child_node, source, child_offset)? {
328                            block.push(stmt)
329                        }
330                    }
331                    child_offset += child.len() as usize
332                }
333                Ok(Some(LuaStatement::Do(block)))
334            }
335            LuaElementType::FunctionDeclaration => {
336                let mut name = Vec::new();
337                let mut receiver = None;
338                let mut parameters = Vec::new();
339                let mut is_vararg = false;
340                let mut block = Vec::new();
341
342                let mut child_offset = offset;
343                let mut state = 0; // 0: name, 1: parameters, 2: block
344
345                for child in node.children() {
346                    match child {
347                        GreenTree::Leaf(leaf) => {
348                            match leaf.kind {
349                                LuaTokenType::Identifier => {
350                                    let text = source.get_text_in(oak_core::Range { start: child_offset, end: child_offset + leaf.length as usize }).to_string();
351                                    if state == 0 {
352                                        name.push(text)
353                                    }
354                                    else if state == 1 {
355                                        parameters.push(text)
356                                    }
357                                }
358                                LuaTokenType::Colon => {
359                                    // Receiver follows - in Lua function name: method,
360                                    // the part before colon is name parts, part after colon is method name
361                                    // But usually it's obj:method, where obj is name parts.
362                                    if state == 0 {
363                                        // The current name parts we have are the receiver parts.
364                                        // We'll move them to receiver and start fresh for method name?
365                                        // Actually LuaFunctionStatement has name: Vec<String> and receiver: Option<String>.
366                                        // Usually it's function a.b:c() -> name=["a", "b"], receiver=Some("c")
367                                        if !name.is_empty() {
368                                            receiver = name.pop()
369                                        }
370                                    }
371                                }
372                                LuaTokenType::LeftParen => state = 1,
373                                LuaTokenType::RightParen => state = 2,
374                                LuaTokenType::DotDotDot => is_vararg = true,
375                                _ => {}
376                            }
377                        }
378                        GreenTree::Node(child_node) => {
379                            if state == 2 {
380                                if let Some(stmt) = self.build_statement(child_node, source, child_offset)? {
381                                    block.push(stmt)
382                                }
383                            }
384                            else if child_node.kind == LuaElementType::FunctionName {
385                                // Recursive name building if nested
386                                let mut name_offset = child_offset;
387                                for name_child in child_node.children() {
388                                    match name_child {
389                                        GreenTree::Leaf(leaf) => {
390                                            if leaf.kind == LuaTokenType::Identifier {
391                                                name.push(source.get_text_in(oak_core::Range { start: name_offset, end: name_offset + leaf.length as usize }).to_string())
392                                            }
393                                            else if leaf.kind == LuaTokenType::Colon {
394                                                if !name.is_empty() {
395                                                    receiver = name.pop()
396                                                }
397                                            }
398                                        }
399                                        _ => {}
400                                    }
401                                    name_offset += name_child.len() as usize
402                                }
403                            }
404                        }
405                    }
406                    child_offset += child.len() as usize
407                }
408
409                Ok(Some(LuaStatement::Function(LuaFunctionStatement { name, receiver, parameters, is_vararg, block })))
410            }
411            _ => Ok(None),
412        }
413    }
414
415    fn build_expression<S: Source + ?Sized>(&self, node: &GreenNode<LuaLanguage>, source: &S, offset: usize) -> Result<Option<LuaExpression>, oak_core::OakError> {
416        match node.kind {
417            LuaElementType::LiteralExpression => {
418                for child in node.children() {
419                    if let GreenTree::Leaf(leaf) = child {
420                        match leaf.kind {
421                            LuaTokenType::Number => {
422                                let text = source.get_text_in(oak_core::Range { start: offset, end: offset + leaf.length as usize });
423                                if let Ok(val) = text.parse::<f64>() {
424                                    return Ok(Some(LuaExpression::Number(val)));
425                                }
426                            }
427                            LuaTokenType::String => {
428                                let text = source.get_text_in(oak_core::Range { start: offset, end: offset + leaf.length as usize });
429                                // Simple quote removal
430                                let s = if text.len() >= 2 { &text[1..text.len() - 1] } else { &text };
431                                return Ok(Some(LuaExpression::String(s.to_string())));
432                            }
433                            LuaTokenType::True => return Ok(Some(LuaExpression::Boolean(true))),
434                            LuaTokenType::False => return Ok(Some(LuaExpression::Boolean(false))),
435                            LuaTokenType::Nil => return Ok(Some(LuaExpression::Nil)),
436                            _ => {}
437                        }
438                    }
439                }
440                Ok(None)
441            }
442            LuaElementType::IdentifierExpression => {
443                for child in node.children() {
444                    if let GreenTree::Leaf(leaf) = child {
445                        if leaf.kind == LuaTokenType::Identifier {
446                            let name = source.get_text_in(oak_core::Range { start: offset, end: offset + leaf.length as usize }).to_string();
447                            return Ok(Some(LuaExpression::Identifier(name)));
448                        }
449                    }
450                }
451                Ok(None)
452            }
453            LuaElementType::BinaryExpression => {
454                let mut left = None;
455                let mut op = String::new();
456                let mut right = None;
457                let mut child_offset = offset;
458
459                for child in node.children() {
460                    match child {
461                        GreenTree::Node(child_node) => {
462                            if let Some(expr) = self.build_expression(child_node, source, child_offset)? {
463                                if left.is_none() { left = Some(expr) } else { right = Some(expr) }
464                            }
465                        }
466                        GreenTree::Leaf(leaf) => {
467                            // Binary operators
468                            match leaf.kind {
469                                LuaTokenType::Plus
470                                | LuaTokenType::Minus
471                                | LuaTokenType::Star
472                                | LuaTokenType::Slash
473                                | LuaTokenType::Percent
474                                | LuaTokenType::Caret
475                                | LuaTokenType::Lt
476                                | LuaTokenType::LtEq
477                                | LuaTokenType::Gt
478                                | LuaTokenType::GtEq
479                                | LuaTokenType::EqEq
480                                | LuaTokenType::TildeEq
481                                | LuaTokenType::Ampersand
482                                | LuaTokenType::Pipe
483                                | LuaTokenType::Tilde
484                                | LuaTokenType::LtLt
485                                | LuaTokenType::GtGt
486                                | LuaTokenType::SlashSlash
487                                | LuaTokenType::And
488                                | LuaTokenType::Or
489                                | LuaTokenType::DotDot => op = source.get_text_in(oak_core::Range { start: child_offset, end: child_offset + leaf.length as usize }).to_string(),
490                                _ => {}
491                            }
492                        }
493                    }
494                    child_offset += child.len() as usize
495                }
496
497                if let (Some(l), Some(r)) = (left, right) { Ok(Some(LuaExpression::Binary(Box::new(LuaBinaryExpression { left: l, op, right: r })))) } else { Ok(None) }
498            }
499            LuaElementType::UnaryExpression => {
500                let mut op = String::new();
501                let mut operand = None;
502                let mut child_offset = offset;
503
504                for child in node.children() {
505                    match child {
506                        GreenTree::Node(child_node) => operand = self.build_expression(child_node, source, child_offset)?,
507                        GreenTree::Leaf(leaf) => match leaf.kind {
508                            LuaTokenType::Minus | LuaTokenType::Not | LuaTokenType::Hash | LuaTokenType::Tilde => op = source.get_text_in(oak_core::Range { start: child_offset, end: child_offset + leaf.length as usize }).to_string(),
509                            _ => {}
510                        },
511                    }
512                    child_offset += child.len() as usize
513                }
514
515                if let Some(o) = operand { Ok(Some(LuaExpression::Unary(Box::new(LuaUnaryExpression { op, operand: o })))) } else { Ok(None) }
516            }
517            LuaElementType::CallExpression => {
518                let mut function = None;
519                let mut arguments = Vec::new();
520                let mut child_offset = offset;
521
522                for child in node.children() {
523                    if let GreenTree::Node(child_node) = child {
524                        if let Some(expr) = self.build_expression(child_node, source, child_offset)? {
525                            if function.is_none() { function = Some(expr) } else { arguments.push(expr) }
526                        }
527                    }
528                    else if let GreenTree::Leaf(leaf) = child {
529                        if leaf.kind == LuaTokenType::String {
530                            let text = source.get_text_in(oak_core::Range { start: child_offset, end: child_offset + leaf.length as usize });
531                            let s = if text.len() >= 2 { &text[1..text.len() - 1] } else { &text };
532                            arguments.push(LuaExpression::String(s.to_string()))
533                        }
534                    }
535                    child_offset += child.len() as usize
536                }
537
538                if let Some(f) = function { Ok(Some(LuaExpression::Call(Box::new(LuaCallExpression { function: f, arguments })))) } else { Ok(None) }
539            }
540            LuaElementType::TableConstructorExpression => {
541                let mut fields = Vec::new();
542                let mut child_offset = offset;
543                for child in node.children() {
544                    if let GreenTree::Node(child_node) = child {
545                        if child_node.kind == LuaElementType::TableField {
546                            let mut key = None;
547                            let mut value = None;
548                            let mut name = None;
549                            let mut field_offset = child_offset;
550                            let mut after_eq = false;
551
552                            for field_child in child_node.children() {
553                                match field_child {
554                                    GreenTree::Leaf(leaf) => {
555                                        if leaf.kind == LuaTokenType::Identifier && !after_eq {
556                                            name = Some(source.get_text_in(oak_core::Range { start: field_offset, end: field_offset + leaf.length as usize }).to_string())
557                                        }
558                                        else if leaf.kind == LuaTokenType::Eq {
559                                            after_eq = true
560                                        }
561                                    }
562                                    GreenTree::Node(field_node) => {
563                                        if let Some(expr) = self.build_expression(field_node, source, field_offset)? {
564                                            if key.is_none() && !after_eq && name.is_none() { key = Some(expr) } else { value = Some(expr) }
565                                        }
566                                    }
567                                }
568                                field_offset += field_child.len() as usize
569                            }
570
571                            if let Some(v) = value {
572                                if let Some(k) = key {
573                                    fields.push(LuaTableField::Keyed { key: k, value: v })
574                                }
575                                else if let Some(n) = name {
576                                    fields.push(LuaTableField::Named { name: n, value: v })
577                                }
578                                else {
579                                    fields.push(LuaTableField::List { value: v })
580                                }
581                            }
582                            else if let Some(k) = key {
583                                fields.push(LuaTableField::List { value: k })
584                            }
585                        }
586                    }
587                    child_offset += child.len() as usize
588                }
589                Ok(Some(LuaExpression::Table(LuaTableConstructor { fields })))
590            }
591            LuaElementType::FunctionExpression => {
592                let mut parameters = Vec::new();
593                let mut is_vararg = false;
594                let mut block = Vec::new();
595                let mut child_offset = offset;
596                let mut state = 0; // 0: params, 1: block
597
598                for child in node.children() {
599                    match child {
600                        GreenTree::Leaf(leaf) => match leaf.kind {
601                            LuaTokenType::Identifier if state == 0 => parameters.push(source.get_text_in(oak_core::Range { start: child_offset, end: child_offset + leaf.length as usize }).to_string()),
602                            LuaTokenType::DotDotDot => is_vararg = true,
603                            LuaTokenType::RightParen => state = 1,
604                            _ => {}
605                        },
606                        GreenTree::Node(child_node) => {
607                            if state == 1 {
608                                if let Some(stmt) = self.build_statement(child_node, source, child_offset)? {
609                                    block.push(stmt)
610                                }
611                            }
612                        }
613                    }
614                    child_offset += child.len() as usize
615                }
616                Ok(Some(LuaExpression::Function(LuaFunctionExpression { parameters, is_vararg, block })))
617            }
618            LuaElementType::MemberExpression => {
619                let mut table = None;
620                let mut member = String::new();
621                let mut is_method = false;
622                let mut child_offset = offset;
623
624                for child in node.children() {
625                    match child {
626                        GreenTree::Node(child_node) => {
627                            if table.is_none() {
628                                table = self.build_expression(child_node, source, child_offset)?
629                            }
630                        }
631                        GreenTree::Leaf(leaf) => {
632                            if leaf.kind == LuaTokenType::Identifier {
633                                member = source.get_text_in(oak_core::Range { start: child_offset, end: child_offset + leaf.length as usize }).to_string()
634                            }
635                            else if leaf.kind == LuaTokenType::Colon {
636                                is_method = true
637                            }
638                        }
639                    }
640                    child_offset += child.len() as usize
641                }
642
643                if let Some(t) = table { Ok(Some(LuaExpression::Member(Box::new(LuaMemberExpression { table: t, member, is_method })))) } else { Ok(None) }
644            }
645            LuaElementType::IndexExpression => {
646                let mut table = None;
647                let mut index = None;
648                let mut child_offset = offset;
649
650                for child in node.children() {
651                    if let GreenTree::Node(child_node) = child {
652                        if table.is_none() { table = self.build_expression(child_node, source, child_offset)? } else { index = self.build_expression(child_node, source, child_offset)? }
653                    }
654                    child_offset += child.len() as usize
655                }
656
657                if let (Some(t), Some(i)) = (table, index) { Ok(Some(LuaExpression::Index(Box::new(LuaIndexExpression { table: t, index: i })))) } else { Ok(None) }
658            }
659            LuaElementType::VarargExpression => Ok(Some(LuaExpression::Vararg)),
660            LuaElementType::ParenthesizedExpression => {
661                let mut child_offset = offset;
662                for child in node.children() {
663                    if let GreenTree::Node(child_node) = child {
664                        if let Some(expr) = self.build_expression(child_node, source, child_offset)? {
665                            return Ok(Some(expr));
666                        }
667                    }
668                    child_offset += child.len() as usize
669                }
670                Ok(None)
671            }
672            _ => Ok(None),
673        }
674    }
675}