just/src/expression.rs
2017-11-16 23:30:08 -08:00

50 lines
1.4 KiB
Rust

use common::*;
#[derive(PartialEq, Debug)]
pub enum Expression<'a> {
Variable{name: &'a str, token: Token<'a>},
String{cooked_string: CookedString<'a>},
Backtick{raw: &'a str, token: Token<'a>},
Concatination{lhs: Box<Expression<'a>>, rhs: Box<Expression<'a>>},
}
impl<'a> Expression<'a> {
pub fn variables(&'a self) -> Variables<'a> {
Variables {
stack: vec![self],
}
}
}
impl<'a> Display for Expression<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
Expression::Backtick {raw, .. } => write!(f, "`{}`", raw)?,
Expression::Concatination{ref lhs, ref rhs } => write!(f, "{} + {}", lhs, rhs)?,
Expression::String {ref cooked_string} => write!(f, "\"{}\"", cooked_string.raw)?,
Expression::Variable {name, .. } => write!(f, "{}", name)?,
}
Ok(())
}
}
pub struct Variables<'a> {
stack: Vec<&'a Expression<'a>>,
}
impl<'a> Iterator for Variables<'a> {
type Item = &'a Token<'a>;
fn next(&mut self) -> Option<&'a Token<'a>> {
match self.stack.pop() {
None | Some(&Expression::String{..}) | Some(&Expression::Backtick{..}) => None,
Some(&Expression::Variable{ref token,..}) => Some(token),
Some(&Expression::Concatination{ref lhs, ref rhs}) => {
self.stack.push(lhs);
self.stack.push(rhs);
self.next()
}
}
}
}