Skip to main content

oak_lua/ast/
mod.rs

1#![doc = include_str!("readme.md")]
2use core::range::Range;
3use oak_core::source::{SourceBuffer, ToSource};
4#[cfg(feature = "oak-pretty-print")]
5use oak_pretty_print::{AsDocument, Document};
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8
9/// Lua 根节点
10#[derive(Debug, Clone)]
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12pub struct LuaRoot {
13    pub statements: Vec<LuaStatement>,
14    #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
15    pub span: Range<usize>,
16}
17
18impl ToSource for LuaRoot {
19    fn to_source(&self, buffer: &mut SourceBuffer) {
20        for stmt in &self.statements {
21            stmt.to_source(buffer);
22            buffer.push("\n")
23        }
24    }
25}
26
27#[cfg(feature = "oak-pretty-print")]
28impl AsDocument for LuaRoot {
29    fn as_document(&self) -> Document<'_> {
30        Document::join(self.statements.iter().map(|s| s.as_document()), Document::Line)
31    }
32}
33
34/// Lua 语句
35#[derive(Debug, Clone)]
36#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
37pub enum LuaStatement {
38    Local(LuaLocalStatement),
39    Assignment(LuaAssignmentStatement),
40    Expression(LuaExpression),
41    Return(LuaReturnStatement),
42    If(LuaIfStatement),
43    While(LuaWhileStatement),
44    For(LuaForStatement),
45    Repeat(LuaRepeatStatement),
46    Function(LuaFunctionStatement),
47    Break,
48    Do(Vec<LuaStatement>),
49    Goto(String),
50    Label(String),
51}
52
53impl ToSource for LuaStatement {
54    fn to_source(&self, buffer: &mut SourceBuffer) {
55        match self {
56            LuaStatement::Local(s) => s.to_source(buffer),
57            LuaStatement::Assignment(s) => s.to_source(buffer),
58            LuaStatement::Expression(e) => e.to_source(buffer),
59            LuaStatement::Return(s) => s.to_source(buffer),
60            LuaStatement::If(s) => s.to_source(buffer),
61            LuaStatement::While(s) => s.to_source(buffer),
62            LuaStatement::For(s) => s.to_source(buffer),
63            LuaStatement::Repeat(s) => s.to_source(buffer),
64            LuaStatement::Function(s) => s.to_source(buffer),
65            LuaStatement::Break => buffer.push("break"),
66            LuaStatement::Do(stmts) => {
67                buffer.push("do\n");
68                for stmt in stmts {
69                    stmt.to_source(buffer);
70                    buffer.push("\n")
71                }
72                buffer.push("end")
73            }
74            LuaStatement::Goto(label) => {
75                buffer.push("goto ");
76                buffer.push(label)
77            }
78            LuaStatement::Label(name) => {
79                buffer.push("::");
80                buffer.push(name);
81                buffer.push("::")
82            }
83        }
84    }
85}
86
87#[cfg(feature = "oak-pretty-print")]
88impl AsDocument for LuaStatement {
89    fn as_document(&self) -> Document<'_> {
90        let mut buffer = SourceBuffer::new();
91        self.to_source(&mut buffer);
92        Document::Text(buffer.finish().into())
93    }
94}
95
96/// 本地变量声明
97#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
98#[derive(Debug, Clone)]
99pub struct LuaLocalStatement {
100    pub names: Vec<String>,
101    pub values: Vec<LuaExpression>,
102}
103
104impl ToSource for LuaLocalStatement {
105    fn to_source(&self, buffer: &mut SourceBuffer) {
106        buffer.push("local ");
107        for (i, name) in self.names.iter().enumerate() {
108            if i > 0 {
109                buffer.push(", ")
110            }
111            buffer.push(name)
112        }
113        if !self.values.is_empty() {
114            buffer.push(" = ");
115            for (i, val) in self.values.iter().enumerate() {
116                if i > 0 {
117                    buffer.push(", ")
118                }
119                val.to_source(buffer)
120            }
121        }
122    }
123}
124
125/// 赋值语句
126#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
127#[derive(Debug, Clone)]
128pub struct LuaAssignmentStatement {
129    pub targets: Vec<LuaExpression>,
130    pub values: Vec<LuaExpression>,
131}
132
133impl ToSource for LuaAssignmentStatement {
134    fn to_source(&self, buffer: &mut SourceBuffer) {
135        for (i, target) in self.targets.iter().enumerate() {
136            if i > 0 {
137                buffer.push(", ")
138            }
139            target.to_source(buffer)
140        }
141        buffer.push(" = ");
142        for (i, val) in self.values.iter().enumerate() {
143            if i > 0 {
144                buffer.push(", ")
145            }
146            val.to_source(buffer)
147        }
148    }
149}
150
151/// 返回语句
152#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
153#[derive(Debug, Clone)]
154pub struct LuaReturnStatement {
155    pub values: Vec<LuaExpression>,
156}
157
158impl ToSource for LuaReturnStatement {
159    fn to_source(&self, buffer: &mut SourceBuffer) {
160        buffer.push("return ");
161        for (i, val) in self.values.iter().enumerate() {
162            if i > 0 {
163                buffer.push(", ")
164            }
165            val.to_source(buffer)
166        }
167    }
168}
169
170/// If 语句
171#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
172#[derive(Debug, Clone)]
173pub struct LuaIfStatement {
174    pub condition: LuaExpression,
175    pub then_block: Vec<LuaStatement>,
176    pub else_ifs: Vec<(LuaExpression, Vec<LuaStatement>)>,
177    pub else_block: Option<Vec<LuaStatement>>,
178}
179
180impl ToSource for LuaIfStatement {
181    fn to_source(&self, buffer: &mut SourceBuffer) {
182        buffer.push("if ");
183        self.condition.to_source(buffer);
184        buffer.push(" then\n");
185        for stmt in &self.then_block {
186            stmt.to_source(buffer);
187            buffer.push("\n")
188        }
189        for (cond, block) in &self.else_ifs {
190            buffer.push("elseif ");
191            cond.to_source(buffer);
192            buffer.push(" then\n");
193            for stmt in block {
194                stmt.to_source(buffer);
195                buffer.push("\n")
196            }
197        }
198        if let Some(block) = &self.else_block {
199            buffer.push("else\n");
200            for stmt in block {
201                stmt.to_source(buffer);
202                buffer.push("\n")
203            }
204        }
205        buffer.push("end")
206    }
207}
208
209/// While 语句
210#[derive(Debug, Clone)]
211#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
212pub struct LuaWhileStatement {
213    pub condition: LuaExpression,
214    pub block: Vec<LuaStatement>,
215}
216
217impl ToSource for LuaWhileStatement {
218    fn to_source(&self, buffer: &mut SourceBuffer) {
219        buffer.push("while ");
220        self.condition.to_source(buffer);
221        buffer.push(" do\n");
222        for stmt in &self.block {
223            stmt.to_source(buffer);
224            buffer.push("\n")
225        }
226        buffer.push("end")
227    }
228}
229
230/// For 语句
231#[derive(Debug, Clone)]
232#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
233pub enum LuaForStatement {
234    Numeric { variable: String, start: LuaExpression, end: LuaExpression, step: Option<LuaExpression>, block: Vec<LuaStatement> },
235    Generic { variables: Vec<String>, iterators: Vec<LuaExpression>, block: Vec<LuaStatement> },
236}
237
238impl ToSource for LuaForStatement {
239    fn to_source(&self, buffer: &mut SourceBuffer) {
240        match self {
241            LuaForStatement::Numeric { variable, start, end, step, block } => {
242                buffer.push("for ");
243                buffer.push(variable);
244                buffer.push(" = ");
245                start.to_source(buffer);
246                buffer.push(", ");
247                end.to_source(buffer);
248                if let Some(s) = step {
249                    buffer.push(", ");
250                    s.to_source(buffer)
251                }
252                buffer.push(" do\n");
253                for stmt in block {
254                    stmt.to_source(buffer);
255                    buffer.push("\n")
256                }
257                buffer.push("end")
258            }
259            LuaForStatement::Generic { variables, iterators, block } => {
260                buffer.push("for ");
261                for (i, var) in variables.iter().enumerate() {
262                    if i > 0 {
263                        buffer.push(", ")
264                    }
265                    buffer.push(var)
266                }
267                buffer.push(" in ");
268                for (i, it) in iterators.iter().enumerate() {
269                    if i > 0 {
270                        buffer.push(", ")
271                    }
272                    it.to_source(buffer)
273                }
274                buffer.push(" do\n");
275                for stmt in block {
276                    stmt.to_source(buffer);
277                    buffer.push("\n")
278                }
279                buffer.push("end")
280            }
281        }
282    }
283}
284
285/// Repeat 语句
286#[derive(Debug, Clone)]
287#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
288pub struct LuaRepeatStatement {
289    pub block: Vec<LuaStatement>,
290    pub condition: LuaExpression,
291}
292
293impl ToSource for LuaRepeatStatement {
294    fn to_source(&self, buffer: &mut SourceBuffer) {
295        buffer.push("repeat\n");
296        for stmt in &self.block {
297            stmt.to_source(buffer);
298            buffer.push("\n")
299        }
300        buffer.push("until ");
301        self.condition.to_source(buffer)
302    }
303}
304
305/// 函数定义语句
306#[derive(Debug, Clone)]
307#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
308pub struct LuaFunctionStatement {
309    pub name: Vec<String>,
310    pub receiver: Option<String>,
311    pub parameters: Vec<String>,
312    pub is_vararg: bool,
313    pub block: Vec<LuaStatement>,
314}
315
316impl ToSource for LuaFunctionStatement {
317    fn to_source(&self, buffer: &mut SourceBuffer) {
318        buffer.push("function ");
319        for (i, part) in self.name.iter().enumerate() {
320            if i > 0 {
321                buffer.push(".")
322            }
323            buffer.push(part)
324        }
325        if let Some(recv) = &self.receiver {
326            buffer.push(":");
327            buffer.push(recv)
328        }
329        buffer.push("(");
330        for (i, param) in self.parameters.iter().enumerate() {
331            if i > 0 {
332                buffer.push(", ")
333            }
334            buffer.push(param)
335        }
336        if self.is_vararg {
337            if !self.parameters.is_empty() {
338                buffer.push(", ")
339            }
340            buffer.push("...")
341        }
342        buffer.push(")\n");
343        for stmt in &self.block {
344            stmt.to_source(buffer);
345            buffer.push("\n")
346        }
347        buffer.push("end")
348    }
349}
350
351/// Lua 表达式
352#[derive(Debug, Clone)]
353#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
354pub enum LuaExpression {
355    Identifier(String),
356    Number(f64),
357    String(String),
358    Boolean(bool),
359    Nil,
360    Binary(Box<LuaBinaryExpression>),
361    Unary(Box<LuaUnaryExpression>),
362    Call(Box<LuaCallExpression>),
363    Table(LuaTableConstructor),
364    Function(LuaFunctionExpression),
365    Index(Box<LuaIndexExpression>),
366    Member(Box<LuaMemberExpression>),
367    Vararg,
368}
369
370impl ToSource for LuaExpression {
371    fn to_source(&self, buffer: &mut SourceBuffer) {
372        match self {
373            LuaExpression::Identifier(id) => buffer.push(id),
374            LuaExpression::Number(n) => buffer.push(&n.to_string()),
375            LuaExpression::String(s) => {
376                buffer.push("\"");
377                buffer.push(s);
378                buffer.push("\"")
379            }
380            LuaExpression::Boolean(b) => buffer.push(if *b { "true" } else { "false" }),
381            LuaExpression::Nil => buffer.push("nil"),
382            LuaExpression::Binary(bin) => bin.to_source(buffer),
383            LuaExpression::Unary(un) => un.to_source(buffer),
384            LuaExpression::Call(call) => call.to_source(buffer),
385            LuaExpression::Table(table) => table.to_source(buffer),
386            LuaExpression::Function(func) => func.to_source(buffer),
387            LuaExpression::Index(idx) => idx.to_source(buffer),
388            LuaExpression::Member(mem) => mem.to_source(buffer),
389            LuaExpression::Vararg => buffer.push("..."),
390        }
391    }
392}
393
394#[cfg(feature = "oak-pretty-print")]
395impl AsDocument for LuaExpression {
396    fn as_document(&self) -> Document<'_> {
397        let mut buffer = SourceBuffer::new();
398        self.to_source(&mut buffer);
399        Document::Text(buffer.finish().into())
400    }
401}
402
403/// 一元表达式
404#[derive(Debug, Clone)]
405#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
406pub struct LuaUnaryExpression {
407    pub op: String,
408    pub operand: LuaExpression,
409}
410
411impl ToSource for LuaUnaryExpression {
412    fn to_source(&self, buffer: &mut SourceBuffer) {
413        buffer.push(&self.op);
414        self.operand.to_source(buffer)
415    }
416}
417
418/// 二元表达式
419#[derive(Debug, Clone)]
420#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
421pub struct LuaBinaryExpression {
422    pub left: LuaExpression,
423    pub op: String,
424    pub right: LuaExpression,
425}
426
427impl ToSource for LuaBinaryExpression {
428    fn to_source(&self, buffer: &mut SourceBuffer) {
429        self.left.to_source(buffer);
430        buffer.push(" ");
431        buffer.push(&self.op);
432        buffer.push(" ");
433        self.right.to_source(buffer)
434    }
435}
436
437/// 函数调用表达式
438#[derive(Debug, Clone)]
439#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
440pub struct LuaCallExpression {
441    pub function: LuaExpression,
442    pub arguments: Vec<LuaExpression>,
443}
444
445impl ToSource for LuaCallExpression {
446    fn to_source(&self, buffer: &mut SourceBuffer) {
447        self.function.to_source(buffer);
448        buffer.push("(");
449        for (i, arg) in self.arguments.iter().enumerate() {
450            if i > 0 {
451                buffer.push(", ")
452            }
453            arg.to_source(buffer)
454        }
455        buffer.push(")")
456    }
457}
458
459/// 表构造器
460#[derive(Debug, Clone)]
461#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
462pub struct LuaTableConstructor {
463    pub fields: Vec<LuaTableField>,
464}
465
466impl ToSource for LuaTableConstructor {
467    fn to_source(&self, buffer: &mut SourceBuffer) {
468        buffer.push("{");
469        for (i, field) in self.fields.iter().enumerate() {
470            if i > 0 {
471                buffer.push(", ")
472            }
473            field.to_source(buffer)
474        }
475        buffer.push("}")
476    }
477}
478
479#[derive(Debug, Clone)]
480#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
481pub enum LuaTableField {
482    Keyed { key: LuaExpression, value: LuaExpression },
483    Named { name: String, value: LuaExpression },
484    List { value: LuaExpression },
485}
486
487impl ToSource for LuaTableField {
488    fn to_source(&self, buffer: &mut SourceBuffer) {
489        match self {
490            LuaTableField::Keyed { key, value } => {
491                buffer.push("[");
492                key.to_source(buffer);
493                buffer.push("] = ");
494                value.to_source(buffer)
495            }
496            LuaTableField::Named { name, value } => {
497                buffer.push(name);
498                buffer.push(" = ");
499                value.to_source(buffer)
500            }
501            LuaTableField::List { value } => value.to_source(buffer),
502        }
503    }
504}
505
506/// 匿名函数表达式
507#[derive(Debug, Clone)]
508#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
509pub struct LuaFunctionExpression {
510    pub parameters: Vec<String>,
511    pub is_vararg: bool,
512    pub block: Vec<LuaStatement>,
513}
514
515impl ToSource for LuaFunctionExpression {
516    fn to_source(&self, buffer: &mut SourceBuffer) {
517        buffer.push("function(");
518        for (i, param) in self.parameters.iter().enumerate() {
519            if i > 0 {
520                buffer.push(", ")
521            }
522            buffer.push(param)
523        }
524        if self.is_vararg {
525            if !self.parameters.is_empty() {
526                buffer.push(", ")
527            }
528            buffer.push("...")
529        }
530        buffer.push(")\n");
531        for stmt in &self.block {
532            stmt.to_source(buffer);
533            buffer.push("\n")
534        }
535        buffer.push("end")
536    }
537}
538
539/// 索引访问表达式
540#[derive(Debug, Clone)]
541#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
542pub struct LuaIndexExpression {
543    pub table: LuaExpression,
544    pub index: LuaExpression,
545}
546
547impl ToSource for LuaIndexExpression {
548    fn to_source(&self, buffer: &mut SourceBuffer) {
549        self.table.to_source(buffer);
550        buffer.push("[");
551        self.index.to_source(buffer);
552        buffer.push("]")
553    }
554}
555
556/// 成员访问表达式
557#[derive(Debug, Clone)]
558#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
559pub struct LuaMemberExpression {
560    pub table: LuaExpression,
561    pub member: String,
562    pub is_method: bool,
563}
564
565impl ToSource for LuaMemberExpression {
566    fn to_source(&self, buffer: &mut SourceBuffer) {
567        self.table.to_source(buffer);
568        if self.is_method {
569            buffer.push(":")
570        }
571        else {
572            buffer.push(".")
573        }
574        buffer.push(&self.member)
575    }
576}