1use super::*;
2
3pub struct Variables<'expression, 'src> {
4 stack: Vec<&'expression Expression<'src>>,
5}
6
7impl<'expression, 'src> Variables<'expression, 'src> {
8 pub fn new(root: &'expression Expression<'src>) -> Self {
9 Self { stack: vec![root] }
10 }
11}
12
13impl<'expression, 'src> Iterator for Variables<'expression, 'src> {
14 type Item = Token<'src>;
15
16 fn next(&mut self) -> Option<Token<'src>> {
17 loop {
18 match self.stack.pop()? {
19 Expression::And { lhs, rhs } | Expression::Or { lhs, rhs } => {
20 self.stack.push(lhs);
21 self.stack.push(rhs);
22 }
23 Expression::Assert {
24 condition:
25 Condition {
26 lhs,
27 rhs,
28 operator: _,
29 },
30 error,
31 } => {
32 self.stack.push(error);
33 self.stack.push(rhs);
34 self.stack.push(lhs);
35 }
36 Expression::Backtick { .. } | Expression::StringLiteral { .. } => {}
37 Expression::Call { thunk } => match thunk {
38 Thunk::Nullary { .. } => {}
39 Thunk::Unary { arg, .. } => self.stack.push(arg),
40 Thunk::UnaryOpt {
41 args: (a, opt_b), ..
42 } => {
43 self.stack.push(a);
44 if let Some(b) = opt_b.as_ref() {
45 self.stack.push(b);
46 }
47 }
48 Thunk::UnaryPlus {
49 args: (a, rest), ..
50 } => {
51 let first: &[&Expression] = &[a];
52 for arg in first.iter().copied().chain(rest).rev() {
53 self.stack.push(arg);
54 }
55 }
56 Thunk::Binary { args, .. } => {
57 for arg in args.iter().rev() {
58 self.stack.push(arg);
59 }
60 }
61 Thunk::BinaryPlus {
62 args: ([a, b], rest),
63 ..
64 } => {
65 let first: &[&Expression] = &[a, b];
66 for arg in first.iter().copied().chain(rest).rev() {
67 self.stack.push(arg);
68 }
69 }
70 Thunk::Ternary { args, .. } => {
71 for arg in args.iter().rev() {
72 self.stack.push(arg);
73 }
74 }
75 },
76 Expression::Concatenation { lhs, rhs } => {
77 self.stack.push(rhs);
78 self.stack.push(lhs);
79 }
80 Expression::Conditional {
81 condition:
82 Condition {
83 lhs,
84 rhs,
85 operator: _,
86 },
87 then,
88 otherwise,
89 } => {
90 self.stack.push(otherwise);
91 self.stack.push(then);
92 self.stack.push(rhs);
93 self.stack.push(lhs);
94 }
95 Expression::Group { contents } => {
96 self.stack.push(contents);
97 }
98 Expression::Join { lhs, rhs } => {
99 self.stack.push(rhs);
100 if let Some(lhs) = lhs {
101 self.stack.push(lhs);
102 }
103 }
104 Expression::Variable { name, .. } => return Some(name.token),
105 }
106 }
107 }
108}