Skip to main content

jrsonnet_rowan_parser/
token_set.rs

1use std::fmt;
2
3use crate::SyntaxKind;
4
5#[derive(Clone, Copy, Default)]
6pub struct SyntaxKindSet(u128);
7
8impl SyntaxKindSet {
9	#[allow(dead_code)]
10	pub const EMPTY: Self = Self(0);
11	pub const ALL: Self = Self(u128::MAX);
12
13	pub const fn new(kinds: &[SyntaxKind]) -> Self {
14		let mut res = 0u128;
15		let mut i = 0;
16		while i < kinds.len() {
17			res |= mask(kinds[i]);
18			i += 1;
19		}
20		Self(res)
21	}
22
23	#[must_use]
24	pub const fn union(self, other: Self) -> Self {
25		Self(self.0 | other.0)
26	}
27	#[must_use]
28	pub const fn with(self, kind: SyntaxKind) -> Self {
29		Self(self.0 | mask(kind))
30	}
31
32	pub fn contains(&self, kind: SyntaxKind) -> bool {
33		if !is_token(kind) {
34			return false;
35		}
36		self.0 & mask(kind) != 0
37	}
38}
39impl fmt::Display for SyntaxKindSet {
40	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41		let mut v = self.0;
42		let mut variants = <Vec<SyntaxKind>>::new();
43		for i in 0..128 {
44			if v & 1 == 1 {
45				variants.push(SyntaxKind::from_raw(i));
46			}
47			v >>= 1;
48			if v == 0 {
49				break;
50			}
51		}
52		for (i, v) in variants.iter().enumerate() {
53			if i == 0 {
54			} else if i == variants.len() - 1 {
55				write!(f, " or ")?;
56			} else {
57				write!(f, ", ")?;
58			}
59			write!(f, "{v:?}")?;
60		}
61		Ok(())
62	}
63}
64impl fmt::Debug for SyntaxKindSet {
65	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66		let mut v = self.0;
67		let mut variants = <Vec<SyntaxKind>>::new();
68		for i in 0..128 {
69			if v & 1 == 1 {
70				variants.push(SyntaxKind::from_raw(i));
71			}
72			v >>= 1;
73			if v == 0 {
74				break;
75			}
76		}
77		f.debug_tuple("SyntaxKindSet").field(&variants).finish()
78	}
79}
80
81const fn mask(kind: SyntaxKind) -> u128 {
82	assert!(kind as u32 <= 128, "mask for not a token kind");
83	1u128 << (kind as u128)
84}
85
86#[macro_export]
87macro_rules! TS {
88	($($tt:tt)*) => {
89		$crate::SyntaxKindSet::new(&[
90			$(
91				$crate::T![$tt]
92			),*
93		])
94	};
95}
96
97#[test]
98fn sanity() {
99	assert!(
100		(SyntaxKind::LEXING_ERROR as u32) < 127,
101		"can't keep KindSet as bitset"
102	);
103}
104fn is_token(kind: SyntaxKind) -> bool {
105	(kind as u32) < 127
106}