sieve/compiler/grammar/tests/
test_environment.rs1use crate::compiler::{
8 grammar::{instruction::CompilerState, Capability, Comparator},
9 lexer::{word::Word, Token},
10 CompileError, Value, VariableType,
11};
12
13use crate::compiler::grammar::{test::Test, MatchType};
14
15use super::test_string::TestString;
16
17impl CompilerState<'_> {
18 pub(crate) fn parse_test_environment(&mut self) -> Result<Test, CompileError> {
19 let mut match_type = MatchType::Is;
20 let mut comparator = Comparator::AsciiCaseMap;
21 let mut name = None;
22 let mut key_list;
23
24 loop {
25 let token_info = self.tokens.unwrap_next()?;
26 match token_info.token {
27 Token::Tag(
28 word @ (Word::Is
29 | Word::Contains
30 | Word::Matches
31 | Word::Value
32 | Word::Count
33 | Word::Regex),
34 ) => {
35 self.validate_argument(
36 1,
37 match word {
38 Word::Value | Word::Count => Capability::Relational.into(),
39 Word::Regex => Capability::Regex.into(),
40 Word::List => Capability::ExtLists.into(),
41 _ => None,
42 },
43 token_info.line_num,
44 token_info.line_pos,
45 )?;
46
47 match_type = self.parse_match_type(word)?;
48 }
49 Token::Tag(Word::Comparator) => {
50 self.validate_argument(2, None, token_info.line_num, token_info.line_pos)?;
51 comparator = self.parse_comparator()?;
52 }
53 _ => {
54 if name.is_none() {
55 if let Token::StringConstant(s) = token_info.token {
56 name = Value::Variable(VariableType::Environment(
57 s.into_string().to_lowercase(),
58 ))
59 .into();
60 } else {
61 return Err(token_info.expected("environment variable"));
62 }
63 } else {
64 key_list = self.parse_strings_token(token_info)?;
65 break;
66 }
67 }
68 }
69 }
70 self.validate_match(&match_type, &mut key_list)?;
71
72 Ok(Test::Environment(TestString {
73 source: vec![name.unwrap()],
74 key_list,
75 match_type,
76 comparator,
77 is_not: false,
78 }))
79 }
80}