rslua/
ast_walker.rs

1use rslua_traits::Comments;
2
3use crate::ast::*;
4use crate::types::Source;
5
6// if visitor return `Ok(true)`, walker will not travel its children
7// if visitor return `Ok(false)`, walker will travel its children recursively.
8// if visitor return `Err(E)`, walker will stop traveling.
9pub trait AstVisitor<E = ()> {
10    fn stat_sep(&mut self) {}
11
12    fn begin_if(&mut self, _cond: &Expr) -> Result<bool, E> {
13        Ok(false)
14    }
15    fn then(&mut self, _block: &Block) -> Result<bool, E> {
16        Ok(false)
17    }
18    fn begin_else_if(&mut self, _cond: &Expr) -> Result<bool, E> {
19        Ok(false)
20    }
21    fn begin_else(&mut self, _block: &Block) -> Result<bool, E> {
22        Ok(false)
23    }
24    fn end_if(&mut self) {}
25
26    fn begin_while(&mut self, _cond: &Expr) -> Result<bool, E> {
27        Ok(false)
28    }
29    fn begin_while_block(&mut self, _block: &Block) -> Result<bool, E> {
30        Ok(false)
31    }
32    fn end_while(&mut self) {}
33
34    fn begin_do_block(&mut self, _block: &Block) -> Result<bool, E> {
35        Ok(false)
36    }
37    fn end_do_block(&mut self) {}
38
39    fn begin_for_num(&mut self, _for_enum: &ForNum) -> Result<bool, E> {
40        Ok(false)
41    }
42    fn for_enum_equal(&mut self) {}
43
44    fn begin_for_list(&mut self, _forlist: &ForList) -> Result<bool, E> {
45        Ok(false)
46    }
47
48    fn for_list_in(&mut self) {}
49
50    fn begin_for_block(&mut self, _block: &Block) -> Result<bool, E> {
51        Ok(false)
52    }
53    fn end_for(&mut self) {}
54
55    fn begin_repeat(&mut self, _block: &Block) -> Result<bool, E> {
56        Ok(false)
57    }
58    fn until(&mut self) {}
59    fn end_repeat(&mut self) {}
60
61    fn func(&mut self, _funcstat: &FuncStat) {}
62
63    fn local_stat(&mut self, _stat: &LocalStat) -> Result<(), E> {
64        Ok(())
65    }
66    fn label_stat(&mut self, _stat: &LabelStat) -> Result<(), E> {
67        Ok(())
68    }
69    fn ret_stat(&mut self, _stat: &RetStat) -> Result<(), E> {
70        Ok(())
71    }
72    fn break_stat(&mut self, _stat: &BreakStat) -> Result<(), E> {
73        Ok(())
74    }
75    fn goto_stat(&mut self, _stat: &GotoStat) -> Result<(), E> {
76        Ok(())
77    }
78    fn assign_stat(&mut self, _stat: &AssignStat) -> Result<(), E> {
79        Ok(())
80    }
81    fn call_stat(&mut self, _stat: &CallStat) -> Result<(), E> {
82        Ok(())
83    }
84
85    fn exprlist(&mut self, _stat: &ExprList) -> Result<(), E> {
86        Ok(())
87    }
88
89    fn expr(&mut self, _stat: &Expr) -> Result<bool, E> {
90        Ok(false)
91    }
92    fn expr_sep(&mut self) {}
93
94    fn nil(&mut self) {}
95    fn true_(&mut self) {}
96    fn false_(&mut self) {}
97    fn float(&mut self, _f: &FloatExpr) {}
98    fn int(&mut self, _i: &IntExpr) {}
99    fn string(&mut self, _s: &StringExpr) {}
100    fn vararg(&mut self) {}
101
102    fn anonymous_func(&mut self) {}
103    fn begin_func_body(&mut self, _body: &FuncBody) -> Result<bool, E> {
104        Ok(false)
105    }
106    fn end_func_body(&mut self) {}
107
108    fn begin_table(&mut self, _t: &Table) -> Result<bool, E> {
109        Ok(false)
110    }
111    fn end_table(&mut self, _t: &Table) {}
112
113    fn field_sep(&mut self) {}
114
115    fn begin_rec_field(&mut self, _field: &RecField) -> Result<bool, E> {
116        Ok(false)
117    }
118    fn field_kv_sep(&mut self) {}
119    fn begin_field_key(&mut self, _key: &FieldKey) -> Result<bool, E> {
120        Ok(false)
121    }
122    fn end_field_key(&mut self, _key: &FieldKey) {}
123    fn end_rec_field(&mut self) {}
124
125    fn begin_bin_expr(&mut self, _expr: &BinExpr) -> Result<bool, E> {
126        Ok(false)
127    }
128    fn binop(&mut self, _op: &BinOp) {}
129    fn end_bin_expr(&mut self) {}
130
131    fn begin_un_expr(&mut self, _expr: &UnExpr) -> Result<bool, E> {
132        Ok(false)
133    }
134    fn unop(&mut self, _op: &UnOp) {}
135    fn end_un_expr(&mut self) {}
136
137    fn begin_suffixed_expr(&mut self, _expr: &SuffixedExpr) -> Result<bool, E> {
138        Ok(false)
139    }
140    fn end_suffixed_expr(&mut self) {}
141
142    fn name(&mut self, _name: &StringExpr) {}
143    fn attr(&mut self, _attr: &StringExpr) {}
144    fn method(&mut self, _method: &StringExpr) {}
145
146    fn begin_index(&mut self, _expr: &Expr) -> Result<bool, E> {
147        Ok(false)
148    }
149    fn end_index(&mut self) {}
150
151    fn begin_func_args(&mut self, _args: &FuncArgs) -> Result<bool, E> {
152        Ok(false)
153    }
154    fn end_func_args(&mut self) {}
155
156    fn begin_paren_expr(&mut self, _expr: &Expr) -> Result<bool, E> {
157        Ok(false)
158    }
159    fn end_paren_expr(&mut self) {}
160
161    fn suffix(&mut self, _suf: &Suffix) -> Result<bool, E> {
162        Ok(false)
163    }
164
165    fn error(&mut self, e: E, _source: &Source) -> Result<(), E> {
166        Err(e)
167    }
168
169    fn comments(&mut self, _comments: &impl Comments) {}
170}
171
172pub fn walk_block<T: AstVisitor<E>, E>(block: &Block, visitor: &mut T) -> Result<(), E> {
173    for stat in block.stats.iter() {
174        if let Err(e) = walk_stat(stat, visitor) {
175            return visitor.error(
176                e,
177                &Source {
178                    line: 0,
179                    col: 0,
180                    length: 0,
181                },
182            );
183        }
184        visitor.stat_sep();
185    }
186    Ok(())
187}
188
189pub fn walk_stat<T: AstVisitor<E>, E>(stat: &Stat, visitor: &mut T) -> Result<(), E> {
190    visitor.comments(stat);
191    match stat {
192        Stat::IfStat(ifstat) => walk_ifstat(ifstat, visitor),
193        Stat::WhileStat(whilestat) => walk_whilestat(whilestat, visitor),
194        Stat::DoBlock(doblock) => walk_doblockstat(doblock, visitor),
195        Stat::ForStat(forstat) => walk_forstat(forstat, visitor),
196        Stat::RepeatStat(repeatstat) => walk_repeatstat(repeatstat, visitor),
197        Stat::FuncStat(funcstat) => walk_funcstat(funcstat, visitor),
198        Stat::LocalStat(localstat) => walk_localstat(localstat, visitor),
199        Stat::LabelStat(labelstat) => walk_labelstat(labelstat, visitor),
200        Stat::RetStat(retstat) => walk_retstat(retstat, visitor),
201        Stat::BreakStat(breakstat) => walk_breakstat(breakstat, visitor),
202        Stat::GotoStat(gotostat) => walk_gotostat(gotostat, visitor),
203        Stat::AssignStat(assignstat) => walk_assignstat(assignstat, visitor),
204        Stat::CallStat(callstat) => walk_callstat(callstat, visitor),
205    }
206}
207
208pub fn walk_ifstat<T: AstVisitor<E>, E>(stat: &IfStat, visitor: &mut T) -> Result<(), E> {
209    let mut if_blocks = stat.cond_blocks.iter();
210    if let Some(if_block) = if_blocks.next() {
211        if !visitor.begin_if(&if_block.cond)? {
212            walk_expr(&if_block.cond, visitor)?;
213        }
214        visitor.comments(&if_block.then);
215        if !visitor.then(&if_block.block)? {
216            walk_block(&if_block.block, visitor)?;
217        }
218        for else_if_block in if_blocks {
219            if !visitor.begin_else_if(&else_if_block.cond)? {
220                walk_expr(&else_if_block.cond, visitor)?;
221            }
222            visitor.comments(&else_if_block.then);
223            if !visitor.then(&else_if_block.block)? {
224                walk_block(&else_if_block.block, visitor)?;
225            }
226        }
227        if let Some(else_block) = &stat.else_block {
228            if !visitor.begin_else(else_block)? {
229                walk_block(else_block, visitor)?;
230            }
231        }
232        visitor.comments(&stat.end);
233        visitor.end_if();
234    }
235    Ok(())
236}
237
238pub fn walk_whilestat<T: AstVisitor<E>, E>(stat: &WhileStat, visitor: &mut T) -> Result<(), E> {
239    if !visitor.begin_while(&stat.cond)? {
240        walk_expr(&stat.cond, visitor)?;
241    }
242    visitor.comments(&stat.do_);
243    if !visitor.begin_while_block(&stat.block)? {
244        walk_block(&stat.block, visitor)?;
245    }
246    visitor.comments(&stat.end);
247    visitor.end_while();
248    Ok(())
249}
250
251pub fn walk_doblockstat<T: AstVisitor<E>, E>(stat: &DoBlock, visitor: &mut T) -> Result<(), E> {
252    if !visitor.begin_do_block(&stat.block)? {
253        walk_block(&stat.block, visitor)?;
254    }
255    visitor.comments(&stat.end);
256    visitor.end_do_block();
257    Ok(())
258}
259
260pub fn walk_forstat<T: AstVisitor<E>, E>(stat: &ForStat, visitor: &mut T) -> Result<(), E> {
261    match stat {
262        ForStat::ForNum(fornum) => walk_forenum(fornum, visitor),
263        ForStat::ForList(forlist) => walk_forlist(forlist, visitor),
264    }
265}
266
267pub fn walk_forenum<T: AstVisitor<E>, E>(stat: &ForNum, visitor: &mut T) -> Result<(), E> {
268    if !visitor.begin_for_num(stat)? {
269        visitor.name(&stat.var);
270        visitor.comments(&stat.equal);
271        visitor.for_enum_equal();
272        walk_expr(&stat.init, visitor)?;
273        visitor.comments(&stat.init_comma);
274        visitor.expr_sep();
275        walk_expr(&stat.limit, visitor)?;
276        if let Some(expr) = &stat.step {
277            visitor.comments(stat.limit_comma.as_ref().unwrap());
278            visitor.expr_sep();
279            walk_expr(expr, visitor)?;
280        }
281    }
282    visitor.comments(&stat.do_);
283    if !visitor.begin_for_block(&stat.body)? {
284        walk_block(&stat.body, visitor)?;
285    }
286    visitor.comments(&stat.end);
287    visitor.end_for();
288    Ok(())
289}
290
291pub fn walk_forlist<T: AstVisitor<E>, E>(stat: &ForList, visitor: &mut T) -> Result<(), E> {
292    if !visitor.begin_for_list(stat)? {
293        stat.vars.vars.iter().enumerate().for_each(|(i, var)| {
294            visitor.comments(var);
295            visitor.name(var);
296            if i != stat.vars.vars.len() - 1 {
297                visitor.comments(&stat.vars.delimiters[i]);
298                visitor.expr_sep();
299            }
300        });
301        visitor.comments(&stat.in_);
302        visitor.for_list_in();
303        visitor.exprlist(&stat.exprs)?;
304    }
305    visitor.comments(&stat.do_);
306    if !visitor.begin_for_block(&stat.body)? {
307        walk_block(&stat.body, visitor)?;
308    }
309    visitor.comments(&stat.end);
310    visitor.end_for();
311    Ok(())
312}
313
314pub fn walk_repeatstat<T: AstVisitor<E>, E>(stat: &RepeatStat, visitor: &mut T) -> Result<(), E> {
315    if !visitor.begin_repeat(&stat.block)? {
316        walk_block(&stat.block, visitor)?;
317        visitor.comments(&stat.until);
318        visitor.until();
319        walk_expr(&stat.cond, visitor)?;
320    }
321    visitor.end_repeat();
322    Ok(())
323}
324
325pub fn walk_funcstat<T: AstVisitor<E>, E>(stat: &FuncStat, visitor: &mut T) -> Result<(), E> {
326    visitor.func(stat);
327    walk_funcbody(&stat.body, visitor)
328}
329
330pub fn walk_localstat<T: AstVisitor<E>, E>(stat: &LocalStat, visitor: &mut T) -> Result<(), E> {
331    visitor.local_stat(stat)
332}
333
334pub fn walk_labelstat<T: AstVisitor<E>, E>(stat: &LabelStat, visitor: &mut T) -> Result<(), E> {
335    visitor.label_stat(stat)
336}
337
338pub fn walk_retstat<T: AstVisitor<E>, E>(stat: &RetStat, visitor: &mut T) -> Result<(), E> {
339    visitor.ret_stat(stat)
340}
341
342pub fn walk_breakstat<T: AstVisitor<E>, E>(stat: &BreakStat, visitor: &mut T) -> Result<(), E> {
343    visitor.break_stat(stat)
344}
345
346pub fn walk_gotostat<T: AstVisitor<E>, E>(stat: &GotoStat, visitor: &mut T) -> Result<(), E> {
347    visitor.goto_stat(stat)
348}
349
350pub fn walk_assignstat<T: AstVisitor<E>, E>(stat: &AssignStat, visitor: &mut T) -> Result<(), E> {
351    visitor.assign_stat(stat)
352}
353
354pub fn walk_callstat<T: AstVisitor<E>, E>(stat: &CallStat, visitor: &mut T) -> Result<(), E> {
355    visitor.call_stat(stat)
356}
357
358pub fn walk_expr<T: AstVisitor<E>, E>(expr: &Expr, visitor: &mut T) -> Result<(), E> {
359    visitor.comments(expr);
360    if !visitor.expr(expr)? {
361        match expr {
362            Expr::Nil(_) => visitor.nil(),
363            Expr::True(_) => visitor.true_(),
364            Expr::False(_) => visitor.false_(),
365            Expr::Float(f) => visitor.float(f),
366            Expr::Int(i) => visitor.int(i),
367            Expr::String(string) => visitor.string(string),
368            Expr::VarArg(_) => visitor.vararg(),
369            Expr::Name(s) => visitor.name(s),
370            Expr::ParenExpr(expr) => walk_parenexpr(expr, visitor)?,
371            Expr::FuncBody(body) => {
372                visitor.anonymous_func();
373                walk_funcbody(body, visitor)?
374            }
375            Expr::Table(t) => walk_table(t, visitor)?,
376            Expr::BinExpr(expr) => walk_binexpr(expr, visitor)?,
377            Expr::UnExpr(expr) => walk_unexpr(expr, visitor)?,
378            Expr::SuffixedExpr(expr) => walk_suffixedexpr(expr, visitor)?,
379        };
380    }
381    Ok(())
382}
383
384pub fn walk_funcbody<T: AstVisitor<E>, E>(body: &FuncBody, visitor: &mut T) -> Result<(), E> {
385    if !visitor.begin_func_body(body)? {
386        walk_block(&body.block, visitor)?;
387    }
388    visitor.comments(&body.end);
389    visitor.end_func_body();
390    Ok(())
391}
392
393pub fn walk_binexpr<T: AstVisitor<E>, E>(expr: &BinExpr, visitor: &mut T) -> Result<(), E> {
394    if !visitor.begin_bin_expr(expr)? {
395        walk_expr(&expr.left, visitor)?;
396        visitor.binop(&expr.op);
397        walk_expr(&expr.right, visitor)?;
398    }
399    visitor.end_bin_expr();
400    Ok(())
401}
402
403pub fn walk_unexpr<T: AstVisitor<E>, E>(expr: &UnExpr, visitor: &mut T) -> Result<(), E> {
404    if !visitor.begin_un_expr(expr)? {
405        visitor.unop(&expr.op);
406        walk_expr(&expr.expr, visitor)?;
407    }
408    visitor.end_un_expr();
409    Ok(())
410}
411
412pub fn walk_suffixedexpr<T: AstVisitor<E>, E>(
413    expr: &SuffixedExpr,
414    visitor: &mut T,
415) -> Result<(), E> {
416    if !visitor.begin_suffixed_expr(expr)? {
417        walk_expr(&expr.primary, visitor)?;
418        for suf in expr.suffixes.iter() {
419            if !visitor.suffix(suf)? {
420                match suf {
421                    Suffix::Attr(_, attr) => visitor.attr(attr),
422                    Suffix::Method(_, method) => visitor.method(method),
423                    Suffix::Index(_, index, _) => walk_index(index, visitor)?,
424                    Suffix::FuncArgs(args) => walk_funcargs(args, visitor)?,
425                }
426            }
427        }
428    }
429    visitor.end_suffixed_expr();
430    Ok(())
431}
432
433pub fn walk_assinable<T: AstVisitor<E>, E>(
434    assignable: &Assignable,
435    visitor: &mut T,
436) -> Result<(), E> {
437    match assignable {
438        Assignable::SuffixedExpr(s) => walk_suffixedexpr(s, visitor)?,
439        Assignable::Name(s) => visitor.name(s),
440    };
441    Ok(())
442}
443
444pub fn walk_index<T: AstVisitor<E>, E>(expr: &Expr, visitor: &mut T) -> Result<(), E> {
445    if !visitor.begin_index(expr)? {
446        walk_expr(expr, visitor)?;
447    }
448    visitor.end_index();
449    Ok(())
450}
451
452pub fn walk_funcargs<T: AstVisitor<E>, E>(args: &FuncArgs, visitor: &mut T) -> Result<(), E> {
453    if !visitor.begin_func_args(args)? {
454        match args {
455            FuncArgs::String(s) => visitor.string(s),
456            FuncArgs::Table(t) => walk_table(t, visitor)?,
457            FuncArgs::Exprs(_, exprs, rp) => {
458                visitor.exprlist(exprs)?;
459                visitor.comments(rp);
460            }
461        }
462    }
463    visitor.end_func_args();
464    Ok(())
465}
466
467pub fn walk_parenexpr<T: AstVisitor<E>, E>(expr: &Expr, visitor: &mut T) -> Result<(), E> {
468    if !visitor.begin_paren_expr(expr)? {
469        walk_expr(expr, visitor)?;
470    }
471    visitor.end_paren_expr();
472    Ok(())
473}
474
475pub fn walk_table<T: AstVisitor<E>, E>(table: &Table, visitor: &mut T) -> Result<(), E> {
476    if !visitor.begin_table(table)? {
477        walk_fields(&table.fields, visitor)?;
478    }
479    visitor.end_table(table);
480    Ok(())
481}
482
483pub fn walk_fields<T: AstVisitor<E>, E>(fields: &[Field], visitor: &mut T) -> Result<(), E> {
484    for field in fields.iter() {
485        walk_field(field, visitor)?;
486        visitor.field_sep();
487    }
488    Ok(())
489}
490
491pub fn walk_field<T: AstVisitor<E>, E>(field: &Field, visitor: &mut T) -> Result<(), E> {
492    match field {
493        Field::RecField(field) => walk_recfield(field, visitor),
494        Field::ListField(field) => walk_listfield(field, visitor),
495    }
496}
497
498pub fn walk_recfield<T: AstVisitor<E>, E>(field: &RecField, visitor: &mut T) -> Result<(), E> {
499    if !visitor.begin_rec_field(field)? {
500        walk_fieldkey(&field.key, visitor)?;
501        visitor.field_kv_sep();
502        walk_expr(&field.value, visitor)?;
503    }
504    visitor.end_rec_field();
505    Ok(())
506}
507
508pub fn walk_listfield<T: AstVisitor<E>, E>(field: &ListField, visitor: &mut T) -> Result<(), E> {
509    walk_expr(&field.value, visitor)?;
510    Ok(())
511}
512
513pub fn walk_fieldkey<T: AstVisitor<E>, E>(key: &FieldKey, visitor: &mut T) -> Result<(), E> {
514    if !visitor.begin_field_key(key)? {
515        match key {
516            FieldKey::Name(s) => visitor.name(s),
517            FieldKey::Expr(_, expr, _) => walk_expr(expr, visitor)?,
518        };
519    }
520    visitor.end_field_key(key);
521    Ok(())
522}