Skip to content

Commit 11926dc

Browse files
committed
Lex, parse, and scaffold the evaluation of metadata variables.
1 parent 5dd1927 commit 11926dc

File tree

1 file changed

+48
-8
lines changed

1 file changed

+48
-8
lines changed

esi/src/expression.rs

+48-8
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,16 @@ impl EvalContext<'_> {
3232
pub fn new(variables: &Variables) -> EvalContext {
3333
EvalContext { variables }
3434
}
35+
pub fn get_metadata(&self, _key: &str) -> Value {
36+
Value::Null
37+
}
3538
}
3639

3740
fn eval_expr(expr: Expr, ctx: &EvalContext) -> Result<Value> {
3841
let result = match expr {
3942
Expr::Integer(i) => Value::Integer(i),
4043
Expr::String(s) => Value::String(s),
44+
Expr::MetaVariable(s) => ctx.get_metadata(&s).clone(),
4145
Expr::Variable(s) => ctx.variables.get(&s).clone(),
4246
Expr::Comparison(c) => {
4347
let left = eval_expr(c.left, ctx)?;
@@ -149,6 +153,7 @@ fn call_dispatch(identifier: String, args: Vec<Value>) -> Result<Value> {
149153
enum Expr {
150154
Integer(i64),
151155
String(String),
156+
MetaVariable(String),
152157
Variable(String),
153158
Comparison(Box<Comparison>),
154159
Call(String, Vec<Expr>),
@@ -178,6 +183,7 @@ fn parse_expr(cur: &mut Peekable<Iter<Token>>) -> Result<Expr> {
178183
Token::Integer(i) => Expr::Integer(*i),
179184
Token::String(s) => Expr::String(s.clone()),
180185
Token::Variable(s) => Expr::Variable(s.clone()),
186+
Token::MetaVariable(s) => Expr::MetaVariable(s.clone()),
181187
Token::Identifier(s) => parse_call(s.clone(), cur)?,
182188
_ => {
183189
return Err(ExecutionError::ExpressionParseError(
@@ -265,6 +271,7 @@ enum Token {
265271
Integer(i64),
266272
String(String),
267273
Variable(String),
274+
MetaVariable(String),
268275
Operator(Operator),
269276
Identifier(String),
270277
OpenParen,
@@ -296,15 +303,11 @@ fn lex_expr(expr: String) -> Result<Vec<Token>> {
296303
match pc {
297304
'(' => {
298305
cur.next();
299-
result.push(get_variable(&mut cur));
306+
result.push(get_variable(&mut cur)?);
300307
}
301308
'a'..='z' => {
302309
result.push(get_identifier(&mut cur));
303310
}
304-
'A'..='Z' => {
305-
// TODO: metadata identifier
306-
return Err(ExecutionError::ExpressionParseError(expr));
307-
}
308311
_ => return Err(ExecutionError::ExpressionParseError(expr)),
309312
}
310313
}
@@ -496,16 +499,40 @@ fn get_string(cur: &mut Peekable<Chars>) -> Result<Token> {
496499
Ok(Token::String(buf.into_iter().collect()))
497500
}
498501

499-
fn get_variable(cur: &mut Peekable<Chars>) -> Token {
502+
fn get_variable(cur: &mut Peekable<Chars>) -> Result<Token> {
500503
let mut buf = Vec::new();
504+
let mut is_meta_variable = false;
505+
506+
if let Some(c) = cur.next() {
507+
match c {
508+
'a'..='z' => buf.push(c),
509+
'A'..='Z' => {
510+
is_meta_variable = true;
511+
buf.push(c);
512+
}
513+
_ => {
514+
return Err(ExecutionError::ExpressionParseError(
515+
"unexpected character while parsing variable".to_string(),
516+
))
517+
}
518+
}
519+
} else {
520+
return Err(ExecutionError::ExpressionParseError(
521+
"unexpected eof while parsing variable".to_string(),
522+
));
523+
}
501524

502525
while let Some(c) = cur.next() {
503526
match c {
504527
')' => break,
505528
_ => buf.push(c),
506529
}
507530
}
508-
Token::Variable(buf.into_iter().collect())
531+
if is_meta_variable {
532+
Ok(Token::MetaVariable(buf.into_iter().collect()))
533+
} else {
534+
Ok(Token::Variable(buf.into_iter().collect()))
535+
}
509536
}
510537

511538
#[cfg(test)]
@@ -570,6 +597,12 @@ mod tests {
570597
Ok(())
571598
}
572599
#[test]
600+
fn test_lex_meta_variable() -> Result<()> {
601+
let tokens = lex_expr("$(HELLO)".to_string())?;
602+
assert_eq!(tokens, vec![Token::MetaVariable("HELLO".to_string())]);
603+
Ok(())
604+
}
605+
#[test]
573606
fn test_lex_matches_operator() -> Result<()> {
574607
let tokens = lex_expr("matches".to_string())?;
575608
assert_eq!(tokens, vec![Token::Operator(Operator::Matches)]);
@@ -665,14 +698,21 @@ mod tests {
665698
assert_eq!(expr, Expr::String("hello".to_string()));
666699
Ok(())
667700
}
668-
669701
#[test]
670702
fn test_parse_variable() -> Result<()> {
671703
let tokens = lex_expr("$(hello)".to_string())?;
672704
let expr = parse(tokens)?;
673705
assert_eq!(expr, Expr::Variable("hello".to_string()));
674706
Ok(())
675707
}
708+
709+
#[test]
710+
fn test_parse_meta_variable() -> Result<()> {
711+
let tokens = lex_expr("$(HELLO)".to_string())?;
712+
let expr = parse(tokens)?;
713+
assert_eq!(expr, Expr::MetaVariable("HELLO".to_string()));
714+
Ok(())
715+
}
676716
#[test]
677717
fn test_parse_comparison() -> Result<()> {
678718
let tokens = lex_expr("$(foo) matches 'bar'".to_string())?;

0 commit comments

Comments
 (0)