1 use super::{Parser, Result, Slice}; 2 use crate::ast; 3 4 #[derive(Debug, PartialEq, Clone, Copy)] 5 pub(super) enum Level { 6 None = 0, 7 Regular = 1, 8 Group = 2, 9 Resource = 3, 10 } 11 12 impl<'s, S> Parser<S> 13 where 14 S: Slice<'s>, 15 { get_comment(&mut self) -> Result<(ast::Comment<S>, Level)>16 pub(super) fn get_comment(&mut self) -> Result<(ast::Comment<S>, Level)> { 17 let mut level = Level::None; 18 let mut content = vec![]; 19 20 while self.ptr < self.length { 21 let line_level = self.get_comment_level(); 22 if line_level == Level::None { 23 self.ptr -= 1; 24 break; 25 } else if level != Level::None && line_level != level { 26 self.ptr -= line_level as usize; 27 break; 28 } 29 30 level = line_level; 31 32 if self.ptr == self.length { 33 break; 34 } else if self.is_current_byte(b'\n') { 35 content.push(self.get_comment_line()?); 36 } else { 37 if let Err(e) = self.expect_byte(b' ') { 38 if content.is_empty() { 39 return Err(e); 40 } else { 41 self.ptr -= line_level as usize; 42 break; 43 } 44 } 45 content.push(self.get_comment_line()?); 46 } 47 self.skip_eol(); 48 } 49 50 Ok((ast::Comment { content }, level)) 51 } 52 get_comment_level(&mut self) -> Level53 fn get_comment_level(&mut self) -> Level { 54 let mut chars = 0; 55 56 for _ in 0..3 { 57 if self.take_byte_if(b'#') { 58 chars += 1; 59 } 60 } 61 62 match chars { 63 0 => Level::None, 64 1 => Level::Regular, 65 2 => Level::Group, 66 3 => Level::Resource, 67 _ => unreachable!(), 68 } 69 } 70 get_comment_line(&mut self) -> Result<S>71 fn get_comment_line(&mut self) -> Result<S> { 72 let start_pos = self.ptr; 73 74 while self.ptr < self.length && !self.is_eol() { 75 self.ptr += 1; 76 } 77 78 Ok(self.source.slice(start_pos..self.ptr)) 79 } 80 } 81