| 1 | use super::{ |
| 2 | core::{Parser, Result}, |
| 3 | errors::ParserError, |
| 4 | slice::Slice, |
| 5 | }; |
| 6 | use crate::ast; |
| 7 | |
| 8 | impl<'s, S> Parser<S> |
| 9 | where |
| 10 | S: Slice<'s>, |
| 11 | { |
| 12 | pub fn parse_runtime( |
| 13 | mut self, |
| 14 | ) -> std::result::Result<ast::Resource<S>, (ast::Resource<S>, Vec<ParserError>)> { |
| 15 | let mut errors = vec![]; |
| 16 | |
| 17 | // That default allocation gives the lowest |
| 18 | // number of instructions and cycles in ioi. |
| 19 | let mut body = Vec::with_capacity(6); |
| 20 | |
| 21 | self.skip_blank_block(); |
| 22 | |
| 23 | while self.ptr < self.length { |
| 24 | let entry_start = self.ptr; |
| 25 | let entry = self.get_entry_runtime(entry_start); |
| 26 | |
| 27 | match entry { |
| 28 | Ok(Some(entry)) => { |
| 29 | body.push(entry); |
| 30 | } |
| 31 | Ok(None) => {} |
| 32 | Err(mut err) => { |
| 33 | self.skip_to_next_entry_start(); |
| 34 | err.slice = Some(entry_start..self.ptr); |
| 35 | errors.push(err); |
| 36 | let content = self.source.slice(entry_start..self.ptr); |
| 37 | body.push(ast::Entry::Junk { content }); |
| 38 | } |
| 39 | } |
| 40 | self.skip_blank_block(); |
| 41 | } |
| 42 | |
| 43 | if errors.is_empty() { |
| 44 | Ok(ast::Resource { body }) |
| 45 | } else { |
| 46 | Err((ast::Resource { body }, errors)) |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | fn get_entry_runtime(&mut self, entry_start: usize) -> Result<Option<ast::Entry<S>>> { |
| 51 | let entry = match get_current_byte!(self) { |
| 52 | Some(b'#' ) => { |
| 53 | self.skip_comment(); |
| 54 | None |
| 55 | } |
| 56 | Some(b'-' ) => Some(ast::Entry::Term(self.get_term(entry_start)?)), |
| 57 | _ => Some(ast::Entry::Message(self.get_message(entry_start)?)), |
| 58 | }; |
| 59 | Ok(entry) |
| 60 | } |
| 61 | } |
| 62 | |