• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Stateful iteration over token trees.
2 //!
3 //! We use this as the source of tokens for parser.
4 use crate::{Leaf, Subtree, TokenTree};
5 
6 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
7 struct EntryId(usize);
8 
9 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
10 struct EntryPtr(
11     /// The index of the buffer containing the entry.
12     EntryId,
13     /// The index of the entry within the buffer.
14     usize,
15 );
16 
17 /// Internal type which is used instead of `TokenTree` to represent a token tree
18 /// within a `TokenBuffer`.
19 #[derive(Debug)]
20 enum Entry<'t, Span> {
21     // Mimicking types from proc-macro.
22     Subtree(Option<&'t TokenTree<Span>>, &'t Subtree<Span>, EntryId),
23     Leaf(&'t TokenTree<Span>),
24     /// End entries contain a pointer to the entry from the containing
25     /// token tree, or [`None`] if this is the outermost level.
26     End(Option<EntryPtr>),
27 }
28 
29 /// A token tree buffer
30 /// The safe version of `syn` [`TokenBuffer`](https://github.com/dtolnay/syn/blob/6533607f91686545cb034d2838beea338d9d0742/src/buffer.rs#L41)
31 #[derive(Debug)]
32 pub struct TokenBuffer<'t, Span> {
33     buffers: Vec<Box<[Entry<'t, Span>]>>,
34 }
35 
36 trait TokenList<'a, Span> {
entries( &self, ) -> (Vec<(usize, (&'a Subtree<Span>, Option<&'a TokenTree<Span>>))>, Vec<Entry<'a, Span>>)37     fn entries(
38         &self,
39     ) -> (Vec<(usize, (&'a Subtree<Span>, Option<&'a TokenTree<Span>>))>, Vec<Entry<'a, Span>>);
40 }
41 
42 impl<'a, Span> TokenList<'a, Span> for &'a [TokenTree<Span>] {
entries( &self, ) -> (Vec<(usize, (&'a Subtree<Span>, Option<&'a TokenTree<Span>>))>, Vec<Entry<'a, Span>>)43     fn entries(
44         &self,
45     ) -> (Vec<(usize, (&'a Subtree<Span>, Option<&'a TokenTree<Span>>))>, Vec<Entry<'a, Span>>)
46     {
47         // Must contain everything in tokens and then the Entry::End
48         let start_capacity = self.len() + 1;
49         let mut entries = Vec::with_capacity(start_capacity);
50         let mut children = vec![];
51         for (idx, tt) in self.iter().enumerate() {
52             match tt {
53                 TokenTree::Leaf(_) => {
54                     entries.push(Entry::Leaf(tt));
55                 }
56                 TokenTree::Subtree(subtree) => {
57                     entries.push(Entry::End(None));
58                     children.push((idx, (subtree, Some(tt))));
59                 }
60             }
61         }
62         (children, entries)
63     }
64 }
65 
66 impl<'a, Span> TokenList<'a, Span> for &'a Subtree<Span> {
entries( &self, ) -> (Vec<(usize, (&'a Subtree<Span>, Option<&'a TokenTree<Span>>))>, Vec<Entry<'a, Span>>)67     fn entries(
68         &self,
69     ) -> (Vec<(usize, (&'a Subtree<Span>, Option<&'a TokenTree<Span>>))>, Vec<Entry<'a, Span>>)
70     {
71         // Must contain everything in tokens and then the Entry::End
72         let mut entries = vec![];
73         let mut children = vec![];
74         entries.push(Entry::End(None));
75         children.push((0usize, (*self, None)));
76         (children, entries)
77     }
78 }
79 
80 impl<'t, Span> TokenBuffer<'t, Span> {
from_tokens(tokens: &'t [TokenTree<Span>]) -> TokenBuffer<'t, Span>81     pub fn from_tokens(tokens: &'t [TokenTree<Span>]) -> TokenBuffer<'t, Span> {
82         Self::new(tokens)
83     }
84 
from_subtree(subtree: &'t Subtree<Span>) -> TokenBuffer<'t, Span>85     pub fn from_subtree(subtree: &'t Subtree<Span>) -> TokenBuffer<'t, Span> {
86         Self::new(subtree)
87     }
88 
new<T: TokenList<'t, Span>>(tokens: T) -> TokenBuffer<'t, Span>89     fn new<T: TokenList<'t, Span>>(tokens: T) -> TokenBuffer<'t, Span> {
90         let mut buffers = vec![];
91         let idx = TokenBuffer::new_inner(tokens, &mut buffers, None);
92         assert_eq!(idx, 0);
93         TokenBuffer { buffers }
94     }
95 
new_inner<T: TokenList<'t, Span>>( tokens: T, buffers: &mut Vec<Box<[Entry<'t, Span>]>>, next: Option<EntryPtr>, ) -> usize96     fn new_inner<T: TokenList<'t, Span>>(
97         tokens: T,
98         buffers: &mut Vec<Box<[Entry<'t, Span>]>>,
99         next: Option<EntryPtr>,
100     ) -> usize {
101         let (children, mut entries) = tokens.entries();
102 
103         entries.push(Entry::End(next));
104         let res = buffers.len();
105         buffers.push(entries.into_boxed_slice());
106 
107         for (child_idx, (subtree, tt)) in children {
108             let idx = TokenBuffer::new_inner(
109                 subtree.token_trees.as_slice(),
110                 buffers,
111                 Some(EntryPtr(EntryId(res), child_idx + 1)),
112             );
113             buffers[res].as_mut()[child_idx] = Entry::Subtree(tt, subtree, EntryId(idx));
114         }
115 
116         res
117     }
118 
119     /// Creates a cursor referencing the first token in the buffer and able to
120     /// traverse until the end of the buffer.
begin(&self) -> Cursor<'_, Span>121     pub fn begin(&self) -> Cursor<'_, Span> {
122         Cursor::create(self, EntryPtr(EntryId(0), 0))
123     }
124 
entry(&self, ptr: &EntryPtr) -> Option<&Entry<'_, Span>>125     fn entry(&self, ptr: &EntryPtr) -> Option<&Entry<'_, Span>> {
126         let id = ptr.0;
127         self.buffers[id.0].get(ptr.1)
128     }
129 }
130 
131 #[derive(Debug)]
132 pub enum TokenTreeRef<'a, Span> {
133     Subtree(&'a Subtree<Span>, Option<&'a TokenTree<Span>>),
134     Leaf(&'a Leaf<Span>, &'a TokenTree<Span>),
135 }
136 
137 impl<'a, Span: Clone> TokenTreeRef<'a, Span> {
cloned(&self) -> TokenTree<Span>138     pub fn cloned(&self) -> TokenTree<Span> {
139         match self {
140             TokenTreeRef::Subtree(subtree, tt) => match tt {
141                 Some(it) => (*it).clone(),
142                 None => (*subtree).clone().into(),
143             },
144             TokenTreeRef::Leaf(_, tt) => (*tt).clone(),
145         }
146     }
147 }
148 
149 /// A safe version of `Cursor` from `syn` crate <https://github.com/dtolnay/syn/blob/6533607f91686545cb034d2838beea338d9d0742/src/buffer.rs#L125>
150 #[derive(Copy, Clone, Debug)]
151 pub struct Cursor<'a, Span> {
152     buffer: &'a TokenBuffer<'a, Span>,
153     ptr: EntryPtr,
154 }
155 
156 impl<'a, Span> PartialEq for Cursor<'a, Span> {
eq(&self, other: &Cursor<'_, Span>) -> bool157     fn eq(&self, other: &Cursor<'_, Span>) -> bool {
158         self.ptr == other.ptr && std::ptr::eq(self.buffer, other.buffer)
159     }
160 }
161 
162 impl<'a, Span> Eq for Cursor<'a, Span> {}
163 
164 impl<'a, Span> Cursor<'a, Span> {
165     /// Check whether it is eof
eof(self) -> bool166     pub fn eof(self) -> bool {
167         matches!(self.buffer.entry(&self.ptr), None | Some(Entry::End(None)))
168     }
169 
170     /// If the cursor is pointing at the end of a subtree, returns
171     /// the parent subtree
end(self) -> Option<&'a Subtree<Span>>172     pub fn end(self) -> Option<&'a Subtree<Span>> {
173         match self.entry() {
174             Some(Entry::End(Some(ptr))) => {
175                 let idx = ptr.1;
176                 if let Some(Entry::Subtree(_, subtree, _)) =
177                     self.buffer.entry(&EntryPtr(ptr.0, idx - 1))
178                 {
179                     return Some(subtree);
180                 }
181                 None
182             }
183             _ => None,
184         }
185     }
186 
entry(&self) -> Option<&'a Entry<'a, Span>>187     fn entry(&self) -> Option<&'a Entry<'a, Span>> {
188         self.buffer.entry(&self.ptr)
189     }
190 
191     /// If the cursor is pointing at a `Subtree`, returns
192     /// a cursor into that subtree
subtree(self) -> Option<Cursor<'a, Span>>193     pub fn subtree(self) -> Option<Cursor<'a, Span>> {
194         match self.entry() {
195             Some(Entry::Subtree(_, _, entry_id)) => {
196                 Some(Cursor::create(self.buffer, EntryPtr(*entry_id, 0)))
197             }
198             _ => None,
199         }
200     }
201 
202     /// If the cursor is pointing at a `TokenTree`, returns it
token_tree(self) -> Option<TokenTreeRef<'a, Span>>203     pub fn token_tree(self) -> Option<TokenTreeRef<'a, Span>> {
204         match self.entry() {
205             Some(Entry::Leaf(tt)) => match tt {
206                 TokenTree::Leaf(leaf) => Some(TokenTreeRef::Leaf(leaf, tt)),
207                 TokenTree::Subtree(subtree) => Some(TokenTreeRef::Subtree(subtree, Some(tt))),
208             },
209             Some(Entry::Subtree(tt, subtree, _)) => Some(TokenTreeRef::Subtree(subtree, *tt)),
210             Some(Entry::End(_)) | None => None,
211         }
212     }
213 
create(buffer: &'a TokenBuffer<'_, Span>, ptr: EntryPtr) -> Cursor<'a, Span>214     fn create(buffer: &'a TokenBuffer<'_, Span>, ptr: EntryPtr) -> Cursor<'a, Span> {
215         Cursor { buffer, ptr }
216     }
217 
218     /// Bump the cursor
bump(self) -> Cursor<'a, Span>219     pub fn bump(self) -> Cursor<'a, Span> {
220         if let Some(Entry::End(exit)) = self.buffer.entry(&self.ptr) {
221             match exit {
222                 Some(exit) => Cursor::create(self.buffer, *exit),
223                 None => self,
224             }
225         } else {
226             Cursor::create(self.buffer, EntryPtr(self.ptr.0, self.ptr.1 + 1))
227         }
228     }
229 
230     /// Bump the cursor, if it is a subtree, returns
231     /// a cursor into that subtree
bump_subtree(self) -> Cursor<'a, Span>232     pub fn bump_subtree(self) -> Cursor<'a, Span> {
233         match self.entry() {
234             Some(&Entry::Subtree(_, _, entry_id)) => {
235                 Cursor::create(self.buffer, EntryPtr(entry_id, 0))
236             }
237             Some(Entry::End(exit)) => match exit {
238                 Some(exit) => Cursor::create(self.buffer, *exit),
239                 None => self,
240             },
241             _ => Cursor::create(self.buffer, EntryPtr(self.ptr.0, self.ptr.1 + 1)),
242         }
243     }
244 
245     /// Check whether it is a top level
is_root(&self) -> bool246     pub fn is_root(&self) -> bool {
247         let entry_id = self.ptr.0;
248         entry_id.0 == 0
249     }
250 }
251