Skip to main content

flams_utils/parsing/
read.rs

1use crate::{parsing::SourceParser, sourcerefs::StringPosition};
2use std::io::Read;
3
4pub struct ReadParser<R: Read, P: StringPosition> {
5    inner: std::io::Bytes<std::io::BufReader<R>>,
6    buf: Vec<char>,
7    pos: P,
8}
9impl<R: Read, P: StringPosition> ReadParser<R, P> {
10    pub fn new(inner: R) -> Self {
11        Self {
12            inner: std::io::BufReader::new(inner).bytes(),
13            buf: Vec::new(),
14            pos: P::default(),
15        }
16    }
17}
18
19impl<'a, R: Read + 'a, P: StringPosition> SourceParser<'a> for ReadParser<R, P> {
20    type Pos = P;
21    type Str = String;
22    type Source = R;
23    #[inline]
24    fn curr_pos(&self) -> P {
25        self.pos
26    }
27    #[inline]
28    fn skip(&mut self, i: usize) {
29        for _ in 0..i {
30            self.next_char();
31        }
32    }
33    fn next_char(&mut self) -> Option<char> {
34        match self.get_char() {
35            Some('\n') => {
36                self.pos.inc_newline(false);
37                Some('\n')
38            }
39            Some('\r') => {
40                match self.get_char() {
41                    Some('\n') | None => {
42                        self.pos.inc_newline(false);
43                    }
44                    Some(c) => {
45                        self.pos.inc_newline(false);
46                        self.push_char(c);
47                    }
48                }
49                Some('\n')
50            }
51            Some(c) => {
52                self.pos.inc_by(c);
53                Some(c)
54            }
55            None => None,
56        }
57    }
58    fn read_until_line_end(&mut self) -> (String, P) {
59        let (s, rn) = self.find_line_end();
60        self.pos.inc_offset_by(&s);
61        let pos = self.pos;
62        if let Some(rn) = rn {
63            self.pos.inc_newline(rn);
64        }
65        (s, pos)
66    }
67    fn trim_start(&mut self) {
68        while let Some(c) = self.get_char() {
69            if c == '\n' {
70                self.pos.inc_newline(false);
71            } else if c == '\r' {
72                match self.get_char() {
73                    Some('\n') => {
74                        self.pos.inc_newline(true);
75                    }
76                    Some(c) => {
77                        self.push_char(c);
78                        self.pos.inc_newline(false);
79                    }
80                    None => {
81                        self.pos.inc_newline(false);
82                        break;
83                    }
84                }
85            } else if c.is_whitespace() {
86                self.pos.inc_by(c);
87            } else {
88                self.push_char(c);
89                break;
90            }
91        }
92    }
93
94    #[allow(clippy::unnecessary_map_or)]
95    fn starts_with(&mut self, c: char) -> bool {
96        self.get_char().map_or(false, |c2| {
97            self.push_char(c2);
98            c2 == c
99        })
100    }
101    fn read_while(&mut self, mut pred: impl FnMut(char) -> bool) -> Self::Str {
102        let mut ret = String::new();
103        let mut rn = false;
104        while let Some(c) = self.get_char() {
105            if !pred(c) {
106                self.push_char(c);
107                break;
108            }
109            if rn && c == '\n' {
110                self.pos.inc_newline(true);
111                rn = false;
112                continue;
113            }
114            if rn {
115                self.pos.inc_newline(false);
116                rn = false;
117            } else if c == '\n' {
118                self.pos.inc_newline(false);
119                ret.push('\n');
120                continue;
121            } else if c == '\r' {
122                ret.push('\n');
123                rn = true;
124                continue;
125            }
126            self.pos.inc_by(c);
127            ret.push(c);
128        }
129        if rn {
130            self.pos.inc_newline(false);
131        }
132        ret
133    }
134
135    fn read_until_inclusive(&mut self, pred: impl FnMut(char) -> bool) -> Self::Str {
136        let mut r = self.read_until(pred);
137        if let Some(c) = self.next_char() {
138            r.push(c);
139        }
140        r
141    }
142
143    #[inline]
144    fn read_until_byte(&mut self, b: u8) -> Self::Str {
145        self.read_until_char(b as char)
146    }
147    #[inline]
148    fn read_until_char(&mut self, ch: char) -> Self::Str {
149        let mut ret = String::new();
150        let mut rn = false;
151        while let Some(c) = self.get_char() {
152            if c == ch {
153                self.push_char(c);
154                break;
155            }
156            if rn && c == '\n' {
157                self.pos.inc_newline(true);
158                rn = false;
159                continue;
160            }
161            if rn {
162                self.pos.inc_newline(false);
163                rn = false;
164            } else if c == '\n' {
165                self.pos.inc_newline(false);
166                ret.push('\n');
167                continue;
168            } else if c == '\r' {
169                ret.push('\n');
170                rn = true;
171                continue;
172            }
173            self.pos.inc_by(c);
174            ret.push(c);
175        }
176        if rn {
177            self.pos.inc_newline(false);
178        }
179        ret
180    }
181
182    fn read_until_with_brackets(
183        &mut self,
184        open: char,
185        close: char,
186        mut pred: impl FnMut(char) -> bool,
187    ) -> Self::Str {
188        let mut ret = String::new();
189        let mut depth = 0;
190        let mut rn = false;
191        while let Some(c) = self.get_char() {
192            if c == open {
193                depth += 1;
194                self.pos.inc_by(c);
195                ret.push(c);
196                continue;
197            } else if c == close && depth > 0 {
198                depth -= 1;
199                self.pos.inc_by(c);
200                ret.push(c);
201                continue;
202            } else if depth > 0 {
203                if rn && c == '\n' {
204                    self.pos.inc_newline(true);
205                    rn = false;
206                    continue;
207                }
208                if rn {
209                    self.pos.inc_newline(false);
210                    rn = false;
211                } else if c == '\n' {
212                    self.pos.inc_newline(false);
213                    ret.push('\n');
214                    continue;
215                } else if c == '\r' {
216                    ret.push('\n');
217                    rn = true;
218                    continue;
219                }
220                self.pos.inc_by(c);
221                ret.push(c);
222                continue;
223            }
224            if pred(c) {
225                self.push_char(c);
226                break;
227            }
228            self.pos.inc_by(c);
229            ret.push(c);
230        }
231        if rn {
232            self.pos.inc_newline(false);
233        }
234        ret
235    }
236
237    #[inline]
238    fn read_until_byte_with_brackets(&mut self, b: u8, open: u8, close: u8) -> Self::Str {
239        self.read_until_with_brackets(open as _, close as _, |c| c == b as char)
240    }
241
242    fn peek_head(&mut self) -> Option<char> {
243        self.get_char().inspect(|c| {
244            self.push_char(*c);
245        })
246    }
247    fn read_n(&mut self, i: usize) -> Self::Str {
248        let mut ret = String::new();
249        for _ in 0..i {
250            if let Some(c) = self.next_char() {
251                ret.push(c);
252            } else {
253                break;
254            }
255        }
256        ret
257    }
258
259    fn read_until_str(&mut self, s: &str) -> Self::Str {
260        let mut ret = String::with_capacity(32);
261        while let Some(c) = self.next_char() {
262            ret.push(c);
263            if ret.ends_with(s) {
264                for _ in 0..s.len() {
265                    self.push_char(ret.pop().unwrap_or_else(|| unreachable!()));
266                }
267                return ret;
268            }
269        }
270        ret
271    }
272
273    #[inline]
274    fn read_until_needle(&mut self, s: &super::Needle) -> Self::Str {
275        self.read_until_str(s.as_str())
276    }
277
278    fn starts_with_str(&mut self, s: &str) -> bool {
279        let mut read = 0;
280        macro_rules! nope {
281            () => {{
282                for c in s.chars().take(read) {
283                    self.push_char(c);
284                }
285                return false;
286            }};
287        }
288        for c in s.chars() {
289            if let Some(c2) = self.next_char() {
290                read += 1;
291                if c != c2 {
292                    nope!()
293                }
294            } else {
295                nope!();
296            }
297        }
298        self.buf.extend(s.chars().rev());
299        true
300    }
301
302    fn drop_prefix(&mut self, s: &str) -> bool {
303        let mut read = 0;
304        macro_rules! nope {
305            () => {{
306                for c in s.chars().take(read) {
307                    self.push_char(c);
308                }
309                return false;
310            }};
311        }
312        for c in s.chars() {
313            if let Some(c2) = self.next_char() {
314                read += 1;
315                if c != c2 {
316                    nope!()
317                }
318            } else {
319                nope!();
320            }
321        }
322        true
323    }
324}
325
326impl<R: Read, P: StringPosition> ReadParser<R, P> {
327    #[inline]
328    fn get_char(&mut self) -> Option<char> {
329        self.buf.pop().or_else(|| self.read_char())
330    }
331    fn read_char(&mut self) -> Option<char> {
332        self.inner.next().and_then(|byte| {
333            byte.ok().and_then(|byte| {
334                if byte & 0b1110_0000_u8 == 192u8 {
335                    // a two byte unicode character
336                    let next = self.inner.next().and_then(Result::ok)?;
337                    Self::char_from_utf8(&[byte, next])
338                } else if byte & 0b1111_0000_u8 == 224u8 {
339                    // a three byte unicode character
340                    let next1 = self.inner.next().and_then(Result::ok)?;
341                    let next2 = self.inner.next().and_then(Result::ok)?;
342                    Self::char_from_utf8(&[byte, next1, next2])
343                } else if byte & 0b1111_1000_u8 == 240u8 {
344                    // a four byte unicode character
345                    let next1 = self.inner.next().and_then(Result::ok)?;
346                    let next2 = self.inner.next().and_then(Result::ok)?;
347                    let next3 = self.inner.next().and_then(Result::ok)?;
348                    Self::char_from_utf8(&[byte, next1, next2, next3])
349                } else {
350                    Some(byte as char)
351                }
352            })
353        })
354    }
355    fn push_char(&mut self, c: char) {
356        self.buf.push(c);
357    }
358    fn char_from_utf8(buf: &[u8]) -> Option<char> {
359        std::str::from_utf8(buf).ok().and_then(|s| s.chars().next())
360    }
361    fn find_line_end(&mut self) -> (String, Option<bool>) {
362        let mut ret = String::new();
363        while let Some(c) = self.get_char() {
364            if c == '\n' {
365                return (ret, Some(false));
366            }
367            if c == '\r' {
368                match self.get_char() {
369                    Some('\n') => return (ret, Some(true)),
370                    Some(c) => self.push_char(c),
371                    None => (),
372                }
373                return (ret, Some(true));
374            }
375            ret.push(c);
376        }
377        (ret, None)
378    }
379}