1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use std::slice::Iter;
use envl_utils::{
error::{EnvlError, ErrorContext},
types::{FilePosition, Position},
variable::Type,
};
use crate::{
misc::token::{Token, Value},
parser::Parser,
};
impl Parser {
pub(super) fn parse_option<'a>(&self, tokens: &mut Iter<'a, Token>) -> Result<Type, EnvlError> {
let mut in_block = false;
let mut block_closed = false;
let mut last_position = None;
let mut optional_type = None;
let mut parser_error = None;
'parse_loop: loop {
if let Some(token) = tokens.next() {
macro_rules! error {
($msg: expr) => {
parser_error = Some(EnvlError {
message: $msg,
position: token.position.clone(),
});
break 'parse_loop;
};
}
last_position = Some(token.position.to_owned());
match &token.value {
Value::LeftShift => {
if in_block {
error!(ErrorContext::InvalidPosition("<".to_string()));
}
in_block = true;
continue;
}
Value::RightShift => {
block_closed = true;
break 'parse_loop;
}
_ => {}
}
if !in_block {
error!(ErrorContext::MustInBlock("vars".to_string()));
}
if optional_type.is_some() {
error!(ErrorContext::InvalidType);
}
match &token.value {
Value::Type(t) => {
optional_type = Some(t.clone());
}
Value::Array => match self.parse_array(tokens) {
Ok(t) => {
optional_type = Some(t);
}
Err(err) => {
parser_error = Some(err);
break 'parse_loop;
}
},
Value::Struct => match self.parse_struct(tokens) {
Ok(t) => {
optional_type = Some(t);
}
Err(err) => {
parser_error = Some(err);
break 'parse_loop;
}
},
_ => {
error!(ErrorContext::InvalidSyntaxInBlock("option".to_string()));
}
}
} else {
break 'parse_loop;
}
}
if let Some(err) = parser_error {
Err(err)
} else {
if let Some(position) = last_position {
if !block_closed {
return Err(EnvlError {
message: ErrorContext::IsntClosed("Option".to_string()),
position,
});
}
}
if let Some(t) = optional_type {
Ok(Type::Option(Box::from(t)))
} else {
Err(EnvlError {
message: ErrorContext::InvalidType,
position: Position {
file_path: self.position.file_path.to_owned(),
start: FilePosition { row: 0, col: 0 },
end: self.position.end.clone(),
},
})
}
}
}
}