1use ktrs_syntax::SyntaxKind;
4
5const WORDS: usize = 8;
6const _: () = assert!((SyntaxKind::DUMMY_HOLDER as usize) < WORDS * 64, "grow TokenSet::WORDS");
7
8#[derive(Clone, Copy, PartialEq, Eq, Hash)]
9pub struct TokenSet([u64; WORDS]);
10
11impl TokenSet {
12 pub const EMPTY: TokenSet = TokenSet([0; WORDS]);
13
14 pub const fn create(kinds: &[SyntaxKind]) -> TokenSet {
16 let mut bits = [0u64; WORDS];
17 let mut i = 0;
18 while i < kinds.len() {
19 let k = kinds[i] as usize;
20 bits[k / 64] |= 1 << (k % 64);
21 i += 1;
22 }
23 TokenSet(bits)
24 }
25
26 pub const fn or_set(sets: &[TokenSet]) -> TokenSet {
28 let mut bits = [0u64; WORDS];
29 let mut s = 0;
30 while s < sets.len() {
31 let mut w = 0;
32 while w < WORDS {
33 bits[w] |= sets[s].0[w];
34 w += 1;
35 }
36 s += 1;
37 }
38 TokenSet(bits)
39 }
40
41 pub const fn and_set(a: TokenSet, b: TokenSet) -> TokenSet {
43 let mut bits = [0u64; WORDS];
44 let mut w = 0;
45 while w < WORDS {
46 bits[w] = a.0[w] & b.0[w];
47 w += 1;
48 }
49 TokenSet(bits)
50 }
51
52 pub const fn and_not(a: TokenSet, b: TokenSet) -> TokenSet {
54 let mut bits = [0u64; WORDS];
55 let mut w = 0;
56 while w < WORDS {
57 bits[w] = a.0[w] & !b.0[w];
58 w += 1;
59 }
60 TokenSet(bits)
61 }
62
63 pub fn contains(self, kind: impl Into<Option<SyntaxKind>>) -> bool {
65 match kind.into() {
66 Some(k) => self.0[k as usize / 64] & (1 << (k as usize % 64)) != 0,
67 None => false,
68 }
69 }
70
71 pub fn intersects(self, other: TokenSet) -> bool {
72 self.0.iter().zip(other.0).any(|(a, b)| a & b != 0)
73 }
74
75 pub fn types(self) -> impl Iterator<Item = SyntaxKind> {
76 (0..WORDS * 64)
77 .filter(move |&i| self.0[i / 64] & (1 << (i % 64)) != 0)
78 .map(|i| SyntaxKind::from_raw(i as u16))
79 }
80}
81
82impl std::fmt::Debug for TokenSet {
83 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84 f.debug_set().entries(self.types()).finish()
85 }
86}