Skip to content

Commit 59b1a16

Browse files
committed
internal: update TokenSet implementation
1 parent 2532c27 commit 59b1a16

File tree

3 files changed

+36
-35
lines changed

3 files changed

+36
-35
lines changed

crates/parser/src/token_set.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ pub(crate) use self::generated::TokenSet;
88
#[test]
99
fn token_set_works_for_tokens() {
1010
use crate::SyntaxKind::*;
11-
let ts = TokenSet::new(&[EOF, SHEBANG, __LAST]);
11+
let ts = TokenSet::new(&[EOF, SHEBANG]);
1212
assert!(ts.contains(EOF));
1313
assert!(ts.contains(SHEBANG));
14-
assert!(ts.contains(__LAST));
1514
assert!(!ts.contains(PLUS));
1615
}
Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,37 @@
11
//! Generated by `sourcegen_ast`, do not edit by hand.
22
33
use crate::SyntaxKind;
4-
#[doc = r" A bit-set of `SyntaxKind`s"]
4+
#[doc = r" A bit-set of token `SyntaxKind`s"]
55
#[derive(Clone, Copy)]
6-
pub(crate) struct TokenSet([u16; 17usize]);
6+
pub(crate) struct TokenSet([u64; 2usize]);
7+
const LAST_TOKEN_DISCRIMINANT: usize = 121usize;
78
impl TokenSet {
8-
pub(crate) const EMPTY: TokenSet = TokenSet([0; 17usize]);
9+
pub(crate) const EMPTY: TokenSet = TokenSet([0; 2usize]);
910
pub(crate) const fn new(kinds: &[SyntaxKind]) -> TokenSet {
10-
let mut res = [0; 17usize];
11+
let mut res = [0; 2usize];
1112
let mut i = 0;
1213
while i < kinds.len() {
1314
let kind = kinds[i];
14-
let idx = kind as usize / 16usize;
15+
debug_assert!(
16+
(kind as usize) <= LAST_TOKEN_DISCRIMINANT,
17+
"Expected a token `SyntaxKind`"
18+
);
19+
let idx = kind as usize / 64usize;
1520
res[idx] |= mask(kind);
1621
i += 1;
1722
}
1823
TokenSet(res)
1924
}
2025
pub(crate) const fn union(self, other: TokenSet) -> TokenSet {
21-
TokenSet([
22-
self.0[0usize] | other.0[0usize],
23-
self.0[1usize] | other.0[1usize],
24-
self.0[2usize] | other.0[2usize],
25-
self.0[3usize] | other.0[3usize],
26-
self.0[4usize] | other.0[4usize],
27-
self.0[5usize] | other.0[5usize],
28-
self.0[6usize] | other.0[6usize],
29-
self.0[7usize] | other.0[7usize],
30-
self.0[8usize] | other.0[8usize],
31-
self.0[9usize] | other.0[9usize],
32-
self.0[10usize] | other.0[10usize],
33-
self.0[11usize] | other.0[11usize],
34-
self.0[12usize] | other.0[12usize],
35-
self.0[13usize] | other.0[13usize],
36-
self.0[14usize] | other.0[14usize],
37-
self.0[15usize] | other.0[15usize],
38-
self.0[16usize] | other.0[16usize],
39-
])
26+
TokenSet([self.0[0usize] | other.0[0usize], self.0[1usize] | other.0[1usize]])
4027
}
4128
pub(crate) const fn contains(&self, kind: SyntaxKind) -> bool {
42-
let idx = kind as usize / 16usize;
29+
debug_assert!((kind as usize) <= LAST_TOKEN_DISCRIMINANT, "Expected a token `SyntaxKind`");
30+
let idx = kind as usize / 64usize;
4331
self.0[idx] & mask(kind) != 0
4432
}
4533
}
46-
const fn mask(kind: SyntaxKind) -> u16 { 1 << (kind as usize % 16usize) }
34+
const fn mask(kind: SyntaxKind) -> u64 {
35+
debug_assert!((kind as usize) <= LAST_TOKEN_DISCRIMINANT, "Expected a token `SyntaxKind`");
36+
1 << (kind as usize % 64usize)
37+
}

xtask/src/codegen/grammar.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -466,28 +466,36 @@ fn generate_syntax_kinds(grammar: KindsSrc<'_>) -> String {
466466
}
467467

468468
fn generate_token_set(grammar: KindsSrc<'_>) -> String {
469-
// +3 for technical syntax kinds (i.e. `TOMBSTONE`, `EOF` and `__LAST`).
470-
let n_syntax_kinds = 3
469+
// +2 for `TOMBSTONE` and `EOF`.
470+
let n_token_kinds = 2
471471
+ grammar.punct.len()
472472
+ grammar.keywords.len()
473473
+ grammar.contextual_keywords.len()
474474
+ grammar.literals.len()
475-
+ grammar.tokens.len()
476-
+ grammar.nodes.len();
475+
+ grammar.tokens.len();
477476

478-
let base_type_size = 16usize;
477+
let base_type_size = 64usize;
479478
let base_type = format_ident!("u{}", base_type_size);
480-
let n_chunks = (n_syntax_kinds as f32 / base_type_size as f32).ceil() as usize;
479+
let n_chunks = (n_token_kinds as f32 / base_type_size as f32).ceil() as usize;
480+
481+
// 0 and 1 discriminants are assigned to `TOMBSTONE` and `EOF`.
482+
let last_token_discriminant = n_token_kinds - 1;
481483

482484
let union_items = (0..n_chunks).map(|idx| quote! { self.0[#idx] | other.0[#idx] });
483485

486+
let assert_token_kind = quote! {
487+
debug_assert!((kind as usize) <= LAST_TOKEN_DISCRIMINANT, "Expected a token `SyntaxKind`");
488+
};
489+
484490
let ast = quote! {
485491
use crate::SyntaxKind;
486492

487-
/// A bit-set of `SyntaxKind`s
493+
/// A bit-set of token `SyntaxKind`s
488494
#[derive(Clone, Copy)]
489495
pub(crate) struct TokenSet([#base_type; #n_chunks]);
490496

497+
const LAST_TOKEN_DISCRIMINANT: usize = #last_token_discriminant;
498+
491499
impl TokenSet {
492500
pub(crate) const EMPTY: TokenSet = TokenSet([0; #n_chunks]);
493501

@@ -496,6 +504,7 @@ fn generate_token_set(grammar: KindsSrc<'_>) -> String {
496504
let mut i = 0;
497505
while i < kinds.len() {
498506
let kind = kinds[i];
507+
#assert_token_kind
499508
let idx = kind as usize / #base_type_size;
500509
res[idx] |= mask(kind);
501510
i += 1;
@@ -510,12 +519,14 @@ fn generate_token_set(grammar: KindsSrc<'_>) -> String {
510519
}
511520

512521
pub(crate) const fn contains(&self, kind: SyntaxKind) -> bool {
522+
#assert_token_kind
513523
let idx = kind as usize / #base_type_size;
514524
self.0[idx] & mask(kind) != 0
515525
}
516526
}
517527

518528
const fn mask(kind: SyntaxKind) -> #base_type {
529+
#assert_token_kind
519530
1 << (kind as usize % #base_type_size)
520531
}
521532
};

0 commit comments

Comments
 (0)