Skip to content

Commit

Permalink
Lex, parse, and scaffold the evaluation of metadata variables.
Browse files Browse the repository at this point in the history
  • Loading branch information
tyler committed Dec 6, 2024
1 parent 5dd1927 commit 11926dc
Showing 1 changed file with 48 additions and 8 deletions.
56 changes: 48 additions & 8 deletions esi/src/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,16 @@ impl EvalContext<'_> {
pub fn new(variables: &Variables) -> EvalContext {
EvalContext { variables }
}
pub fn get_metadata(&self, _key: &str) -> Value {
Value::Null
}
}

fn eval_expr(expr: Expr, ctx: &EvalContext) -> Result<Value> {
let result = match expr {
Expr::Integer(i) => Value::Integer(i),
Expr::String(s) => Value::String(s),
Expr::MetaVariable(s) => ctx.get_metadata(&s).clone(),
Expr::Variable(s) => ctx.variables.get(&s).clone(),
Expr::Comparison(c) => {
let left = eval_expr(c.left, ctx)?;
Expand Down Expand Up @@ -149,6 +153,7 @@ fn call_dispatch(identifier: String, args: Vec<Value>) -> Result<Value> {
enum Expr {
Integer(i64),
String(String),
MetaVariable(String),
Variable(String),
Comparison(Box<Comparison>),
Call(String, Vec<Expr>),
Expand Down Expand Up @@ -178,6 +183,7 @@ fn parse_expr(cur: &mut Peekable<Iter<Token>>) -> Result<Expr> {
Token::Integer(i) => Expr::Integer(*i),
Token::String(s) => Expr::String(s.clone()),
Token::Variable(s) => Expr::Variable(s.clone()),
Token::MetaVariable(s) => Expr::MetaVariable(s.clone()),
Token::Identifier(s) => parse_call(s.clone(), cur)?,
_ => {
return Err(ExecutionError::ExpressionParseError(
Expand Down Expand Up @@ -265,6 +271,7 @@ enum Token {
Integer(i64),
String(String),
Variable(String),
MetaVariable(String),
Operator(Operator),
Identifier(String),
OpenParen,
Expand Down Expand Up @@ -296,15 +303,11 @@ fn lex_expr(expr: String) -> Result<Vec<Token>> {
match pc {
'(' => {
cur.next();
result.push(get_variable(&mut cur));
result.push(get_variable(&mut cur)?);
}
'a'..='z' => {
result.push(get_identifier(&mut cur));
}
'A'..='Z' => {
// TODO: metadata identifier
return Err(ExecutionError::ExpressionParseError(expr));
}
_ => return Err(ExecutionError::ExpressionParseError(expr)),
}
}
Expand Down Expand Up @@ -496,16 +499,40 @@ fn get_string(cur: &mut Peekable<Chars>) -> Result<Token> {
Ok(Token::String(buf.into_iter().collect()))
}

fn get_variable(cur: &mut Peekable<Chars>) -> Token {
fn get_variable(cur: &mut Peekable<Chars>) -> Result<Token> {
let mut buf = Vec::new();
let mut is_meta_variable = false;

if let Some(c) = cur.next() {
match c {
'a'..='z' => buf.push(c),
'A'..='Z' => {
is_meta_variable = true;
buf.push(c);
}
_ => {
return Err(ExecutionError::ExpressionParseError(
"unexpected character while parsing variable".to_string(),
))
}
}
} else {
return Err(ExecutionError::ExpressionParseError(
"unexpected eof while parsing variable".to_string(),
));
}

while let Some(c) = cur.next() {
match c {
')' => break,
_ => buf.push(c),
}
}
Token::Variable(buf.into_iter().collect())
if is_meta_variable {
Ok(Token::MetaVariable(buf.into_iter().collect()))
} else {
Ok(Token::Variable(buf.into_iter().collect()))
}
}

#[cfg(test)]
Expand Down Expand Up @@ -570,6 +597,12 @@ mod tests {
Ok(())
}
#[test]
fn test_lex_meta_variable() -> Result<()> {
let tokens = lex_expr("$(HELLO)".to_string())?;
assert_eq!(tokens, vec![Token::MetaVariable("HELLO".to_string())]);
Ok(())
}
#[test]
fn test_lex_matches_operator() -> Result<()> {
let tokens = lex_expr("matches".to_string())?;
assert_eq!(tokens, vec![Token::Operator(Operator::Matches)]);
Expand Down Expand Up @@ -665,14 +698,21 @@ mod tests {
assert_eq!(expr, Expr::String("hello".to_string()));
Ok(())
}

#[test]
fn test_parse_variable() -> Result<()> {
let tokens = lex_expr("$(hello)".to_string())?;
let expr = parse(tokens)?;
assert_eq!(expr, Expr::Variable("hello".to_string()));
Ok(())
}

#[test]
fn test_parse_meta_variable() -> Result<()> {
let tokens = lex_expr("$(HELLO)".to_string())?;
let expr = parse(tokens)?;
assert_eq!(expr, Expr::MetaVariable("HELLO".to_string()));
Ok(())
}
#[test]
fn test_parse_comparison() -> Result<()> {
let tokens = lex_expr("$(foo) matches 'bar'".to_string())?;
Expand Down

0 comments on commit 11926dc

Please sign in to comment.