Skip to main content

rbx_rsml/
list.rs

1use std::{mem::{self, Discriminant, MaybeUninit}};
2use crate::lexer::{Token, TokenKind};
3
4#[macro_export]
5macro_rules! token_kind_list {
6    ($str:literal, [ $( $name:ident ),* ]) => {
7        &TokenKindList::new_with_stringified([$(
8            (TokenKind::$name, std::mem::discriminant(&TokenKind::$name))
9        ),*], Stringified::Single(String::from($str)))
10    };
11
12    ($( $name:ident ),*) => {
13        &TokenKindList::new([$(
14            (TokenKind::$name, std::mem::discriminant(&TokenKind::$name))
15        ),*])
16    };
17
18    ([ $( $name:ident ),* ]) => {
19        token_kind_list!($( $name ),*)
20    };
21}
22
23#[derive(Debug)]
24pub struct TokenKindList<const N: usize>{
25    items: [(TokenKind, Discriminant<TokenKind>); N],
26    stringified: Option<Stringified>
27}
28
29#[derive(Debug, Clone)]
30pub enum Stringified {
31    Single(String),
32    Many(Vec<String>)
33}
34
35impl Stringified {
36    fn iter(&self) -> Box<dyn Iterator<Item = &String> + '_> {
37        match self {
38            Stringified::Single(item) => Box::new(std::iter::once(item)),
39            Stringified::Many(items) => Box::new(items.iter())
40        }
41    }
42
43    fn extend(self, extend_with: Stringified) -> Stringified {
44        Self::Many(match (self, extend_with) {
45            (Stringified::Single(a), Stringified::Single(b)) => vec![a, b],
46            (Stringified::Many(mut a), Stringified::Many(b)) => {
47                a.extend(b);
48                a
49            },
50            (Stringified::Many(mut a), Stringified::Single(b)) |
51            (Stringified::Single(b), Stringified::Many(mut a)) => {
52                a.push(b);
53                a
54            }
55        })
56    }
57
58}
59
60impl<'a, const N: usize> TokenKindList<N> {
61    pub fn new(items: [(TokenKind, Discriminant<TokenKind>); N]) -> Self {
62        Self {
63            items,
64            stringified: None
65        }
66    }
67
68    pub fn new_with_stringified(
69        items: [(TokenKind, Discriminant<TokenKind>); N],
70        stringified: Stringified
71    ) -> Self {
72        Self {
73            items,
74            stringified: Some(stringified)
75        }
76    }
77
78    pub fn has_token(&self, token: &Token) -> bool {
79        let discriminant = &token.discriminant();
80
81        self.items.iter().any(|x| &x.1 == discriminant)
82    }
83
84    pub fn has_discriminant(&self, discriminant: &Discriminant<TokenKind>) -> bool {
85        self.items.iter().any(|x| &x.1 == discriminant)
86    }
87
88    pub fn to_string(&'a self) -> Option<String> {
89        let stringified = &self.stringified;
90        let items = self.items;
91
92        let mut iter: Box<dyn Iterator<Item = &str>> =
93            if let Some(stringified) = stringified { Box::new(stringified.iter().map(String::as_str)) }
94            else { Box::new(items.iter().map(|x| x.0.name())) };
95
96        let Some(mut current_item) = iter.next() else { return None };
97
98        let mut msg = format!("{}", current_item);
99
100        let Some(next_item) = iter.next() else { return Some(msg) };
101        current_item = next_item;
102
103        loop {
104            let next_item = iter.next();
105            
106            if let Some(next_item) = next_item {
107                let msg_item = format!(", {}", current_item);
108                current_item = next_item;
109                msg += &msg_item;
110
111            } else {
112                let msg_item = format!(" or {}", current_item);
113                msg += &msg_item;
114                break
115            };
116        }
117
118        return Some(msg)
119    }
120
121    pub fn with_stringified(&self, stringified: Stringified) -> Self {
122        Self {
123            items: self.items,
124            stringified: Some(stringified)
125        }
126    }
127
128    pub fn concat<const B: usize>(&self, b: &TokenKindList<B>) -> TokenKindList<{N + B}>
129    where
130        [(); N + B]:
131    {
132        TokenKindList::<{N + B}> {
133            items: array_concat(&self.items, &b.items),
134            stringified: match (&self.stringified, &b.stringified) {
135                (Some(a), Some(b)) => Some(a.clone().extend(b.clone())),
136                (Some(a), None) => Some(a.clone()),
137                (None, Some(b)) => Some(b.clone()),
138                (None, None) => None
139            }
140        }
141    }
142}
143
144fn array_concat<T, const AN: usize, const BN: usize>(a: &[T; AN], b: &[T; BN]) -> [T; AN + BN]
145where T: Copy, [(); AN + BN]: {
146    let mut output: [MaybeUninit<T>; AN + BN] =
147        unsafe { MaybeUninit::uninit().assume_init() };
148
149    for i in 0..AN {
150        output[i] = MaybeUninit::new(a[i]);
151    }
152
153    for i in 0..BN {
154        output[AN + i] = MaybeUninit::new(b[i]);
155    }
156
157    unsafe {
158        mem::transmute_copy::<_, [T; AN + BN]>(&output)
159    }
160}