]> git.lizzy.rs Git - rust.git/blob - crates/parser/src/tokens.rs
prettyfy
[rust.git] / crates / parser / src / tokens.rs
1 //! Input for the parser -- a sequence of tokens.
2 //!
3 //! As of now, parser doesn't have access to the *text* of the tokens, and makes
4 //! decisions based solely on their classification.
5
6 use crate::SyntaxKind;
7
8 #[allow(non_camel_case_types)]
9 type bits = u64;
10
11 /// Main input to the parser.
12 ///
13 /// A sequence of tokens represented internally as a struct of arrays.
14 #[derive(Default)]
15 pub struct Tokens {
16     kind: Vec<SyntaxKind>,
17     joint: Vec<bits>,
18     contextual_kind: Vec<SyntaxKind>,
19 }
20
21 /// `pub` impl used by callers to create `Tokens`.
22 impl Tokens {
23     #[inline]
24     pub fn push(&mut self, kind: SyntaxKind) {
25         self.push_impl(kind, SyntaxKind::EOF)
26     }
27     #[inline]
28     pub fn push_ident(&mut self, contextual_kind: SyntaxKind) {
29         self.push_impl(SyntaxKind::IDENT, contextual_kind)
30     }
31     /// Sets jointness for the last token we've pushed.
32     ///
33     /// This is a separate API rather than an argument to the `push` to make it
34     /// convenient both for textual and mbe tokens. With text, you know whether
35     /// the *previous* token was joint, with mbe, you know whether the *current*
36     /// one is joint. This API allows for styles of usage:
37     ///
38     /// ```
39     /// // In text:
40     /// tokens.was_joint(prev_joint);
41     /// tokens.push(curr);
42     ///
43     /// // In MBE:
44     /// token.push(curr);
45     /// tokens.push(curr_joint)
46     /// ```
47     #[inline]
48     pub fn was_joint(&mut self) {
49         let n = self.len() - 1;
50         let (idx, b_idx) = self.bit_index(n);
51         self.joint[idx] |= 1 << b_idx;
52     }
53     #[inline]
54     fn push_impl(&mut self, kind: SyntaxKind, contextual_kind: SyntaxKind) {
55         let idx = self.len();
56         if idx % (bits::BITS as usize) == 0 {
57             self.joint.push(0);
58         }
59         self.kind.push(kind);
60         self.contextual_kind.push(contextual_kind);
61     }
62 }
63
64 /// pub(crate) impl used by the parser to consume `Tokens`.
65 impl Tokens {
66     pub(crate) fn kind(&self, idx: usize) -> SyntaxKind {
67         self.kind.get(idx).copied().unwrap_or(SyntaxKind::EOF)
68     }
69     pub(crate) fn contextual_kind(&self, idx: usize) -> SyntaxKind {
70         self.contextual_kind.get(idx).copied().unwrap_or(SyntaxKind::EOF)
71     }
72     pub(crate) fn is_joint(&self, n: usize) -> bool {
73         let (idx, b_idx) = self.bit_index(n);
74         self.joint[idx] & 1 << b_idx != 0
75     }
76 }
77
78 impl Tokens {
79     fn bit_index(&self, n: usize) -> (usize, usize) {
80         let idx = n / (bits::BITS as usize);
81         let b_idx = n % (bits::BITS as usize);
82         (idx, b_idx)
83     }
84     fn len(&self) -> usize {
85         self.kind.len()
86     }
87 }