@@ -32,12 +32,16 @@ impl EvalContext<'_> {
32
32
pub fn new ( variables : & Variables ) -> EvalContext {
33
33
EvalContext { variables }
34
34
}
35
+ pub fn get_metadata ( & self , _key : & str ) -> Value {
36
+ Value :: Null
37
+ }
35
38
}
36
39
37
40
fn eval_expr ( expr : Expr , ctx : & EvalContext ) -> Result < Value > {
38
41
let result = match expr {
39
42
Expr :: Integer ( i) => Value :: Integer ( i) ,
40
43
Expr :: String ( s) => Value :: String ( s) ,
44
+ Expr :: MetaVariable ( s) => ctx. get_metadata ( & s) . clone ( ) ,
41
45
Expr :: Variable ( s) => ctx. variables . get ( & s) . clone ( ) ,
42
46
Expr :: Comparison ( c) => {
43
47
let left = eval_expr ( c. left , ctx) ?;
@@ -149,6 +153,7 @@ fn call_dispatch(identifier: String, args: Vec<Value>) -> Result<Value> {
149
153
enum Expr {
150
154
Integer ( i64 ) ,
151
155
String ( String ) ,
156
+ MetaVariable ( String ) ,
152
157
Variable ( String ) ,
153
158
Comparison ( Box < Comparison > ) ,
154
159
Call ( String , Vec < Expr > ) ,
@@ -178,6 +183,7 @@ fn parse_expr(cur: &mut Peekable<Iter<Token>>) -> Result<Expr> {
178
183
Token :: Integer ( i) => Expr :: Integer ( * i) ,
179
184
Token :: String ( s) => Expr :: String ( s. clone ( ) ) ,
180
185
Token :: Variable ( s) => Expr :: Variable ( s. clone ( ) ) ,
186
+ Token :: MetaVariable ( s) => Expr :: MetaVariable ( s. clone ( ) ) ,
181
187
Token :: Identifier ( s) => parse_call ( s. clone ( ) , cur) ?,
182
188
_ => {
183
189
return Err ( ExecutionError :: ExpressionParseError (
@@ -265,6 +271,7 @@ enum Token {
265
271
Integer ( i64 ) ,
266
272
String ( String ) ,
267
273
Variable ( String ) ,
274
+ MetaVariable ( String ) ,
268
275
Operator ( Operator ) ,
269
276
Identifier ( String ) ,
270
277
OpenParen ,
@@ -296,15 +303,11 @@ fn lex_expr(expr: String) -> Result<Vec<Token>> {
296
303
match pc {
297
304
'(' => {
298
305
cur. next ( ) ;
299
- result. push ( get_variable ( & mut cur) ) ;
306
+ result. push ( get_variable ( & mut cur) ? ) ;
300
307
}
301
308
'a' ..='z' => {
302
309
result. push ( get_identifier ( & mut cur) ) ;
303
310
}
304
- 'A' ..='Z' => {
305
- // TODO: metadata identifier
306
- return Err ( ExecutionError :: ExpressionParseError ( expr) ) ;
307
- }
308
311
_ => return Err ( ExecutionError :: ExpressionParseError ( expr) ) ,
309
312
}
310
313
}
@@ -496,16 +499,40 @@ fn get_string(cur: &mut Peekable<Chars>) -> Result<Token> {
496
499
Ok ( Token :: String ( buf. into_iter ( ) . collect ( ) ) )
497
500
}
498
501
499
- fn get_variable ( cur : & mut Peekable < Chars > ) -> Token {
502
+ fn get_variable ( cur : & mut Peekable < Chars > ) -> Result < Token > {
500
503
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
+ }
501
524
502
525
while let Some ( c) = cur. next ( ) {
503
526
match c {
504
527
')' => break ,
505
528
_ => buf. push ( c) ,
506
529
}
507
530
}
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
+ }
509
536
}
510
537
511
538
#[ cfg( test) ]
@@ -570,6 +597,12 @@ mod tests {
570
597
Ok ( ( ) )
571
598
}
572
599
#[ 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]
573
606
fn test_lex_matches_operator ( ) -> Result < ( ) > {
574
607
let tokens = lex_expr ( "matches" . to_string ( ) ) ?;
575
608
assert_eq ! ( tokens, vec![ Token :: Operator ( Operator :: Matches ) ] ) ;
@@ -665,14 +698,21 @@ mod tests {
665
698
assert_eq ! ( expr, Expr :: String ( "hello" . to_string( ) ) ) ;
666
699
Ok ( ( ) )
667
700
}
668
-
669
701
#[ test]
670
702
fn test_parse_variable ( ) -> Result < ( ) > {
671
703
let tokens = lex_expr ( "$(hello)" . to_string ( ) ) ?;
672
704
let expr = parse ( tokens) ?;
673
705
assert_eq ! ( expr, Expr :: Variable ( "hello" . to_string( ) ) ) ;
674
706
Ok ( ( ) )
675
707
}
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
+ }
676
716
#[ test]
677
717
fn test_parse_comparison ( ) -> Result < ( ) > {
678
718
let tokens = lex_expr ( "$(foo) matches 'bar'" . to_string ( ) ) ?;
0 commit comments