just/src/variables.rs
2024-05-14 20:07:41 -07:00

97 lines
2.5 KiB
Rust

use super::*;
pub(crate) struct Variables<'expression, 'src> {
stack: Vec<&'expression Expression<'src>>,
}
impl<'expression, 'src> Variables<'expression, 'src> {
pub(crate) fn new(root: &'expression Expression<'src>) -> Self {
Self { stack: vec![root] }
}
}
impl<'expression, 'src> Iterator for Variables<'expression, 'src> {
type Item = Token<'src>;
fn next(&mut self) -> Option<Token<'src>> {
loop {
match self.stack.pop()? {
Expression::StringLiteral { .. } | Expression::Backtick { .. } => {}
Expression::Call { thunk } => match thunk {
Thunk::Nullary { .. } => {}
Thunk::Unary { arg, .. } => self.stack.push(arg),
Thunk::UnaryOpt {
args: (a, opt_b), ..
} => {
self.stack.push(a);
if let Some(b) = opt_b.as_ref() {
self.stack.push(b);
}
}
Thunk::Binary { args, .. } => {
for arg in args.iter().rev() {
self.stack.push(arg);
}
}
Thunk::BinaryPlus {
args: ([a, b], rest),
..
} => {
let first: &[&Expression] = &[a, b];
for arg in first.iter().copied().chain(rest).rev() {
self.stack.push(arg);
}
}
Thunk::Ternary { args, .. } => {
for arg in args.iter().rev() {
self.stack.push(arg);
}
}
},
Expression::Conditional {
condition:
Condition {
lhs,
rhs,
operator: _,
},
then,
otherwise,
} => {
self.stack.push(otherwise);
self.stack.push(then);
self.stack.push(rhs);
self.stack.push(lhs);
}
Expression::Variable { name, .. } => return Some(name.token),
Expression::Concatenation { lhs, rhs } => {
self.stack.push(rhs);
self.stack.push(lhs);
}
Expression::Join { lhs, rhs } => {
self.stack.push(rhs);
if let Some(lhs) = lhs {
self.stack.push(lhs);
}
}
Expression::Group { contents } => {
self.stack.push(contents);
}
Expression::Assert {
condition:
Condition {
lhs,
rhs,
operator: _,
},
error,
} => {
self.stack.push(error);
self.stack.push(rhs);
self.stack.push(lhs);
}
}
}
}
}