rslua/
ast.rs

1use crate::tokens::{Token, TokenType};
2use crate::types::{FloatType, IntType};
3use rslua_traits::Comments;
4
5#[derive(Clone, PartialEq, Debug)]
6pub enum UnOp {
7    Minus(Token),
8    BNot(Token),
9    Not(Token),
10    Len(Token),
11    None,
12}
13
14impl Comments for UnOp {
15    fn get_comments(&self) -> Vec<&str> {
16        match self {
17            UnOp::Minus(token) => token.get_comments(),
18            UnOp::BNot(token) => token.get_comments(),
19            UnOp::Not(token) => token.get_comments(),
20            UnOp::Len(token) => token.get_comments(),
21            UnOp::None => vec![],
22        }
23    }
24}
25
26impl UnOp {
27    pub fn from_token(token: Token) -> UnOp {
28        match token.t {
29            TokenType::Minus => UnOp::Minus(token),
30            TokenType::BXor => UnOp::BNot(token),
31            TokenType::Not => UnOp::Not(token),
32            TokenType::Len => UnOp::Len(token),
33            _ => UnOp::None,
34        }
35    }
36    pub fn priority(&self) -> u8 {
37        12
38    }
39}
40
41#[derive(Clone, PartialEq, Debug)]
42pub enum BinOp {
43    Add(Token),
44    Minus(Token),
45    Mul(Token),
46    Mod(Token),
47    Pow(Token),
48    Div(Token),
49    IDiv(Token),
50    BAnd(Token),
51    BOr(Token),
52    BXor(Token),
53    Shl(Token),
54    Shr(Token),
55    Concat(Token),
56    Ne(Token),
57    Eq(Token),
58    Lt(Token),
59    Le(Token),
60    Gt(Token),
61    Ge(Token),
62    And(Token),
63    Or(Token),
64    None,
65}
66
67pub struct BinOpPriority {
68    pub left: u8,
69    pub right: u8,
70}
71
72impl BinOp {
73    pub fn from_token(token: Token) -> BinOp {
74        match token.t {
75            TokenType::Add => BinOp::Add(token),
76            TokenType::Minus => BinOp::Minus(token),
77            TokenType::Mul => BinOp::Mul(token),
78            TokenType::Mod => BinOp::Mod(token),
79            TokenType::Pow => BinOp::Pow(token),
80            TokenType::Div => BinOp::Div(token),
81            TokenType::IDiv => BinOp::IDiv(token),
82            TokenType::BAnd => BinOp::BAnd(token),
83            TokenType::BOr => BinOp::BOr(token),
84            TokenType::BXor => BinOp::BXor(token),
85            TokenType::Shl => BinOp::Shl(token),
86            TokenType::Shr => BinOp::Shr(token),
87            TokenType::Concat => BinOp::Concat(token),
88            TokenType::Ne => BinOp::Ne(token),
89            TokenType::Eq => BinOp::Eq(token),
90            TokenType::Lt => BinOp::Lt(token),
91            TokenType::Le => BinOp::Le(token),
92            TokenType::Gt => BinOp::Gt(token),
93            TokenType::Ge => BinOp::Ge(token),
94            TokenType::And => BinOp::And(token),
95            TokenType::Or => BinOp::Or(token),
96            _ => BinOp::None,
97        }
98    }
99
100    pub fn priority(&self) -> BinOpPriority {
101        match self {
102            BinOp::Or(_) => BinOpPriority { left: 1, right: 1 },
103            BinOp::And(_) => BinOpPriority { left: 2, right: 2 },
104            BinOp::Eq(_)
105            | BinOp::Ne(_)
106            | BinOp::Lt(_)
107            | BinOp::Gt(_)
108            | BinOp::Le(_)
109            | BinOp::Ge(_) => BinOpPriority { left: 3, right: 3 },
110            BinOp::BOr(_) => BinOpPriority { left: 4, right: 4 },
111            BinOp::BXor(_) => BinOpPriority { left: 5, right: 5 },
112            BinOp::BAnd(_) => BinOpPriority { left: 6, right: 6 },
113            BinOp::Shl(_) | BinOp::Shr(_) => BinOpPriority { left: 7, right: 7 },
114            BinOp::Concat(_) => BinOpPriority { left: 9, right: 8 },
115            BinOp::Add(_) | BinOp::Minus(_) => BinOpPriority {
116                left: 10,
117                right: 10,
118            },
119            BinOp::Mul(_) | BinOp::Mod(_) | BinOp::Div(_) | BinOp::IDiv(_) => BinOpPriority {
120                left: 11,
121                right: 11,
122            },
123            BinOp::Pow(_) => BinOpPriority {
124                left: 14,
125                right: 13,
126            },
127            _ => unreachable!(),
128        }
129    }
130
131    pub fn is_comp(&self) -> bool {
132        matches!(
133            self,
134            BinOp::Le(_) | BinOp::Ge(_) | BinOp::Ne(_) | BinOp::Eq(_) | BinOp::Lt(_) | BinOp::Gt(_)
135        )
136    }
137}
138
139impl Comments for BinOp {
140    fn get_comments(&self) -> Vec<&str> {
141        // refactor this
142        match self {
143            BinOp::Add(token) => token.get_comments(),
144            BinOp::Minus(token) => token.get_comments(),
145            BinOp::Mul(token) => token.get_comments(),
146            BinOp::Mod(token) => token.get_comments(),
147            BinOp::Pow(token) => token.get_comments(),
148            BinOp::Div(token) => token.get_comments(),
149            BinOp::IDiv(token) => token.get_comments(),
150            BinOp::BAnd(token) => token.get_comments(),
151            BinOp::BOr(token) => token.get_comments(),
152            BinOp::BXor(token) => token.get_comments(),
153            BinOp::Shl(token) => token.get_comments(),
154            BinOp::Shr(token) => token.get_comments(),
155            BinOp::Concat(token) => token.get_comments(),
156            BinOp::Ne(token) => token.get_comments(),
157            BinOp::Eq(token) => token.get_comments(),
158            BinOp::Lt(token) => token.get_comments(),
159            BinOp::Le(token) => token.get_comments(),
160            BinOp::Gt(token) => token.get_comments(),
161            BinOp::Ge(token) => token.get_comments(),
162            BinOp::And(token) => token.get_comments(),
163            BinOp::Or(token) => token.get_comments(),
164            _ => unreachable!(),
165        }
166    }
167}
168
169#[derive(PartialEq, Clone, Debug)]
170pub enum Expr {
171    Nil(Token),
172    True(Token),
173    False(Token),
174    VarArg(Token),
175    Float(FloatExpr),
176    Int(IntExpr),
177    String(StringExpr),
178    Name(StringExpr),
179    ParenExpr(Box<Expr>),
180    FuncBody(FuncBody),
181    Table(Table),
182    BinExpr(BinExpr),
183    UnExpr(UnExpr),
184    SuffixedExpr(SuffixedExpr),
185}
186
187impl Expr {
188    pub fn to_assignable(self) -> Assignable {
189        match self {
190            Expr::Name(s) => Assignable::Name(s),
191            Expr::SuffixedExpr(s) => Assignable::SuffixedExpr(s),
192            _ => unreachable!(),
193        }
194    }
195
196    pub fn unwrap_as_int(&self) -> IntType {
197        match &self {
198            Expr::Int(expr) => expr.value(),
199            _ => unreachable!(),
200        }
201    }
202
203    pub fn unwrap_as_float(&self) -> FloatType {
204        match &self {
205            Expr::Float(expr) => expr.value(),
206            _ => unreachable!(),
207        }
208    }
209
210    pub fn unwrap_as_string(&self) -> String {
211        match &self {
212            Expr::String(expr) => expr.value(),
213            _ => unreachable!(),
214        }
215    }
216
217    pub fn unwrap_as_name(&self) -> &StringExpr {
218        match &self {
219            Expr::Name(expr) => expr,
220            _ => unreachable!(),
221        }
222    }
223}
224
225impl Comments for Expr {
226    fn get_comments(&self) -> Vec<&str> {
227        match &self {
228            Expr::Nil(token) => token.get_comments(),
229            Expr::True(token) => token.get_comments(),
230            Expr::False(token) => token.get_comments(),
231            Expr::VarArg(token) => token.get_comments(),
232            Expr::Float(expr) => expr.get_comments(),
233            Expr::Int(expr) => expr.get_comments(),
234            Expr::String(expr) => expr.get_comments(),
235            Expr::Name(expr) => expr.get_comments(),
236            Expr::ParenExpr(expr) => expr.get_comments(),
237            Expr::FuncBody(expr) => expr.get_comments(),
238            Expr::Table(expr) => expr.get_comments(),
239            Expr::BinExpr(expr) => expr.get_comments(),
240            Expr::UnExpr(expr) => expr.get_comments(),
241            Expr::SuffixedExpr(expr) => expr.get_comments(),
242        }
243    }
244}
245
246#[derive(PartialEq, Clone, Debug)]
247pub enum Assignable {
248    Name(StringExpr),
249    SuffixedExpr(SuffixedExpr),
250}
251
252impl Assignable {
253    pub fn unwrap_as_name(&self) -> &StringExpr {
254        match &self {
255            Assignable::Name(name) => name,
256            _ => unreachable!(),
257        }
258    }
259    pub fn unwrap_as_suffix(&self) -> &SuffixedExpr {
260        match &self {
261            Assignable::SuffixedExpr(suffix) => suffix,
262            _ => unreachable!(),
263        }
264    }
265}
266
267impl Comments for Assignable {
268    fn get_comments(&self) -> Vec<&str> {
269        match &self {
270            Assignable::Name(name) => name.get_comments(),
271            Assignable::SuffixedExpr(suffix) => suffix.get_comments(),
272        }
273    }
274}
275
276#[derive(PartialEq, Clone, Debug)]
277pub struct FloatExpr {
278    pub token: Token,
279}
280
281impl FloatExpr {
282    pub fn value(&self) -> FloatType {
283        self.token.get_float()
284    }
285}
286
287impl Comments for FloatExpr {
288    fn get_comments(&self) -> Vec<&str> {
289        self.token.get_comments()
290    }
291}
292
293#[derive(PartialEq, Clone, Debug)]
294pub struct IntExpr {
295    pub token: Token,
296}
297
298impl IntExpr {
299    pub fn value(&self) -> IntType {
300        self.token.get_int()
301    }
302}
303
304impl Comments for IntExpr {
305    fn get_comments(&self) -> Vec<&str> {
306        self.token.get_comments()
307    }
308}
309
310#[derive(PartialEq, Clone, Debug)]
311pub struct StringExpr {
312    pub token: Token,
313}
314
315impl StringExpr {
316    pub fn value(&self) -> String {
317        self.token.get_string()
318    }
319}
320
321impl Comments for StringExpr {
322    fn get_comments(&self) -> Vec<&str> {
323        self.token.get_comments()
324    }
325}
326
327#[derive(PartialEq, Clone, Debug)]
328pub struct SuffixedExpr {
329    pub primary: Box<Expr>,
330    pub suffixes: Vec<Suffix>,
331}
332
333impl Comments for SuffixedExpr {
334    fn get_comments(&self) -> Vec<&str> {
335        self.primary.get_comments()
336    }
337}
338
339#[derive(Clone, PartialEq, Debug)]
340pub enum Suffix {
341    // '.' NAME
342    Attr(Token, StringExpr),
343    // '[' expr ']'
344    Index(Token, Expr, Token),
345    // ':' NAME
346    Method(Token, StringExpr),
347    FuncArgs(FuncArgs),
348}
349
350impl Suffix {
351    pub fn unwrap_as_func_args(&self) -> &FuncArgs {
352        match &self {
353            Suffix::FuncArgs(args) => args,
354            _ => unreachable!(),
355        }
356    }
357}
358
359impl Comments for Suffix {
360    fn get_comments(&self) -> Vec<&str> {
361        match &self {
362            Suffix::Attr(token, _) => token.get_comments(),
363            Suffix::Index(token, _, _) => token.get_comments(),
364            Suffix::Method(token, _) => token.get_comments(),
365            Suffix::FuncArgs(args) => args.get_comments(),
366        }
367    }
368}
369
370#[derive(Clone, PartialEq, Debug)]
371pub enum FuncArgs {
372    // '(' [ exprlist ] ')'
373    Exprs(Token, ExprList, Token),
374    Table(Table),
375    String(StringExpr),
376}
377
378impl Comments for FuncArgs {
379    fn get_comments(&self) -> Vec<&str> {
380        match &self {
381            FuncArgs::Exprs(token, _, _) => token.get_comments(),
382            FuncArgs::Table(table) => table.get_comments(),
383            FuncArgs::String(string) => string.get_comments(),
384        }
385    }
386}
387
388#[derive(Default, Clone, PartialEq, Debug)]
389pub struct ExprList {
390    pub exprs: Vec<Expr>,
391    pub commas: Vec<Token>,
392}
393
394impl Comments for ExprList {
395    fn get_comments(&self) -> Vec<&str> {
396        if let Some(expr) = self.exprs.first() {
397            expr.get_comments()
398        } else {
399            Vec::new()
400        }
401    }
402    fn has_comments(&self) -> bool {
403        self.exprs.iter().any(|expr| expr.has_comments())
404    }
405}
406
407#[derive(Clone, PartialEq, Debug)]
408pub struct Table {
409    pub lb: Token,
410    pub fields: Vec<Field>,
411    pub rb: Token,
412}
413
414impl Comments for Table {
415    fn get_comments(&self) -> Vec<&str> {
416        self.lb.get_comments()
417    }
418}
419
420#[derive(Clone, PartialEq, Debug)]
421pub enum Field {
422    RecField(RecField),
423    ListField(ListField),
424}
425
426impl Field {
427    pub fn unwrap_as_list_field(&self) -> &ListField {
428        match &self {
429            Field::ListField(field) => field,
430            _ => unreachable!(),
431        }
432    }
433    pub fn unwrap_as_rec_field(&self) -> &RecField {
434        match &self {
435            Field::RecField(field) => field,
436            _ => unreachable!(),
437        }
438    }
439}
440
441impl Comments for Field {
442    fn get_comments(&self) -> Vec<&str> {
443        match &self {
444            Field::RecField(field) => field.get_comments(),
445            Field::ListField(field) => field.get_comments(),
446        }
447    }
448}
449
450#[derive(Clone, PartialEq, Debug)]
451pub struct RecField {
452    pub key: FieldKey,
453    pub equal: Token,
454    pub value: Expr,
455    pub sep: Option<Token>,
456}
457
458impl Comments for RecField {
459    fn get_comments(&self) -> Vec<&str> {
460        self.key.get_comments()
461    }
462}
463
464#[derive(Clone, PartialEq, Debug)]
465pub struct ListField {
466    pub value: Expr,
467    pub sep: Option<Token>,
468}
469
470impl Comments for ListField {
471    fn get_comments(&self) -> Vec<&str> {
472        self.value.get_comments()
473    }
474}
475
476#[derive(Clone, PartialEq, Debug)]
477pub enum FieldKey {
478    Name(StringExpr),
479    // '[' expr ']'
480    Expr(Token, Expr, Token),
481}
482
483impl FieldKey {
484    pub fn unwrap_as_name(&self) -> &StringExpr {
485        match &self {
486            FieldKey::Name(name) => name,
487            _ => unreachable!(),
488        }
489    }
490    pub fn unwrap_as_expr(&self) -> &Expr {
491        match &self {
492            FieldKey::Expr(_, expr, _) => expr,
493            _ => unreachable!(),
494        }
495    }
496}
497
498impl Comments for FieldKey {
499    fn get_comments(&self) -> Vec<&str> {
500        match &self {
501            FieldKey::Name(name) => name.get_comments(),
502            FieldKey::Expr(token, ..) => token.get_comments(),
503        }
504    }
505}
506
507#[derive(Clone, PartialEq, Debug)]
508pub struct UnExpr {
509    pub op: UnOp,
510    pub expr: Box<Expr>,
511}
512
513impl Comments for UnExpr {
514    fn get_comments(&self) -> Vec<&str> {
515        self.op.get_comments()
516    }
517}
518
519#[derive(Clone, PartialEq, Debug)]
520pub struct BinExpr {
521    pub left: Box<Expr>,
522    pub op: BinOp,
523    pub right: Box<Expr>,
524}
525
526impl Comments for BinExpr {
527    fn get_comments(&self) -> Vec<&str> {
528        self.left.get_comments()
529    }
530}
531
532#[derive(Clone, PartialEq, Debug)]
533pub struct IfStat {
534    pub cond_blocks: Vec<CondBlock>,
535    pub else_: Option<Token>,
536    pub else_block: Option<Block>,
537    pub end: Token,
538}
539
540impl Comments for IfStat {
541    fn get_comments(&self) -> Vec<&str> {
542        if let Some(cond) = self.cond_blocks.first() {
543            cond.get_comments()
544        } else {
545            unreachable!("IfStat should have at least one cond block")
546        }
547    }
548}
549
550#[derive(Clone, PartialEq, Debug)]
551pub struct CondBlock {
552    pub if_: Token,
553    pub cond: Expr,
554    pub then: Token,
555    pub block: Block,
556}
557
558impl Comments for CondBlock {
559    fn get_comments(&self) -> Vec<&str> {
560        self.if_.get_comments()
561    }
562}
563
564#[derive(Clone, PartialEq, Debug)]
565pub struct WhileStat {
566    pub while_: Token,
567    pub cond: Expr,
568    pub do_: Token,
569    pub block: Block,
570    pub end: Token,
571}
572
573impl Comments for WhileStat {
574    fn get_comments(&self) -> Vec<&str> {
575        self.while_.get_comments()
576    }
577}
578
579#[derive(Clone, PartialEq, Debug)]
580pub struct DoBlock {
581    pub do_: Token,
582    pub block: Block,
583    pub end: Token,
584}
585
586impl Comments for DoBlock {
587    fn get_comments(&self) -> Vec<&str> {
588        self.do_.get_comments()
589    }
590}
591
592#[derive(Clone, PartialEq, Debug)]
593pub enum ForStat {
594    ForNum(ForNum),
595    ForList(ForList),
596}
597
598impl Comments for ForStat {
599    fn get_comments(&self) -> Vec<&str> {
600        match &self {
601            ForStat::ForNum(stat) => stat.get_comments(),
602            ForStat::ForList(stat) => stat.get_comments(),
603        }
604    }
605}
606
607#[derive(Clone, PartialEq, Debug)]
608pub struct ForNum {
609    pub for_: Token,
610    pub var: StringExpr,
611    pub equal: Token,
612    pub init: Expr,
613    pub init_comma: Token,
614    pub limit: Expr,
615    pub limit_comma: Option<Token>,
616    pub step: Option<Expr>,
617    pub do_: Token,
618    pub body: Block,
619    pub end: Token,
620}
621
622impl Comments for ForNum {
623    fn get_comments(&self) -> Vec<&str> {
624        self.for_.get_comments()
625    }
626}
627
628#[derive(Clone, PartialEq, Debug)]
629pub struct ForList {
630    pub for_: Token,
631    pub vars: VarList,
632    pub in_: Token,
633    pub exprs: ExprList,
634    pub do_: Token,
635    pub body: Block,
636    pub end: Token,
637}
638
639impl Comments for ForList {
640    fn get_comments(&self) -> Vec<&str> {
641        self.for_.get_comments()
642    }
643}
644
645#[derive(Clone, PartialEq, Debug)]
646pub struct VarList {
647    pub vars: Vec<StringExpr>,
648    pub delimiters: Vec<Token>,
649}
650
651impl Comments for VarList {
652    fn get_comments(&self) -> Vec<&str> {
653        if let Some(var) = self.vars.first() {
654            var.get_comments()
655        } else {
656            unreachable!("VarList should have at least one var")
657        }
658    }
659}
660
661#[derive(Clone, PartialEq, Debug)]
662pub struct RepeatStat {
663    pub repeat: Token,
664    pub block: Block,
665    pub until: Token,
666    pub cond: Expr,
667}
668
669impl Comments for RepeatStat {
670    fn get_comments(&self) -> Vec<&str> {
671        self.repeat.get_comments()
672    }
673}
674
675#[derive(Clone, PartialEq, Debug)]
676pub enum FuncType {
677    Global,
678    Local(Token),
679}
680
681#[derive(Clone, PartialEq, Debug)]
682pub struct FuncStat {
683    pub func_type: FuncType,
684    pub function: Token,
685    pub func_name: FuncName,
686    pub body: FuncBody,
687}
688
689impl Comments for FuncStat {
690    fn get_comments(&self) -> Vec<&str> {
691        match &self.func_type {
692            FuncType::Global => self.function.get_comments(),
693            FuncType::Local(token) => token.get_comments(),
694        }
695    }
696}
697
698#[derive(Clone, PartialEq, Debug)]
699pub struct FuncName {
700    // NAME {'.' NAME}
701    pub fields: VarList,
702    // [':' NAME]
703    pub method: Option<(Token, StringExpr)>,
704}
705
706impl Comments for FuncName {
707    fn get_comments(&self) -> Vec<&str> {
708        if let Some(field) = self.fields.vars.first() {
709            field.get_comments()
710        } else {
711            unreachable!("FuncName should have at least one field")
712        }
713    }
714}
715
716#[derive(Clone, PartialEq, Debug)]
717pub struct FuncBody {
718    pub lp: Token,
719    pub params: ParamList,
720    pub rp: Token,
721    pub block: Block,
722    pub end: Token,
723}
724
725impl Comments for FuncBody {
726    fn get_comments(&self) -> Vec<&str> {
727        self.lp.get_comments()
728    }
729}
730
731#[derive(Clone, PartialEq, Debug)]
732pub struct ParamList {
733    pub params: Vec<Param>,
734    pub commas: Vec<Token>,
735}
736
737#[derive(Clone, PartialEq, Debug)]
738pub enum Param {
739    VarArg(Token),
740    Name(StringExpr),
741}
742
743impl Param {
744    pub fn unwrap_as_name(&self) -> String {
745        match self {
746            Param::Name(expr) => expr.value(),
747            _ => unreachable!(),
748        }
749    }
750}
751
752impl Comments for Param {
753    fn get_comments(&self) -> Vec<&str> {
754        match &self {
755            Param::VarArg(token) => token.get_comments(),
756            Param::Name(expr) => expr.get_comments(),
757        }
758    }
759}
760
761#[derive(Clone, PartialEq, Debug)]
762pub struct LocalStat {
763    pub local: Token,
764    pub names: VarList,
765    pub equal: Option<Token>,
766    pub exprs: Option<ExprList>,
767}
768
769impl Comments for LocalStat {
770    fn get_comments(&self) -> Vec<&str> {
771        self.local.get_comments()
772    }
773}
774
775#[derive(Clone, PartialEq, Debug)]
776pub struct LabelStat {
777    pub ldc: Token,
778    pub label: StringExpr,
779    pub rdc: Token,
780}
781
782impl Comments for LabelStat {
783    fn get_comments(&self) -> Vec<&str> {
784        self.ldc.get_comments()
785    }
786}
787
788#[derive(Clone, PartialEq, Debug)]
789pub struct RetStat {
790    pub return_: Token,
791    pub exprs: Option<ExprList>,
792    pub semi: Option<Token>,
793}
794
795impl Comments for RetStat {
796    fn get_comments(&self) -> Vec<&str> {
797        self.return_.get_comments()
798    }
799}
800
801#[derive(Clone, PartialEq, Debug)]
802pub struct BreakStat {
803    pub token: Token,
804}
805
806impl Comments for BreakStat {
807    fn get_comments(&self) -> Vec<&str> {
808        self.token.get_comments()
809    }
810}
811
812#[derive(Clone, PartialEq, Debug)]
813pub struct GotoStat {
814    pub goto: Token,
815    pub label: StringExpr,
816}
817
818impl Comments for GotoStat {
819    fn get_comments(&self) -> Vec<&str> {
820        self.goto.get_comments()
821    }
822}
823
824#[derive(Clone, PartialEq, Debug)]
825pub struct AssignStat {
826    pub left: AssignableList,
827    pub equal: Token,
828    pub right: ExprList,
829}
830
831impl Comments for AssignStat {
832    fn get_comments(&self) -> Vec<&str> {
833        if let Some(assignable) = self.left.assignables.first() {
834            assignable.get_comments()
835        } else {
836            unreachable!("AssignStat should have at least one assignable")
837        }
838    }
839}
840
841#[derive(Clone, PartialEq, Debug)]
842pub struct AssignableList {
843    pub assignables: Vec<Assignable>,
844    pub commas: Vec<Token>,
845}
846
847#[derive(Clone, PartialEq, Debug)]
848pub struct CallStat {
849    pub call: Assignable,
850}
851
852impl Comments for CallStat {
853    fn get_comments(&self) -> Vec<&str> {
854        self.call.get_comments()
855    }
856}
857
858#[derive(Clone, PartialEq, Debug)]
859pub enum Stat {
860    IfStat(IfStat),
861    WhileStat(WhileStat),
862    DoBlock(DoBlock),
863    ForStat(ForStat),
864    RepeatStat(RepeatStat),
865    FuncStat(FuncStat),
866    LocalStat(LocalStat),
867    LabelStat(LabelStat),
868    RetStat(RetStat),
869    BreakStat(BreakStat),
870    GotoStat(GotoStat),
871    AssignStat(AssignStat),
872    CallStat(CallStat),
873}
874
875impl Comments for Stat {
876    fn get_comments(&self) -> Vec<&str> {
877        match self {
878            Stat::IfStat(stat) => stat.get_comments(),
879            Stat::WhileStat(stat) => stat.get_comments(),
880            Stat::DoBlock(stat) => stat.get_comments(),
881            Stat::ForStat(stat) => stat.get_comments(),
882            Stat::RepeatStat(stat) => stat.get_comments(),
883            Stat::FuncStat(stat) => stat.get_comments(),
884            Stat::LocalStat(stat) => stat.get_comments(),
885            Stat::LabelStat(stat) => stat.get_comments(),
886            Stat::RetStat(stat) => stat.get_comments(),
887            Stat::BreakStat(stat) => stat.get_comments(),
888            Stat::GotoStat(stat) => stat.get_comments(),
889            Stat::AssignStat(stat) => stat.get_comments(),
890            Stat::CallStat(stat) => stat.get_comments(),
891        }
892    }
893}
894
895#[derive(Clone, PartialEq, Debug)]
896pub struct Block {
897    pub stats: Vec<Stat>,
898}
899
900impl Comments for Block {
901    fn get_comments(&self) -> Vec<&str> {
902        if let Some(stat) = self.stats.first() {
903            stat.get_comments()
904        } else {
905            Vec::new()
906        }
907    }
908}