Skip to content

Commit 71e3fed

Browse files
committed
Arithmetic and logical expression evaluation
1 parent f9c01ba commit 71e3fed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

92 files changed

+3034
-1138
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ Cargo.lock
88

99
# These are backup files generated by rustfmt
1010
**/*.rs.bk
11+
*.failed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ regex = "1.7.0"
2525

2626
[dev-dependencies]
2727
serde_json = "1.0"
28+
evalexpr = "11.1.0"

src/compiler/grammar/actions/action_convert.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,14 @@ use crate::compiler::{
2828
instruction::{CompilerState, Instruction},
2929
test::Test,
3030
},
31-
lexer::string::StringItem,
32-
CompileError,
31+
CompileError, Value,
3332
};
3433

3534
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
3635
pub(crate) struct Convert {
37-
pub from_media_type: StringItem,
38-
pub to_media_type: StringItem,
39-
pub transcoding_params: Vec<StringItem>,
36+
pub from_media_type: Value,
37+
pub to_media_type: Value,
38+
pub transcoding_params: Vec<Value>,
4039
pub is_not: bool,
4140
}
4241

src/compiler/grammar/actions/action_editheader.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,17 @@ use crate::compiler::{
2929
instruction::{CompilerState, Instruction},
3030
Capability, Comparator,
3131
},
32-
lexer::{string::StringItem, word::Word, Token},
33-
CompileError, ErrorType,
32+
lexer::{word::Word, Token},
33+
CompileError, ErrorType, Value,
3434
};
3535

3636
use crate::compiler::grammar::MatchType;
3737

3838
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
3939
pub(crate) struct AddHeader {
4040
pub last: bool,
41-
pub field_name: StringItem,
42-
pub value: StringItem,
41+
pub field_name: Value,
42+
pub value: Value,
4343
}
4444

4545
/*
@@ -54,8 +54,8 @@ pub(crate) struct DeleteHeader {
5454
pub index: Option<i32>,
5555
pub comparator: Comparator,
5656
pub match_type: MatchType,
57-
pub field_name: StringItem,
58-
pub value_patterns: Vec<StringItem>,
57+
pub field_name: Value,
58+
pub value_patterns: Vec<Value>,
5959
pub mime_anychild: bool,
6060
}
6161

@@ -75,7 +75,7 @@ impl<'x> CompilerState<'x> {
7575
_ => {
7676
let string = self.parse_string_token(token_info)?;
7777
if field_name.is_none() {
78-
if let StringItem::Text(header_name) = &string {
78+
if let Value::Text(header_name) = &string {
7979
if HeaderName::parse(header_name).is_none() {
8080
return Err(self
8181
.tokens
@@ -88,7 +88,7 @@ impl<'x> CompilerState<'x> {
8888
} else {
8989
if matches!(
9090
&string,
91-
StringItem::Text(value) if value.len() > self.compiler.max_header_size
91+
Value::Text(value) if value.len() > self.compiler.max_header_size
9292
) {
9393
return Err(self
9494
.tokens
@@ -110,7 +110,7 @@ impl<'x> CompilerState<'x> {
110110
}
111111

112112
pub(crate) fn parse_deleteheader(&mut self) -> Result<(), CompileError> {
113-
let field_name: StringItem;
113+
let field_name: Value;
114114
let mut match_type = MatchType::Is;
115115
let mut comparator = Comparator::AsciiCaseMap;
116116
let mut index = None;
@@ -174,7 +174,7 @@ impl<'x> CompilerState<'x> {
174174
}
175175
_ => {
176176
field_name = self.parse_string_token(token_info)?;
177-
if let StringItem::Text(header_name) = &field_name {
177+
if let Value::Text(header_name) = &field_name {
178178
if HeaderName::parse(header_name).is_none() {
179179
return Err(self
180180
.tokens

src/compiler/grammar/actions/action_fileinto.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,18 @@ use crate::compiler::{
2828
instruction::{CompilerState, Instruction},
2929
Capability,
3030
},
31-
lexer::{string::StringItem, word::Word, Token},
32-
CompileError,
31+
lexer::{word::Word, Token},
32+
CompileError, Value,
3333
};
3434

3535
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
3636
pub(crate) struct FileInto {
3737
pub copy: bool,
3838
pub create: bool,
39-
pub folder: StringItem,
40-
pub flags: Vec<StringItem>,
41-
pub mailbox_id: Option<StringItem>,
42-
pub special_use: Option<StringItem>,
39+
pub folder: Value,
40+
pub flags: Vec<Value>,
41+
pub mailbox_id: Option<Value>,
42+
pub special_use: Option<Value>,
4343
}
4444

4545
impl<'x> CompilerState<'x> {

src/compiler/grammar/actions/action_flags.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,15 @@ use serde::{Deserialize, Serialize};
2525

2626
use crate::compiler::{
2727
grammar::instruction::{CompilerState, Instruction},
28-
lexer::{string::StringItem, word::Word, Token},
29-
CompileError, ErrorType,
28+
lexer::{word::Word, Token},
29+
CompileError, ErrorType, Value, VariableType,
3030
};
3131

32-
use super::action_set::Variable;
33-
3432
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
3533
pub(crate) struct EditFlags {
3634
pub action: Action,
37-
pub name: Option<Variable>,
38-
pub flags: Vec<StringItem>,
35+
pub name: Option<VariableType>,
36+
pub flags: Vec<Value>,
3937
}
4038

4139
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]

src/compiler/grammar/actions/action_include.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ use serde::{Deserialize, Serialize};
2525

2626
use crate::compiler::{
2727
grammar::instruction::{CompilerState, Instruction},
28-
lexer::{string::StringItem, word::Word, Token},
29-
CompileError,
28+
lexer::{word::Word, Token},
29+
CompileError, Value,
3030
};
3131

3232
/*
@@ -41,7 +41,7 @@ pub(crate) struct Include {
4141
pub location: Location,
4242
pub once: bool,
4343
pub optional: bool,
44-
pub value: StringItem,
44+
pub value: Value,
4545
}
4646

4747
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]

src/compiler/grammar/actions/action_keep.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ use crate::compiler::{
2828
instruction::{CompilerState, Instruction},
2929
Capability,
3030
},
31-
lexer::{string::StringItem, word::Word, Token},
32-
CompileError,
31+
lexer::{word::Word, Token},
32+
CompileError, Value,
3333
};
3434

3535
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
3636
pub(crate) struct Keep {
37-
pub flags: Vec<StringItem>,
37+
pub flags: Vec<Value>,
3838
}
3939

4040
impl<'x> CompilerState<'x> {

src/compiler/grammar/actions/action_mime.rs

+11-14
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ use serde::{Deserialize, Serialize};
2525

2626
use crate::compiler::{
2727
grammar::instruction::{CompilerState, Instruction},
28-
lexer::{string::StringItem, word::Word, Token},
29-
CompileError,
28+
lexer::{word::Word, Token},
29+
CompileError, Value, VariableType,
3030
};
3131

32-
use super::action_set::{Modifier, Variable};
32+
use super::action_set::Modifier;
3333

3434
#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
3535
pub(crate) struct ForEveryPart {
@@ -38,24 +38,24 @@ pub(crate) struct ForEveryPart {
3838

3939
#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
4040
pub(crate) struct Replace {
41-
pub subject: Option<StringItem>,
42-
pub from: Option<StringItem>,
43-
pub replacement: StringItem,
41+
pub subject: Option<Value>,
42+
pub from: Option<Value>,
43+
pub replacement: Value,
4444
pub mime: bool,
4545
}
4646

4747
#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
4848
pub(crate) struct Enclose {
49-
pub subject: Option<StringItem>,
50-
pub headers: Vec<StringItem>,
51-
pub value: StringItem,
49+
pub subject: Option<Value>,
50+
pub headers: Vec<Value>,
51+
pub value: Value,
5252
}
5353

5454
#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
5555
pub(crate) struct ExtractText {
5656
pub modifiers: Vec<Modifier>,
5757
pub first: Option<usize>,
58-
pub name: Variable,
58+
pub name: VariableType,
5959
}
6060

6161
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
@@ -188,10 +188,7 @@ impl<'x> CompilerState<'x> {
188188
Ok(())
189189
}
190190

191-
pub(crate) fn parse_mimeopts(
192-
&mut self,
193-
opts: Word,
194-
) -> Result<MimeOpts<StringItem>, CompileError> {
191+
pub(crate) fn parse_mimeopts(&mut self, opts: Word) -> Result<MimeOpts<Value>, CompileError> {
195192
Ok(match opts {
196193
Word::Type => MimeOpts::Type,
197194
Word::Subtype => MimeOpts::Subtype,

src/compiler/grammar/actions/action_notify.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ use crate::{
2929
instruction::{CompilerState, Instruction},
3030
Capability,
3131
},
32-
lexer::{string::StringItem, word::Word, Token},
33-
CompileError, ErrorType,
32+
lexer::{word::Word, Token},
33+
CompileError, ErrorType, Value,
3434
},
3535
runtime::actions::action_notify::{validate_from, validate_uri},
3636
FileCarbonCopy,
@@ -47,12 +47,12 @@ notify [":from" string]
4747

4848
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
4949
pub(crate) struct Notify {
50-
pub from: Option<StringItem>,
51-
pub importance: Option<StringItem>,
52-
pub options: Vec<StringItem>,
53-
pub message: Option<StringItem>,
54-
pub fcc: Option<FileCarbonCopy<StringItem>>,
55-
pub method: StringItem,
50+
pub from: Option<Value>,
51+
pub importance: Option<Value>,
52+
pub options: Vec<Value>,
53+
pub message: Option<Value>,
54+
pub fcc: Option<FileCarbonCopy<Value>>,
55+
pub method: Value,
5656
}
5757

5858
impl<'x> CompilerState<'x> {
@@ -75,7 +75,7 @@ impl<'x> CompilerState<'x> {
7575
Token::Tag(Word::From) => {
7676
self.validate_argument(1, None, token_info.line_num, token_info.line_pos)?;
7777
let address = self.parse_string()?;
78-
if let StringItem::Text(address) = &address {
78+
if let Value::Text(address) = &address {
7979
if address.is_empty() || !validate_from(address) {
8080
return Err(token_info.custom(ErrorType::InvalidAddress));
8181
}
@@ -141,7 +141,7 @@ impl<'x> CompilerState<'x> {
141141
}
142142
_ => {
143143
if let Token::StringConstant(uri) = &token_info.token {
144-
if validate_uri(std::str::from_utf8(uri).unwrap_or("")).is_none() {
144+
if validate_uri(uri.to_string().as_ref()).is_none() {
145145
return Err(token_info.custom(ErrorType::InvalidURI));
146146
}
147147
}

src/compiler/grammar/actions/action_redirect.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,17 @@ use crate::compiler::{
2828
instruction::{CompilerState, Instruction},
2929
Capability,
3030
},
31-
lexer::{string::StringItem, word::Word, Token},
32-
CompileError,
31+
lexer::{word::Word, Token},
32+
CompileError, Value,
3333
};
3434

3535
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
3636
pub(crate) struct Redirect {
3737
pub copy: bool,
38-
pub address: StringItem,
38+
pub address: Value,
3939
pub notify: Notify,
4040
pub return_of_content: Ret,
41-
pub by_time: ByTime<StringItem>,
41+
pub by_time: ByTime<Value>,
4242
pub list: bool,
4343
}
4444

@@ -144,9 +144,9 @@ impl<'x> CompilerState<'x> {
144144
token_info.line_pos,
145145
)?;
146146
let by_mode_ = self.tokens.expect_static_string()?;
147-
if by_mode_.eq_ignore_ascii_case(b"notify") {
147+
if by_mode_.eq_ignore_ascii_case("notify") {
148148
by_mode = ByMode::Notify;
149-
} else if by_mode_.eq_ignore_ascii_case(b"return") {
149+
} else if by_mode_.eq_ignore_ascii_case("return") {
150150
by_mode = ByMode::Return;
151151
} else {
152152
return Err(token_info.expected("\"notify\" or \"return\""));
@@ -178,9 +178,9 @@ impl<'x> CompilerState<'x> {
178178
token_info.line_pos,
179179
)?;
180180
let ret_ = self.tokens.expect_static_string()?;
181-
if ret_.eq_ignore_ascii_case(b"full") {
181+
if ret_.eq_ignore_ascii_case("full") {
182182
ret = Ret::Full;
183-
} else if ret_.eq_ignore_ascii_case(b"hdrs") {
183+
} else if ret_.eq_ignore_ascii_case("hdrs") {
184184
ret = Ret::Hdrs;
185185
} else {
186186
return Err(token_info.expected("\"FULL\" or \"HDRS\""));
@@ -194,11 +194,11 @@ impl<'x> CompilerState<'x> {
194194
token_info.line_pos,
195195
)?;
196196
let notify_ = self.tokens.expect_static_string()?;
197-
if notify_.eq_ignore_ascii_case(b"never") {
197+
if notify_.eq_ignore_ascii_case("never") {
198198
notify = Notify::Never;
199199
} else {
200200
let mut items = Vec::new();
201-
for item in String::from_utf8_lossy(&notify_).split(',') {
201+
for item in notify_.split(',') {
202202
let item = item.trim();
203203
if item.eq_ignore_ascii_case("success") {
204204
items.push(NotifyItem::Success);

src/compiler/grammar/actions/action_reject.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,13 @@ use serde::{Deserialize, Serialize};
2525

2626
use crate::compiler::{
2727
grammar::instruction::{CompilerState, Instruction},
28-
lexer::string::StringItem,
29-
CompileError,
28+
CompileError, Value,
3029
};
3130

3231
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
3332
pub(crate) struct Reject {
3433
pub ereject: bool,
35-
pub reason: StringItem,
34+
pub reason: Value,
3635
}
3736

3837
impl<'x> CompilerState<'x> {

src/compiler/grammar/actions/action_require.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ impl<'x> CompilerState<'x> {
6161
Token::StringConstant(value) => {
6262
self.add_capability(
6363
&mut capabilities,
64-
Capability::parse(std::str::from_utf8(&value).unwrap_or("")),
64+
Capability::parse(value.to_string().as_ref()),
6565
);
6666
let token_info = self.tokens.unwrap_next()?;
6767
match token_info.token {
@@ -80,7 +80,7 @@ impl<'x> CompilerState<'x> {
8080
Token::StringConstant(value) => {
8181
self.add_capability(
8282
&mut capabilities,
83-
Capability::parse(std::str::from_utf8(&value).unwrap_or("")),
83+
Capability::parse(value.to_string().as_ref()),
8484
);
8585
}
8686
_ => {

0 commit comments

Comments
 (0)