2017-11-16 23:30:08 -08:00
|
|
|
use common::*;
|
|
|
|
|
|
|
|
#[derive(PartialEq, Debug)]
|
|
|
|
pub enum Expression<'a> {
|
|
|
|
Backtick{raw: &'a str, token: Token<'a>},
|
2017-12-02 05:37:10 -08:00
|
|
|
Call{name: &'a str, token: Token<'a>},
|
2017-11-16 23:30:08 -08:00
|
|
|
Concatination{lhs: Box<Expression<'a>>, rhs: Box<Expression<'a>>},
|
2017-12-02 05:37:10 -08:00
|
|
|
String{cooked_string: CookedString<'a>},
|
|
|
|
Variable{name: &'a str, token: Token<'a>},
|
2017-11-16 23:30:08 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Expression<'a> {
|
|
|
|
pub fn variables(&'a self) -> Variables<'a> {
|
|
|
|
Variables {
|
|
|
|
stack: vec![self],
|
|
|
|
}
|
|
|
|
}
|
2017-12-02 05:37:10 -08:00
|
|
|
|
|
|
|
pub fn functions(&'a self) -> Functions<'a> {
|
|
|
|
Functions {
|
|
|
|
stack: vec![self],
|
|
|
|
}
|
|
|
|
}
|
2017-11-16 23:30:08 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Display for Expression<'a> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
|
|
|
match *self {
|
|
|
|
Expression::Backtick {raw, .. } => write!(f, "`{}`", raw)?,
|
2017-12-02 05:37:10 -08:00
|
|
|
Expression::Call {name, .. } => write!(f, "{}()", name)?,
|
2017-11-16 23:30:08 -08:00
|
|
|
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() {
|
2017-12-02 05:37:10 -08:00
|
|
|
None
|
|
|
|
| Some(&Expression::String{..})
|
|
|
|
| Some(&Expression::Backtick{..})
|
|
|
|
| Some(&Expression::Call{..}) => 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()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Functions<'a> {
|
|
|
|
stack: Vec<&'a Expression<'a>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Iterator for Functions<'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{..})
|
|
|
|
| Some(&Expression::Variable{..}) => None,
|
|
|
|
Some(&Expression::Call{ref token, ..}) => Some(token),
|
2017-11-16 23:30:08 -08:00
|
|
|
Some(&Expression::Concatination{ref lhs, ref rhs}) => {
|
|
|
|
self.stack.push(lhs);
|
|
|
|
self.stack.push(rhs);
|
|
|
|
self.next()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|