1use crate::error::*;
2use crate::object::*;
3use crate::scanner::*;
4
5use std::collections::{BTreeMap, HashMap, VecDeque};
6
7#[derive(Debug)]
8pub struct Parser<'source> {
9 pub scanner: Scanner<'source>,
10 pub current_level: usize,
11 pub class_history: Vec<String>,
12 pub schemas: HashMap<String, EntrySchema>,
13
14 upstream: HashMap<String, VariableMap>,
15 downstream: HashMap<String, Vec<VariableMap>>,
16 parse_direction: Direction,
17 ref_keys_buffer: Vec<String>,
18}
19
20#[derive(Debug, PartialEq, Eq)]
21enum Direction {
22 Down,
23 Up,
24}
25
26impl<'source> Parser<'source> {
27 pub fn new(source: &'source str) -> Self {
28 Parser {
29 scanner: Scanner::new(source),
30 current_level: 0,
31 class_history: vec!["_root_".to_string()],
32 schemas: HashMap::new(),
33
34 upstream: HashMap::new(),
35 downstream: HashMap::new(),
36 parse_direction: Direction::Down,
37 ref_keys_buffer: Vec::new(),
38 }
39 }
40
41 pub fn push_ref_key(&mut self, key: String) {
42 self.ref_keys_buffer.push(key);
43 }
44
45 pub fn get_schema(&self, class: String) -> Result<EntrySchema, ReamError> {
46 match self.schemas.get(&class) {
47 Some(v) => Ok((*v).clone()), None => Err(ReamError::SchemaError(SchemaErrorType::IncorrectSchema)),
49 }
50 }
51
52 pub fn parent_class(&self) -> Option<String> {
53 let level = self.current_level;
54 match level {
55 1 => None, _ => Some(self.class_history[level - 2].clone()), }
58 }
59
60 pub fn push_class(&mut self, new_class: String) {
61 self.class_history.push(new_class);
62 }
63
64 pub fn pop_class(&mut self) {
65 self.class_history.pop();
66 }
67
68 pub fn parse_header(&mut self) -> Result<usize, ReamError> {
76 let level = match self.scanner.take_token()? {
77 Some(Token(TokenType::Header(n), _, _)) => n,
78 _ => return Err(ReamError::ParseError(ParseErrorType::MissingHeaderLevel)),
79 };
80
81 Ok(level)
82 }
83
84 pub fn parse_identifier(&mut self) -> Result<String, ReamError> {
85 let identifier = match self.scanner.take_token()? {
86 Some(Token(TokenType::Class(c), _, _)) | Some(Token(TokenType::Key(c), _, _)) => c,
87 _ => return Err(ReamError::ParseError(ParseErrorType::MissingIdentifier)),
88 };
89
90 Ok(identifier)
91 }
92
93 pub fn parse_entry(&mut self) -> Result<Option<Entry>, ReamError> {
94
95 let level = self.parse_header()?;
97 self.current_level = level;
98
99 let class = self.parse_identifier()?;
101 self.push_class(class.clone()); let mut entry = Entry::new(class, level, self.parent_class());
105
106 while let Some(Token(TokenType::Dash, _, _)) = self.scanner.peek_token()? {
108 self.scanner.take_token()?; let (key, val) = self.parse_variable()?;
110 entry.push_key(key.clone());
111 entry.insert_variable(key, val)?;
112 }
113
114 let mut entry = self.check_schema(entry)?;
116
117 self.upstream.insert(entry.class(), entry.variable_map());
119
120 entry.set_ref_key(self.ref_keys_buffer.clone()); self.ref_keys_buffer = Vec::new();
123
124 while let Some(Token(TokenType::Header(next_level), _, _)) = self.scanner.peek_token()? {
126 if next_level.to_owned() == self.current_level + 1 {
127 self.parse_direction = Direction::Down;
129 let subentry = match self.parse_entry()? {
130 Some(sub) => sub,
131 None => return Err(ReamError::ParseError(ParseErrorType::MissingSubentry)),
132 };
133 entry.push_subentry(subentry);
134 } else if next_level.to_owned() <= self.current_level {
135 self.parse_direction = Direction::Up;
137 self.current_level -= 1;
138 break;
139 } else {
140 return Err(ReamError::ParseError(ParseErrorType::WrongHeaderLevel));
142 }
143 }
144
145 entry.resolve_downstream_ref(&self.downstream)?;
147
148 self.pop_class();
152
153 let variable_map = match self.upstream.get(&entry.class()) {
155 Some(map) => map.clone(),
156 None => return Err(ReamError::Placeholder),
157 };
158 self.upstream.remove(&entry.class());
159 self.insert_downstream(entry.class().clone(), variable_map.clone());
160
161
162 Ok(Some(entry))
163 }
164
165 pub fn insert_downstream(&mut self, class: String, variable_map: VariableMap) {
166 if let Some(x) = self.downstream.get_mut(&class) {
167 x.push(variable_map);
168 } else {
169 self.downstream.insert(class.clone(), vec![variable_map]);
170 }
171 }
172
173 pub fn check_schema(&mut self, entry: Entry) -> Result<Entry, ReamError> {
174 if self.schemas.contains_key(&entry.class()) {
175 self.check_schema_inner(entry)
177 } else {
178 self.init_schema(entry)
180 }
181 }
182
183 pub fn init_schema(&mut self, entry: Entry) -> Result<Entry, ReamError> {
184 let entry_keys = entry.keys();
185 let entry_parent_class = entry.get_parent_class();
186 let entry_schema = EntrySchema::new(entry_keys, entry_parent_class);
187
188 let entry_class = entry.class().clone(); self.schemas.insert(entry_class, entry_schema);
190
191 Ok(entry)
192 }
193
194 pub fn check_schema_inner(&self, entry: Entry) -> Result<Entry, ReamError> {
195 let entry_schema = entry.get_schema();
196 let parser_schema = self.get_schema(entry.class())?;
197
198 if entry_schema == parser_schema {
199 Ok(entry)
200 } else {
201 Err(ReamError::SchemaError(SchemaErrorType::IncorrectKeys))
202 }
203 }
204
205 pub fn parse_variable(&mut self) -> Result<(String, Value), ReamError> {
206 let key = self.parse_identifier()?;
207 let typ = self.parse_type()?;
208 self.parse_colon()?;
209 let value = self.parse_value(&key, typ)?;
210
211 Ok((key, value))
212 }
213
214 pub fn parse_value(&mut self, key: &String, typ: ValueType) -> Result<Value, ReamError> {
215 let tok_value = self.scanner.take_token()?;
216 let (value_base, typ) = match tok_value {
217 Some(Token(TokenType::Value(v), _, _)) => {
218 match typ {
219 ValueType::Ref => {
221 let (value_base, typ) = self.get_ref(v)?;
222 match value_base {
223 ValueBase::Ref(c, k) => {
226 self.push_ref_key(key.clone());
227 (ValueBase::new_ref(c, k), typ)
228 },
229 _ => (value_base, typ),
230 }
231 },
232 _ => ValueBase::new(v, typ)?,
233 }
234 }
235 Some(Token(TokenType::Star, _, _)) => self.parse_list_items(&key, typ)?,
236 _ => return Err(ReamError::ParseError(ParseErrorType::MissingValue)),
237 };
238
239 let annotation = self.parse_annotation()?;
240
241 let value = Value::new(value_base, annotation, typ);
242
243 Ok(value)
244 }
245
246 pub fn get_ref(&self, value: String) -> Result<(ValueBase, ValueType), ReamError> {
247 let v: Vec<&str> = value.split('$').collect();
248
249 if let [class, key] = &v[..] {
250 match self.upstream.get(*class) {
251 Some(variable_map) => match variable_map.get(&key.to_string()) {
252 Some(s) => Ok(s.get_base_and_typ()),
253 None => Err(ReamError::ReferenceError(
254 ReferenceErrorType::VariableKeyNotFound,
255 )),
256 },
257 None => match self.parse_direction {
258 Direction::Down => Ok((
259 ValueBase::new_ref(
260 (*class).to_string(),
261 (*key).to_string(),
262 ),
263 ValueType::Ref,
264 )),
265 Direction::Up => Err(ReamError::ReferenceError(
266 ReferenceErrorType::EntryClassNotFound,
267 )),
268 }
269 }
270 } else {
271 return Err(ReamError::ReferenceError(
272 ReferenceErrorType::InvalidReference,
273 ));
274 }
275 }
276
277 pub fn parse_list_items(
278 &mut self,
279 key: &String,
280 typ: ValueType,
281 ) -> Result<(ValueBase, ValueType), ReamError> {
282 let typ = match typ {
284 ValueType::List(t) => *t,
285 ValueType::Unknown => ValueType::Unknown,
286 _ => return Err(ReamError::TypeError(TypeErrorType::UnknownType)),
287 };
288
289 let first_item = self.parse_value(&key, typ.clone())?;
291
292 let item_typ = first_item.typ().clone(); let mut list = List::new(item_typ.clone(), first_item);
295
296 loop {
298 match self.scanner.peek_token()? {
299 Some(Token(TokenType::Star, _, _)) => {
300 self.scanner.take_token()?; let new_item = self.parse_value(&key, typ.clone())?;
302 if new_item.typ() == list.item_type() {
304 list.push_item(new_item);
305 } else {
306 return Err(ReamError::TypeError(TypeErrorType::HeterogeneousList));
307 }
308 }
309 _ => break,
310 }
311 }
312
313 let value_base = ValueBase::new_item(list);
314 let typ = ValueType::List(Box::new(item_typ.clone()));
315 Ok((value_base, typ))
316 }
317
318 pub fn parse_annotation(&mut self) -> Result<Option<String>, ReamError> {
319 match self.scanner.peek_token()? {
320 Some(Token(TokenType::Block(_), _, _)) => {
321 self.scanner.take_token()?; match self.scanner.take_token()? {
323 Some(Token(TokenType::Annotation(s), _, _)) => Ok(Some(s)),
324 _ => return Err(ReamError::Placeholder),
325 }
326 }
327 _ => Ok(None),
328 }
329 }
330
331 pub fn parse_type(&mut self) -> Result<ValueType, ReamError> {
332 let typ = match self.scanner.peek_token()? {
333 Some(Token(TokenType::ValueType(_), _, _)) => {
335 let t = match self.scanner.take_token()? {
336 Some(Token(TokenType::ValueType(t), _, _)) => t,
337 _ => return Err(ReamError::Placeholder),
338 };
339 t
340 }
341 Some(Token(TokenType::Colon, _, _)) => ValueType::Unknown,
343 _ => return Err(ReamError::ParseError(ParseErrorType::MissingColon)),
345 };
346
347 Ok(typ)
348 }
349
350 pub fn parse_colon(&mut self) -> Result<(), ReamError> {
351 match self.scanner.take_token()? {
352 Some(Token(TokenType::Colon, _, _)) => Ok(()),
353 _ => return Err(ReamError::ParseError(ParseErrorType::MissingColon)),
354 }
355 }
356}
357
358#[cfg(test)]
359mod tests {
360
361 use super::*;
362
363 }