1use crate::Kind;
2
3#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
17pub struct KindSet(u64);
18
19impl KindSet {
20 pub const NONE: KindSet = KindSet::new(&[]);
22
23 pub const TRIVIA: KindSet = KindSet::new(&[Kind::Whitespace, Kind::Comment]);
25
26 pub const WHITESPACE: KindSet = KindSet::new(&[Kind::Whitespace]);
29
30 pub const COMMENTS: KindSet = KindSet::new(&[Kind::Comment]);
33
34 pub const WHITESPACE_OR_SEMICOLON: KindSet = KindSet::new(&[Kind::Whitespace, Kind::Semicolon]);
36
37 pub const RIGHT_CURLY_OR_SEMICOLON: KindSet = KindSet::new(&[Kind::RightCurly, Kind::Semicolon]);
40
41 pub const LEFT_CURLY_OR_SEMICOLON: KindSet = KindSet::new(&[Kind::LeftCurly, Kind::Semicolon]);
44
45 pub const LEFT_CURLY_RIGHT_PAREN_OR_SEMICOLON: KindSet =
48 KindSet::new(&[Kind::LeftCurly, Kind::RightParen, Kind::Semicolon]);
49
50 pub const LEFT_CURLY_RIGHT_PAREN_COMMA_OR_SEMICOLON: KindSet =
53 KindSet::new(&[Kind::LeftCurly, Kind::RightParen, Kind::Comma, Kind::Semicolon]);
54
55 pub const IDENT_LIKE: KindSet = KindSet::new(&[Kind::Ident, Kind::AtKeyword, Kind::Function, Kind::Hash]);
57
58 pub const DELIM_LIKE: KindSet = KindSet::new(&[
60 Kind::Delim,
61 Kind::Colon,
62 Kind::Semicolon,
63 Kind::Comma,
64 Kind::LeftSquare,
65 Kind::RightSquare,
66 Kind::LeftParen,
67 Kind::RightParen,
68 Kind::LeftCurly,
69 Kind::RightCurly,
70 ]);
71
72 pub const ANY: KindSet = KindSet(u64::MAX);
74
75 pub const fn new(kinds: &[Kind]) -> Self {
79 let mut u = 0;
80 let mut i = 0;
81 let len = kinds.len();
82 while i < len {
83 u |= 1 << (kinds[i] as u8 & 0b111111);
84 i += 1;
85 }
86 Self(u)
87 }
88
89 pub const fn add(&self, kind: Kind) -> Self {
93 Self(self.0 | (1 << (kind as u8 & 0b111111)))
94 }
95
96 pub fn contains(&self, kind: Kind) -> bool {
98 self.0 & (1 << (kind as u8 & 0b111111)) != 0
99 }
100
101 pub(crate) const fn contains_bits(&self, kind_bits: u8) -> bool {
102 self.0 & (1 << (kind_bits & 0b111111)) != 0
103 }
104}
105
106#[test]
107fn test_kindset_contains() {
108 let set = KindSet::new(&[Kind::Eof, Kind::Whitespace, Kind::Comment]);
109 assert!(set.contains(Kind::Eof));
110 assert!(set.contains(Kind::Whitespace));
111 assert!(set.contains(Kind::Comment));
112 assert!(!set.contains(Kind::String));
113 assert!(!set.contains(Kind::Url));
114
115 let set = KindSet::new(&[Kind::LeftCurly, Kind::LeftSquare, Kind::LeftParen]);
116
117 assert!(set.contains(Kind::LeftCurly));
118 assert!(!set.contains(Kind::RightCurly));
119 assert!(set.contains(Kind::LeftSquare));
120 assert!(!set.contains(Kind::RightSquare));
121 assert!(set.contains(Kind::LeftParen));
122 assert!(!set.contains(Kind::RightParen));
123 assert!(!set.contains(Kind::Ident));
124
125 assert!(KindSet::COMMENTS.contains(Kind::Comment));
126 assert!(!KindSet::COMMENTS.contains(Kind::Delim));
127}