diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-05-23 15:31:26 +0100 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-05-23 15:31:26 +0100 |
commit | ef00b5af1c7a7a7cac685eff661a10252825d84a (patch) | |
tree | b48cf769d66b2c9366c5488cfa254520730a98a3 /crates | |
parent | eef24bddc96ddcdbcad5fddb9c0cf0e2ccad7681 (diff) | |
parent | 63b67134fdbfedfeab655ac9ff03730575fdf475 (diff) |
Merge #1312
1312: Introduce TokenBuffer r=matklad a=edwin0cheng
As discussed in Zulip, this PR Introduce `TokenBuffer` , a safe version of `syn` crate `TokenBuffer` which support cursor based traversal of `tt::TokenTree`. This is the basis of incoming refactoring of `TokenSource` iterator based API.
This PR do the following things:
* Add TokenBuffer in `ra_tt` crate.
* Try to use this new API to refactor the `SubtreeSource` to prove it usage.
Co-authored-by: Edwin Cheng <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_mbe/src/subtree_parser.rs | 6 | ||||
-rw-r--r-- | crates/ra_mbe/src/subtree_source.rs | 262 | ||||
-rw-r--r-- | crates/ra_mbe/src/syntax_bridge.rs | 21 | ||||
-rw-r--r-- | crates/ra_tt/src/buffer.rs | 169 | ||||
-rw-r--r-- | crates/ra_tt/src/lib.rs | 2 |
5 files changed, 259 insertions, 201 deletions
diff --git a/crates/ra_mbe/src/subtree_parser.rs b/crates/ra_mbe/src/subtree_parser.rs index f07107414..709b87a38 100644 --- a/crates/ra_mbe/src/subtree_parser.rs +++ b/crates/ra_mbe/src/subtree_parser.rs | |||
@@ -2,6 +2,7 @@ use crate::subtree_source::SubtreeTokenSource; | |||
2 | 2 | ||
3 | use ra_parser::{TokenSource, TreeSink}; | 3 | use ra_parser::{TokenSource, TreeSink}; |
4 | use ra_syntax::{SyntaxKind}; | 4 | use ra_syntax::{SyntaxKind}; |
5 | use tt::buffer::TokenBuffer; | ||
5 | 6 | ||
6 | struct OffsetTokenSink { | 7 | struct OffsetTokenSink { |
7 | token_pos: usize, | 8 | token_pos: usize, |
@@ -69,7 +70,8 @@ impl<'a> Parser<'a> { | |||
69 | where | 70 | where |
70 | F: FnOnce(&dyn TokenSource, &mut dyn TreeSink), | 71 | F: FnOnce(&dyn TokenSource, &mut dyn TreeSink), |
71 | { | 72 | { |
72 | let mut src = SubtreeTokenSource::new(&self.subtree.token_trees[*self.cur_pos..]); | 73 | let buffer = TokenBuffer::new(&self.subtree.token_trees[*self.cur_pos..]); |
74 | let mut src = SubtreeTokenSource::new(&buffer); | ||
73 | let mut sink = OffsetTokenSink { token_pos: 0, error: false }; | 75 | let mut sink = OffsetTokenSink { token_pos: 0, error: false }; |
74 | 76 | ||
75 | f(&src, &mut sink); | 77 | f(&src, &mut sink); |
@@ -85,7 +87,7 @@ impl<'a> Parser<'a> { | |||
85 | let res = src.bump_n(parsed_token); | 87 | let res = src.bump_n(parsed_token); |
86 | *self.cur_pos += res.len(); | 88 | *self.cur_pos += res.len(); |
87 | 89 | ||
88 | let res: Vec<_> = res.into_iter().cloned().collect(); | 90 | let res: Vec<_> = res.into_iter().collect(); |
89 | 91 | ||
90 | match res.len() { | 92 | match res.len() { |
91 | 0 => None, | 93 | 0 => None, |
diff --git a/crates/ra_mbe/src/subtree_source.rs b/crates/ra_mbe/src/subtree_source.rs index c938acf64..972af4a7c 100644 --- a/crates/ra_mbe/src/subtree_source.rs +++ b/crates/ra_mbe/src/subtree_source.rs | |||
@@ -1,50 +1,10 @@ | |||
1 | use ra_parser::{TokenSource}; | 1 | use ra_parser::{TokenSource}; |
2 | use ra_syntax::{classify_literal, SmolStr, SyntaxKind, SyntaxKind::*, T}; | 2 | use ra_syntax::{classify_literal, SmolStr, SyntaxKind, SyntaxKind::*, T}; |
3 | use std::cell::{RefCell}; | 3 | use std::cell::{RefCell, Cell}; |
4 | use tt::buffer::{TokenBuffer, Cursor}; | ||
4 | 5 | ||
5 | // A Sequece of Token, | 6 | pub(crate) trait Querier { |
6 | #[derive(Debug, Clone, Eq, PartialEq)] | 7 | fn token(&self, uidx: usize) -> (SyntaxKind, SmolStr, bool); |
7 | pub(super) enum TokenSeq<'a> { | ||
8 | Subtree(&'a tt::Subtree), | ||
9 | Seq(&'a [tt::TokenTree]), | ||
10 | } | ||
11 | |||
12 | impl<'a> From<&'a tt::Subtree> for TokenSeq<'a> { | ||
13 | fn from(s: &'a tt::Subtree) -> TokenSeq<'a> { | ||
14 | TokenSeq::Subtree(s) | ||
15 | } | ||
16 | } | ||
17 | |||
18 | impl<'a> From<&'a [tt::TokenTree]> for TokenSeq<'a> { | ||
19 | fn from(s: &'a [tt::TokenTree]) -> TokenSeq<'a> { | ||
20 | TokenSeq::Seq(s) | ||
21 | } | ||
22 | } | ||
23 | |||
24 | #[derive(Debug)] | ||
25 | enum DelimToken<'a> { | ||
26 | Delim(&'a tt::Delimiter, bool), | ||
27 | Token(&'a tt::TokenTree), | ||
28 | End, | ||
29 | } | ||
30 | |||
31 | impl<'a> TokenSeq<'a> { | ||
32 | fn get(&self, pos: usize) -> DelimToken<'a> { | ||
33 | match self { | ||
34 | TokenSeq::Subtree(subtree) => { | ||
35 | let len = subtree.token_trees.len() + 2; | ||
36 | match pos { | ||
37 | p if p >= len => DelimToken::End, | ||
38 | p if p == len - 1 => DelimToken::Delim(&subtree.delimiter, true), | ||
39 | 0 => DelimToken::Delim(&subtree.delimiter, false), | ||
40 | p => DelimToken::Token(&subtree.token_trees[p - 1]), | ||
41 | } | ||
42 | } | ||
43 | TokenSeq::Seq(tokens) => { | ||
44 | tokens.get(pos).map(DelimToken::Token).unwrap_or(DelimToken::End) | ||
45 | } | ||
46 | } | ||
47 | } | ||
48 | } | 8 | } |
49 | 9 | ||
50 | #[derive(Debug, Clone, Eq, PartialEq)] | 10 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -54,183 +14,101 @@ struct TtToken { | |||
54 | pub text: SmolStr, | 14 | pub text: SmolStr, |
55 | } | 15 | } |
56 | 16 | ||
57 | #[derive(Debug, Clone, Eq, PartialEq)] | ||
58 | enum WalkCursor { | ||
59 | Token(usize, TtToken), | ||
60 | Eof, | ||
61 | } | ||
62 | |||
63 | #[derive(Debug)] | ||
64 | struct SubTreeWalker<'a> { | ||
65 | pos: usize, | ||
66 | stack: Vec<(TokenSeq<'a>, usize)>, | ||
67 | cursor: WalkCursor, | ||
68 | ts: TokenSeq<'a>, | ||
69 | } | ||
70 | |||
71 | impl<'a> SubTreeWalker<'a> { | ||
72 | fn new(ts: TokenSeq<'a>) -> SubTreeWalker { | ||
73 | let mut res = SubTreeWalker { pos: 0, stack: vec![], cursor: WalkCursor::Eof, ts }; | ||
74 | |||
75 | res.reset(); | ||
76 | res | ||
77 | } | ||
78 | |||
79 | fn is_eof(&self) -> bool { | ||
80 | self.cursor == WalkCursor::Eof | ||
81 | } | ||
82 | |||
83 | fn reset(&mut self) { | ||
84 | self.pos = 0; | ||
85 | self.stack = vec![]; | ||
86 | |||
87 | self.cursor = match self.ts.get(0) { | ||
88 | DelimToken::Token(token) => match token { | ||
89 | tt::TokenTree::Subtree(subtree) => { | ||
90 | let ts = TokenSeq::from(subtree); | ||
91 | self.stack.push((ts, 0)); | ||
92 | WalkCursor::Token(0, convert_delim(subtree.delimiter, false)) | ||
93 | } | ||
94 | tt::TokenTree::Leaf(leaf) => WalkCursor::Token(0, convert_leaf(leaf)), | ||
95 | }, | ||
96 | DelimToken::Delim(delim, is_end) => { | ||
97 | assert!(!is_end); | ||
98 | WalkCursor::Token(0, convert_delim(*delim, false)) | ||
99 | } | ||
100 | DelimToken::End => WalkCursor::Eof, | ||
101 | } | ||
102 | } | ||
103 | |||
104 | fn current(&self) -> Option<&TtToken> { | ||
105 | match &self.cursor { | ||
106 | WalkCursor::Token(_, t) => Some(t), | ||
107 | WalkCursor::Eof => None, | ||
108 | } | ||
109 | } | ||
110 | |||
111 | fn top(&self) -> &TokenSeq { | ||
112 | self.stack.last().map(|(t, _)| t).unwrap_or(&self.ts) | ||
113 | } | ||
114 | |||
115 | /// Move cursor forward by 1 step | ||
116 | fn forward(&mut self) { | ||
117 | if self.is_eof() { | ||
118 | return; | ||
119 | } | ||
120 | self.pos += 1; | ||
121 | |||
122 | if let WalkCursor::Token(u, _) = self.cursor { | ||
123 | self.cursor = self.walk_token(u) | ||
124 | } | ||
125 | } | ||
126 | |||
127 | /// Traversal child token | ||
128 | fn walk_token(&mut self, pos: usize) -> WalkCursor { | ||
129 | let top = self.stack.last().map(|(t, _)| t).unwrap_or(&self.ts); | ||
130 | let pos = pos + 1; | ||
131 | |||
132 | match top.get(pos) { | ||
133 | DelimToken::Token(token) => match token { | ||
134 | tt::TokenTree::Subtree(subtree) => { | ||
135 | let ts = TokenSeq::from(subtree); | ||
136 | self.stack.push((ts, pos)); | ||
137 | WalkCursor::Token(0, convert_delim(subtree.delimiter, false)) | ||
138 | } | ||
139 | tt::TokenTree::Leaf(leaf) => WalkCursor::Token(pos, convert_leaf(leaf)), | ||
140 | }, | ||
141 | DelimToken::Delim(delim, is_end) => { | ||
142 | WalkCursor::Token(pos, convert_delim(*delim, is_end)) | ||
143 | } | ||
144 | DelimToken::End => { | ||
145 | // it is the top level | ||
146 | if let Some((_, last_idx)) = self.stack.pop() { | ||
147 | self.walk_token(last_idx) | ||
148 | } else { | ||
149 | WalkCursor::Eof | ||
150 | } | ||
151 | } | ||
152 | } | ||
153 | } | ||
154 | } | ||
155 | |||
156 | pub(crate) trait Querier { | ||
157 | fn token(&self, uidx: usize) -> (SyntaxKind, SmolStr, bool); | ||
158 | } | ||
159 | |||
160 | // A wrapper class for ref cell | 17 | // A wrapper class for ref cell |
161 | #[derive(Debug)] | 18 | #[derive(Debug)] |
162 | pub(crate) struct WalkerOwner<'a> { | 19 | pub(crate) struct SubtreeWalk<'a> { |
163 | walker: RefCell<SubTreeWalker<'a>>, | 20 | start: Cursor<'a>, |
21 | cursor: Cell<Cursor<'a>>, | ||
164 | cached: RefCell<Vec<Option<TtToken>>>, | 22 | cached: RefCell<Vec<Option<TtToken>>>, |
165 | } | 23 | } |
166 | 24 | ||
167 | impl<'a> WalkerOwner<'a> { | 25 | impl<'a> SubtreeWalk<'a> { |
168 | fn new<I: Into<TokenSeq<'a>>>(ts: I) -> Self { | 26 | fn new(cursor: Cursor<'a>) -> Self { |
169 | WalkerOwner { | 27 | SubtreeWalk { |
170 | walker: RefCell::new(SubTreeWalker::new(ts.into())), | 28 | start: cursor, |
29 | cursor: Cell::new(cursor), | ||
171 | cached: RefCell::new(Vec::with_capacity(10)), | 30 | cached: RefCell::new(Vec::with_capacity(10)), |
172 | } | 31 | } |
173 | } | 32 | } |
174 | 33 | ||
175 | fn get<'b>(&self, pos: usize) -> Option<TtToken> { | 34 | fn get(&self, pos: usize) -> Option<TtToken> { |
176 | let mut cached = self.cached.borrow_mut(); | 35 | let mut cached = self.cached.borrow_mut(); |
177 | if pos < cached.len() { | 36 | if pos < cached.len() { |
178 | return cached[pos].clone(); | 37 | return cached[pos].clone(); |
179 | } | 38 | } |
180 | 39 | ||
181 | while pos >= cached.len() { | 40 | while pos >= cached.len() { |
182 | self.set_pos(cached.len()); | 41 | let cursor = self.cursor.get(); |
183 | let walker = self.walker.borrow(); | 42 | if cursor.eof() { |
184 | cached.push(walker.current().cloned()); | 43 | cached.push(None); |
44 | continue; | ||
45 | } | ||
46 | |||
47 | match cursor.token_tree() { | ||
48 | Some(tt::TokenTree::Leaf(leaf)) => { | ||
49 | cached.push(Some(convert_leaf(&leaf))); | ||
50 | self.cursor.set(cursor.bump()); | ||
51 | } | ||
52 | Some(tt::TokenTree::Subtree(subtree)) => { | ||
53 | self.cursor.set(cursor.subtree().unwrap()); | ||
54 | cached.push(Some(convert_delim(subtree.delimiter, false))); | ||
55 | } | ||
56 | None => { | ||
57 | if let Some(subtree) = cursor.end() { | ||
58 | cached.push(Some(convert_delim(subtree.delimiter, true))); | ||
59 | self.cursor.set(cursor.bump()); | ||
60 | } | ||
61 | } | ||
62 | } | ||
185 | } | 63 | } |
186 | 64 | ||
187 | return cached[pos].clone(); | 65 | return cached[pos].clone(); |
188 | } | 66 | } |
189 | 67 | ||
190 | fn set_pos(&self, pos: usize) { | 68 | fn collect_token_trees(&mut self, n: usize) -> Vec<tt::TokenTree> { |
191 | let mut walker = self.walker.borrow_mut(); | 69 | let mut res = vec![]; |
192 | assert!(walker.pos <= pos); | ||
193 | 70 | ||
194 | while pos > walker.pos && !walker.is_eof() { | 71 | let mut pos = 0; |
195 | walker.forward(); | 72 | let mut cursor = self.start; |
196 | } | 73 | let mut level = 0; |
197 | } | ||
198 | 74 | ||
199 | fn collect_token_trees(&mut self, n: usize) -> Vec<&tt::TokenTree> { | 75 | while pos < n { |
200 | let mut res = vec![]; | 76 | if cursor.eof() { |
201 | let mut walker = self.walker.borrow_mut(); | 77 | break; |
202 | walker.reset(); | 78 | } |
203 | 79 | ||
204 | while walker.pos < n { | 80 | match cursor.token_tree() { |
205 | if let WalkCursor::Token(u, _) = &walker.cursor { | 81 | Some(tt::TokenTree::Leaf(leaf)) => { |
206 | // We only collect the topmost child | 82 | if level == 0 { |
207 | if walker.stack.len() == 0 { | 83 | res.push(leaf.into()); |
208 | if let DelimToken::Token(token) = walker.ts.get(*u) { | ||
209 | res.push(token); | ||
210 | } | 84 | } |
85 | cursor = cursor.bump(); | ||
86 | pos += 1; | ||
211 | } | 87 | } |
212 | // Check whether the second level is a subtree | 88 | Some(tt::TokenTree::Subtree(subtree)) => { |
213 | // if so, collect its parent which is topmost child | 89 | if level == 0 { |
214 | else if walker.stack.len() == 1 { | 90 | res.push(subtree.into()); |
215 | if let DelimToken::Delim(_, is_end) = walker.top().get(*u) { | ||
216 | if !is_end { | ||
217 | let (_, last_idx) = &walker.stack[0]; | ||
218 | if let DelimToken::Token(token) = walker.ts.get(*last_idx) { | ||
219 | res.push(token); | ||
220 | } | ||
221 | } | ||
222 | } | 91 | } |
92 | pos += 1; | ||
93 | level += 1; | ||
94 | cursor = cursor.subtree().unwrap(); | ||
223 | } | 95 | } |
224 | } | ||
225 | 96 | ||
226 | walker.forward(); | 97 | None => { |
98 | if let Some(_) = cursor.end() { | ||
99 | level -= 1; | ||
100 | pos += 1; | ||
101 | cursor = cursor.bump(); | ||
102 | } | ||
103 | } | ||
104 | } | ||
227 | } | 105 | } |
228 | 106 | ||
229 | res | 107 | res |
230 | } | 108 | } |
231 | } | 109 | } |
232 | 110 | ||
233 | impl<'a> Querier for WalkerOwner<'a> { | 111 | impl<'a> Querier for SubtreeWalk<'a> { |
234 | fn token(&self, uidx: usize) -> (SyntaxKind, SmolStr, bool) { | 112 | fn token(&self, uidx: usize) -> (SyntaxKind, SmolStr, bool) { |
235 | self.get(uidx) | 113 | self.get(uidx) |
236 | .map(|tkn| (tkn.kind, tkn.text, tkn.is_joint_to_next)) | 114 | .map(|tkn| (tkn.kind, tkn.text, tkn.is_joint_to_next)) |
@@ -239,22 +117,22 @@ impl<'a> Querier for WalkerOwner<'a> { | |||
239 | } | 117 | } |
240 | 118 | ||
241 | pub(crate) struct SubtreeTokenSource<'a> { | 119 | pub(crate) struct SubtreeTokenSource<'a> { |
242 | walker: WalkerOwner<'a>, | 120 | walker: SubtreeWalk<'a>, |
243 | } | 121 | } |
244 | 122 | ||
245 | impl<'a> SubtreeTokenSource<'a> { | 123 | impl<'a> SubtreeTokenSource<'a> { |
246 | pub fn new<I: Into<TokenSeq<'a>>>(ts: I) -> SubtreeTokenSource<'a> { | 124 | pub fn new(buffer: &'a TokenBuffer) -> SubtreeTokenSource<'a> { |
247 | SubtreeTokenSource { walker: WalkerOwner::new(ts) } | 125 | SubtreeTokenSource { walker: SubtreeWalk::new(buffer.begin()) } |
248 | } | 126 | } |
249 | 127 | ||
250 | pub fn querier<'b>(&'a self) -> &'b WalkerOwner<'a> | 128 | pub fn querier<'b>(&'a self) -> &'b SubtreeWalk<'a> |
251 | where | 129 | where |
252 | 'a: 'b, | 130 | 'a: 'b, |
253 | { | 131 | { |
254 | &self.walker | 132 | &self.walker |
255 | } | 133 | } |
256 | 134 | ||
257 | pub(crate) fn bump_n(&mut self, parsed_tokens: usize) -> Vec<&tt::TokenTree> { | 135 | pub(crate) fn bump_n(&mut self, parsed_tokens: usize) -> Vec<tt::TokenTree> { |
258 | let res = self.walker.collect_token_trees(parsed_tokens); | 136 | let res = self.walker.collect_token_trees(parsed_tokens); |
259 | res | 137 | res |
260 | } | 138 | } |
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index d8e344557..0a75305b4 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs | |||
@@ -47,7 +47,8 @@ pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> Option<(tt::Subtree, Toke | |||
47 | 47 | ||
48 | /// Parses the token tree (result of macro expansion) to an expression | 48 | /// Parses the token tree (result of macro expansion) to an expression |
49 | pub fn token_tree_to_expr(tt: &tt::Subtree) -> Result<TreeArc<ast::Expr>, ExpandError> { | 49 | pub fn token_tree_to_expr(tt: &tt::Subtree) -> Result<TreeArc<ast::Expr>, ExpandError> { |
50 | let token_source = SubtreeTokenSource::new(tt); | 50 | let buffer = tt::buffer::TokenBuffer::new(&[tt.clone().into()]); |
51 | let token_source = SubtreeTokenSource::new(&buffer); | ||
51 | let mut tree_sink = TtTreeSink::new(token_source.querier()); | 52 | let mut tree_sink = TtTreeSink::new(token_source.querier()); |
52 | ra_parser::parse_expr(&token_source, &mut tree_sink); | 53 | ra_parser::parse_expr(&token_source, &mut tree_sink); |
53 | if tree_sink.roots.len() != 1 { | 54 | if tree_sink.roots.len() != 1 { |
@@ -62,7 +63,8 @@ pub fn token_tree_to_expr(tt: &tt::Subtree) -> Result<TreeArc<ast::Expr>, Expand | |||
62 | 63 | ||
63 | /// Parses the token tree (result of macro expansion) to a Pattern | 64 | /// Parses the token tree (result of macro expansion) to a Pattern |
64 | pub fn token_tree_to_pat(tt: &tt::Subtree) -> Result<TreeArc<ast::Pat>, ExpandError> { | 65 | pub fn token_tree_to_pat(tt: &tt::Subtree) -> Result<TreeArc<ast::Pat>, ExpandError> { |
65 | let token_source = SubtreeTokenSource::new(tt); | 66 | let buffer = tt::buffer::TokenBuffer::new(&[tt.clone().into()]); |
67 | let token_source = SubtreeTokenSource::new(&buffer); | ||
66 | let mut tree_sink = TtTreeSink::new(token_source.querier()); | 68 | let mut tree_sink = TtTreeSink::new(token_source.querier()); |
67 | ra_parser::parse_pat(&token_source, &mut tree_sink); | 69 | ra_parser::parse_pat(&token_source, &mut tree_sink); |
68 | if tree_sink.roots.len() != 1 { | 70 | if tree_sink.roots.len() != 1 { |
@@ -75,7 +77,8 @@ pub fn token_tree_to_pat(tt: &tt::Subtree) -> Result<TreeArc<ast::Pat>, ExpandEr | |||
75 | 77 | ||
76 | /// Parses the token tree (result of macro expansion) to a Type | 78 | /// Parses the token tree (result of macro expansion) to a Type |
77 | pub fn token_tree_to_ty(tt: &tt::Subtree) -> Result<TreeArc<ast::TypeRef>, ExpandError> { | 79 | pub fn token_tree_to_ty(tt: &tt::Subtree) -> Result<TreeArc<ast::TypeRef>, ExpandError> { |
78 | let token_source = SubtreeTokenSource::new(tt); | 80 | let buffer = tt::buffer::TokenBuffer::new(&[tt.clone().into()]); |
81 | let token_source = SubtreeTokenSource::new(&buffer); | ||
79 | let mut tree_sink = TtTreeSink::new(token_source.querier()); | 82 | let mut tree_sink = TtTreeSink::new(token_source.querier()); |
80 | ra_parser::parse_ty(&token_source, &mut tree_sink); | 83 | ra_parser::parse_ty(&token_source, &mut tree_sink); |
81 | if tree_sink.roots.len() != 1 { | 84 | if tree_sink.roots.len() != 1 { |
@@ -89,7 +92,8 @@ pub fn token_tree_to_ty(tt: &tt::Subtree) -> Result<TreeArc<ast::TypeRef>, Expan | |||
89 | pub fn token_tree_to_macro_stmts( | 92 | pub fn token_tree_to_macro_stmts( |
90 | tt: &tt::Subtree, | 93 | tt: &tt::Subtree, |
91 | ) -> Result<TreeArc<ast::MacroStmts>, ExpandError> { | 94 | ) -> Result<TreeArc<ast::MacroStmts>, ExpandError> { |
92 | let token_source = SubtreeTokenSource::new(tt); | 95 | let buffer = tt::buffer::TokenBuffer::new(&[tt.clone().into()]); |
96 | let token_source = SubtreeTokenSource::new(&buffer); | ||
93 | let mut tree_sink = TtTreeSink::new(token_source.querier()); | 97 | let mut tree_sink = TtTreeSink::new(token_source.querier()); |
94 | ra_parser::parse_macro_stmts(&token_source, &mut tree_sink); | 98 | ra_parser::parse_macro_stmts(&token_source, &mut tree_sink); |
95 | if tree_sink.roots.len() != 1 { | 99 | if tree_sink.roots.len() != 1 { |
@@ -103,7 +107,8 @@ pub fn token_tree_to_macro_stmts( | |||
103 | pub fn token_tree_to_macro_items( | 107 | pub fn token_tree_to_macro_items( |
104 | tt: &tt::Subtree, | 108 | tt: &tt::Subtree, |
105 | ) -> Result<TreeArc<ast::MacroItems>, ExpandError> { | 109 | ) -> Result<TreeArc<ast::MacroItems>, ExpandError> { |
106 | let token_source = SubtreeTokenSource::new(tt); | 110 | let buffer = tt::buffer::TokenBuffer::new(&[tt.clone().into()]); |
111 | let token_source = SubtreeTokenSource::new(&buffer); | ||
107 | let mut tree_sink = TtTreeSink::new(token_source.querier()); | 112 | let mut tree_sink = TtTreeSink::new(token_source.querier()); |
108 | ra_parser::parse_macro_items(&token_source, &mut tree_sink); | 113 | ra_parser::parse_macro_items(&token_source, &mut tree_sink); |
109 | if tree_sink.roots.len() != 1 { | 114 | if tree_sink.roots.len() != 1 { |
@@ -115,7 +120,8 @@ pub fn token_tree_to_macro_items( | |||
115 | 120 | ||
116 | /// Parses the token tree (result of macro expansion) as a sequence of items | 121 | /// Parses the token tree (result of macro expansion) as a sequence of items |
117 | pub fn token_tree_to_ast_item_list(tt: &tt::Subtree) -> TreeArc<ast::SourceFile> { | 122 | pub fn token_tree_to_ast_item_list(tt: &tt::Subtree) -> TreeArc<ast::SourceFile> { |
118 | let token_source = SubtreeTokenSource::new(tt); | 123 | let buffer = tt::buffer::TokenBuffer::new(&[tt.clone().into()]); |
124 | let token_source = SubtreeTokenSource::new(&buffer); | ||
119 | let mut tree_sink = TtTreeSink::new(token_source.querier()); | 125 | let mut tree_sink = TtTreeSink::new(token_source.querier()); |
120 | ra_parser::parse(&token_source, &mut tree_sink); | 126 | ra_parser::parse(&token_source, &mut tree_sink); |
121 | let syntax = tree_sink.inner.finish(); | 127 | let syntax = tree_sink.inner.finish(); |
@@ -381,7 +387,8 @@ mod tests { | |||
381 | "#, | 387 | "#, |
382 | ); | 388 | ); |
383 | let expansion = expand(&rules, "literals!(foo)"); | 389 | let expansion = expand(&rules, "literals!(foo)"); |
384 | let tt_src = SubtreeTokenSource::new(&expansion); | 390 | let buffer = tt::buffer::TokenBuffer::new(&[expansion.clone().into()]); |
391 | let tt_src = SubtreeTokenSource::new(&buffer); | ||
385 | 392 | ||
386 | let query = tt_src.querier(); | 393 | let query = tt_src.querier(); |
387 | 394 | ||
diff --git a/crates/ra_tt/src/buffer.rs b/crates/ra_tt/src/buffer.rs new file mode 100644 index 000000000..56b844b8b --- /dev/null +++ b/crates/ra_tt/src/buffer.rs | |||
@@ -0,0 +1,169 @@ | |||
1 | use crate::{TokenTree, Subtree, Leaf}; | ||
2 | |||
3 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] | ||
4 | struct EntryId(usize); | ||
5 | |||
6 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] | ||
7 | struct EntryPtr(EntryId, usize); | ||
8 | |||
9 | /// Internal type which is used instead of `TokenTree` to represent a token tree | ||
10 | /// within a `TokenBuffer`. | ||
11 | #[derive(Debug)] | ||
12 | enum Entry { | ||
13 | // Mimicking types from proc-macro. | ||
14 | Subtree(Subtree, EntryId), | ||
15 | Leaf(Leaf), | ||
16 | // End entries contain a pointer to the entry from the containing | ||
17 | // token tree, or None if this is the outermost level. | ||
18 | End(Option<EntryPtr>), | ||
19 | } | ||
20 | |||
21 | /// A token tree buffer | ||
22 | /// The safe version of `syn` [`TokenBuffer`](https://github.com/dtolnay/syn/blob/6533607f91686545cb034d2838beea338d9d0742/src/buffer.rs#L41) | ||
23 | #[derive(Debug)] | ||
24 | pub struct TokenBuffer { | ||
25 | buffers: Vec<Box<[Entry]>>, | ||
26 | } | ||
27 | |||
28 | impl TokenBuffer { | ||
29 | pub fn new(tokens: &[TokenTree]) -> TokenBuffer { | ||
30 | let mut buffers = vec![]; | ||
31 | |||
32 | let idx = TokenBuffer::new_inner(tokens, &mut buffers, None); | ||
33 | assert_eq!(idx, 0); | ||
34 | |||
35 | TokenBuffer { buffers } | ||
36 | } | ||
37 | |||
38 | fn new_inner( | ||
39 | tokens: &[TokenTree], | ||
40 | buffers: &mut Vec<Box<[Entry]>>, | ||
41 | next: Option<EntryPtr>, | ||
42 | ) -> usize { | ||
43 | let mut entries = vec![]; | ||
44 | let mut children = vec![]; | ||
45 | |||
46 | for (idx, tt) in tokens.iter().cloned().enumerate() { | ||
47 | match tt { | ||
48 | TokenTree::Leaf(leaf) => { | ||
49 | entries.push(Entry::Leaf(leaf)); | ||
50 | } | ||
51 | TokenTree::Subtree(subtree) => { | ||
52 | entries.push(Entry::End(None)); | ||
53 | children.push((idx, subtree)); | ||
54 | } | ||
55 | } | ||
56 | } | ||
57 | |||
58 | entries.push(Entry::End(next)); | ||
59 | let res = buffers.len(); | ||
60 | buffers.push(entries.into_boxed_slice()); | ||
61 | |||
62 | for (child_idx, subtree) in children { | ||
63 | let idx = TokenBuffer::new_inner( | ||
64 | &subtree.token_trees, | ||
65 | buffers, | ||
66 | Some(EntryPtr(EntryId(res), child_idx + 1)), | ||
67 | ); | ||
68 | buffers[res].as_mut()[child_idx] = Entry::Subtree(subtree, EntryId(idx)); | ||
69 | } | ||
70 | |||
71 | res | ||
72 | } | ||
73 | |||
74 | /// Creates a cursor referencing the first token in the buffer and able to | ||
75 | /// traverse until the end of the buffer. | ||
76 | pub fn begin(&self) -> Cursor { | ||
77 | Cursor::create(self, EntryPtr(EntryId(0), 0)) | ||
78 | } | ||
79 | |||
80 | fn entry(&self, ptr: &EntryPtr) -> Option<&Entry> { | ||
81 | let id = ptr.0; | ||
82 | self.buffers[id.0].get(ptr.1) | ||
83 | } | ||
84 | } | ||
85 | |||
86 | /// A safe version of `Cursor` from `syn` crate https://github.com/dtolnay/syn/blob/6533607f91686545cb034d2838beea338d9d0742/src/buffer.rs#L125 | ||
87 | #[derive(Copy, Clone, Debug)] | ||
88 | pub struct Cursor<'a> { | ||
89 | buffer: &'a TokenBuffer, | ||
90 | ptr: EntryPtr, | ||
91 | } | ||
92 | |||
93 | impl<'a> PartialEq for Cursor<'a> { | ||
94 | fn eq(&self, other: &Cursor) -> bool { | ||
95 | self.ptr == other.ptr && std::ptr::eq(self.buffer, other.buffer) | ||
96 | } | ||
97 | } | ||
98 | |||
99 | impl<'a> Eq for Cursor<'a> {} | ||
100 | |||
101 | impl<'a> Cursor<'a> { | ||
102 | /// Check whether it is eof | ||
103 | pub fn eof(self) -> bool { | ||
104 | match self.buffer.entry(&self.ptr) { | ||
105 | None | Some(Entry::End(None)) => true, | ||
106 | _ => false, | ||
107 | } | ||
108 | } | ||
109 | |||
110 | /// If the cursor is pointing at the end of a subtree, returns | ||
111 | /// the parent subtree | ||
112 | pub fn end(self) -> Option<(&'a Subtree)> { | ||
113 | match self.entry() { | ||
114 | Some(Entry::End(Some(ptr))) => { | ||
115 | let idx = ptr.1; | ||
116 | if let Some(Entry::Subtree(subtree, _)) = | ||
117 | self.buffer.entry(&EntryPtr(ptr.0, idx - 1)) | ||
118 | { | ||
119 | return Some(subtree); | ||
120 | } | ||
121 | |||
122 | None | ||
123 | } | ||
124 | _ => None, | ||
125 | } | ||
126 | } | ||
127 | |||
128 | fn entry(self) -> Option<(&'a Entry)> { | ||
129 | self.buffer.entry(&self.ptr) | ||
130 | } | ||
131 | |||
132 | /// If the cursor is pointing at a `Subtree`, returns | ||
133 | /// a cursor into that subtree | ||
134 | pub fn subtree(self) -> Option<Cursor<'a>> { | ||
135 | match self.entry() { | ||
136 | Some(Entry::Subtree(_, entry_id)) => { | ||
137 | Some(Cursor::create(self.buffer, EntryPtr(*entry_id, 0))) | ||
138 | } | ||
139 | _ => None, | ||
140 | } | ||
141 | } | ||
142 | |||
143 | /// If the cursor is pointing at a `TokenTree`, returns it | ||
144 | pub fn token_tree(self) -> Option<(TokenTree)> { | ||
145 | match self.entry() { | ||
146 | Some(Entry::Leaf(leaf)) => Some(leaf.clone().into()), | ||
147 | Some(Entry::Subtree(subtree, _)) => Some(subtree.clone().into()), | ||
148 | Some(Entry::End(_)) => None, | ||
149 | None => None, | ||
150 | } | ||
151 | } | ||
152 | |||
153 | fn create(buffer: &'a TokenBuffer, ptr: EntryPtr) -> Cursor<'a> { | ||
154 | Cursor { buffer, ptr } | ||
155 | } | ||
156 | |||
157 | /// Bump the cursor | ||
158 | pub fn bump(self) -> Cursor<'a> { | ||
159 | if let Some(Entry::End(exit)) = self.buffer.entry(&self.ptr) { | ||
160 | if let Some(exit) = exit { | ||
161 | Cursor::create(self.buffer, *exit) | ||
162 | } else { | ||
163 | self | ||
164 | } | ||
165 | } else { | ||
166 | Cursor::create(self.buffer, EntryPtr(self.ptr.0, self.ptr.1 + 1)) | ||
167 | } | ||
168 | } | ||
169 | } | ||
diff --git a/crates/ra_tt/src/lib.rs b/crates/ra_tt/src/lib.rs index 62c5ac52a..2a48c66c4 100644 --- a/crates/ra_tt/src/lib.rs +++ b/crates/ra_tt/src/lib.rs | |||
@@ -165,3 +165,5 @@ impl Subtree { | |||
165 | self.token_trees.len() + children_count | 165 | self.token_trees.len() + children_count |
166 | } | 166 | } |
167 | } | 167 | } |
168 | |||
169 | pub mod buffer; | ||