tiger_lib/parse/
cob.rs

1use std::mem::take;
2
3use crate::token::{Loc, Token};
4
5/// Copy on boundary type used for when a token may cross multiple parts of the input.
6#[derive(Clone, Debug, Default)]
7pub(crate) enum Cob {
8    #[default]
9    Uninit,
10    Borrowed(&'static str, usize, usize, Loc),
11    Owned(String, Loc),
12}
13
14impl Cob {
15    pub(crate) fn new() -> Self {
16        Self::default()
17    }
18
19    #[inline]
20    pub(crate) fn set(&mut self, str: &'static str, index: usize, loc: Loc) {
21        *self = Self::Borrowed(str, index, index, loc);
22    }
23
24    /// **ASSERT**: the char must match the char starting at the end index of the borrowed string (if applicable).
25    pub(crate) fn add_char(&mut self, c: char) {
26        match *self {
27            Self::Uninit => unreachable!(),
28            Self::Borrowed(str, start, end, loc) if end == str.len() => {
29                let mut string = str[start..].to_owned();
30                string.push(c);
31                *self = Self::Owned(string, loc);
32            }
33            Self::Borrowed(_str, _, ref mut end, _) => {
34                // ASSERT: _str[*end..].starts_with(c)
35                *end += c.len_utf8();
36            }
37            Self::Owned(ref mut string, _) => string.push(c),
38        }
39    }
40
41    pub(crate) fn make_owned(&mut self) {
42        match *self {
43            Self::Uninit => unreachable!(),
44            Self::Borrowed(str, start, end, loc) => {
45                let string = str[start..end].to_owned();
46                *self = Self::Owned(string, loc);
47            }
48            Self::Owned(_, _) => (),
49        }
50    }
51
52    pub(crate) fn take_to_token(&mut self) -> Token {
53        match take(self) {
54            Cob::Uninit => unreachable!(),
55            Cob::Borrowed(str, start, end, loc) => Token::from_static_str(&str[start..end], loc),
56            Cob::Owned(string, loc) => Token::new(&string, loc),
57        }
58    }
59}