cas_parser/parser/
iter.rs1use super::ast::expr::Expr;
2
3pub struct ExprIter<'a> {
8 stack: Vec<&'a Expr>,
9 last_visited: Option<&'a Expr>,
10}
11
12impl<'a> ExprIter<'a> {
13 pub fn new(expr: &'a Expr) -> Self {
16 Self {
17 stack: vec![expr],
18 last_visited: None,
19 }
20 }
21
22 fn visit(&mut self) -> Option<&'a Expr> {
24 self.last_visited = Some(self.stack.pop()?);
25 self.last_visited
26 }
27
28 fn is_last_visited(&self, expr: &'a Expr) -> bool {
30 match self.last_visited {
31 Some(last_visited) => std::ptr::eq(last_visited, expr),
32 None => false,
33 }
34 }
35}
36
37impl<'a> Iterator for ExprIter<'a> {
38 type Item = &'a Expr;
39
40 fn next(&mut self) -> Option<Self::Item> {
41 loop {
42 let expr = self.stack.last()?;
43 match expr {
44 Expr::Literal(_) => return self.visit(),
45 Expr::Paren(paren) => {
46 if self.is_last_visited(&paren.expr) {
47 return self.visit();
48 }
49 self.stack.push(&paren.expr);
50 },
51 Expr::Block(_) => return self.visit(), Expr::If(if_expr) => {
53 if let Some(else_expr) = &if_expr.else_expr {
54 if self.is_last_visited(else_expr) {
55 return self.visit();
56 }
57 self.stack.push(else_expr);
58 self.stack.push(&if_expr.then_expr);
59 self.stack.push(&if_expr.condition);
60 } else {
61 if self.is_last_visited(&if_expr.then_expr) {
62 return self.visit();
63 }
64 self.stack.push(&if_expr.then_expr);
65 self.stack.push(&if_expr.condition);
66 }
67 },
68 Expr::Loop(loop_expr) => {
69 if self.is_last_visited(&loop_expr.body) {
70 return self.visit();
71 }
72 self.stack.push(&loop_expr.body);
73 },
74 Expr::While(while_expr) => {
75 if self.is_last_visited(&while_expr.body) {
76 return self.visit();
77 }
78 self.stack.push(&while_expr.body);
79 self.stack.push(&while_expr.condition);
80 },
81 Expr::Break(break_expr) => {
82 if let Some(value) = &break_expr.value {
83 if self.is_last_visited(value) {
84 return self.visit();
85 }
86 self.stack.push(value);
87 } else {
88 return self.visit();
89 }
90 },
91 Expr::Continue(_) => return self.visit(),
92 Expr::Call(call) => {
93 if call.args.is_empty() || self.is_last_visited(call.args.last().unwrap()) {
94 return self.visit();
95 }
96 for arg in call.args.iter().rev() {
97 self.stack.push(arg);
98 }
99 },
100 Expr::Unary(unary) => {
101 if self.is_last_visited(&unary.operand) {
102 return self.visit();
103 }
104 self.stack.push(&unary.operand);
105 },
106 Expr::Binary(binary) => {
107 if self.is_last_visited(&binary.rhs) {
108 return self.visit();
109 }
110 self.stack.push(&binary.rhs);
111 self.stack.push(&binary.lhs);
112 },
113 Expr::Assign(assign) => {
114 if self.is_last_visited(&assign.value) {
115 return self.visit();
116 }
117 self.stack.push(&assign.value);
118 },
119 }
120 }
121 }
122}