diff options
Diffstat (limited to 'crates/ra_mbe')
-rw-r--r-- | crates/ra_mbe/src/syntax_bridge.rs | 64 | ||||
-rw-r--r-- | crates/ra_mbe/src/tt_cursor.rs | 48 |
2 files changed, 80 insertions, 32 deletions
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index e0f228ce9..3521b382a 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs | |||
@@ -148,30 +148,21 @@ fn convert_tt( | |||
148 | match child { | 148 | match child { |
149 | SyntaxElement::Token(token) => { | 149 | SyntaxElement::Token(token) => { |
150 | if token.kind().is_punct() { | 150 | if token.kind().is_punct() { |
151 | let mut prev = None; | 151 | assert!(token.text().len() == 1, "Input ast::token punct must be single char."); |
152 | for char in token.text().chars() { | 152 | let char = token.text().chars().next().unwrap(); |
153 | if let Some(char) = prev { | 153 | |
154 | token_trees.push( | 154 | let spacing = match child_iter.peek() { |
155 | tt::Leaf::from(tt::Punct { char, spacing: tt::Spacing::Joint }) | 155 | Some(SyntaxElement::Token(token)) => { |
156 | .into(), | 156 | if token.kind().is_punct() { |
157 | ); | 157 | tt::Spacing::Joint |
158 | } | 158 | } else { |
159 | prev = Some(char) | 159 | tt::Spacing::Alone |
160 | } | ||
161 | if let Some(char) = prev { | ||
162 | let spacing = match child_iter.peek() { | ||
163 | Some(SyntaxElement::Token(token)) => { | ||
164 | if token.kind().is_punct() { | ||
165 | tt::Spacing::Joint | ||
166 | } else { | ||
167 | tt::Spacing::Alone | ||
168 | } | ||
169 | } | 160 | } |
170 | _ => tt::Spacing::Alone, | 161 | } |
171 | }; | 162 | _ => tt::Spacing::Alone, |
163 | }; | ||
172 | 164 | ||
173 | token_trees.push(tt::Leaf::from(tt::Punct { char, spacing }).into()); | 165 | token_trees.push(tt::Leaf::from(tt::Punct { char, spacing }).into()); |
174 | } | ||
175 | } else { | 166 | } else { |
176 | let child: tt::TokenTree = if token.kind() == SyntaxKind::TRUE_KW | 167 | let child: tt::TokenTree = if token.kind() == SyntaxKind::TRUE_KW |
177 | || token.kind() == SyntaxKind::FALSE_KW | 168 | || token.kind() == SyntaxKind::FALSE_KW |
@@ -224,6 +215,15 @@ impl<'a, Q: Querier> TtTreeSink<'a, Q> { | |||
224 | } | 215 | } |
225 | } | 216 | } |
226 | 217 | ||
218 | fn is_delimiter(kind: SyntaxKind) -> bool { | ||
219 | use SyntaxKind::*; | ||
220 | |||
221 | match kind { | ||
222 | L_PAREN | L_BRACK | L_CURLY | R_PAREN | R_BRACK | R_CURLY => true, | ||
223 | _ => false, | ||
224 | } | ||
225 | } | ||
226 | |||
227 | impl<'a, Q: Querier> TreeSink for TtTreeSink<'a, Q> { | 227 | impl<'a, Q: Querier> TreeSink for TtTreeSink<'a, Q> { |
228 | fn token(&mut self, kind: SyntaxKind, n_tokens: u8) { | 228 | fn token(&mut self, kind: SyntaxKind, n_tokens: u8) { |
229 | if kind == L_DOLLAR || kind == R_DOLLAR { | 229 | if kind == L_DOLLAR || kind == R_DOLLAR { |
@@ -240,14 +240,18 @@ impl<'a, Q: Querier> TreeSink for TtTreeSink<'a, Q> { | |||
240 | self.buf.clear(); | 240 | self.buf.clear(); |
241 | self.inner.token(kind, text); | 241 | self.inner.token(kind, text); |
242 | 242 | ||
243 | // // Add a white space to token | 243 | // Add a white space between tokens, only if both are not delimiters |
244 | // let (last_kind, _, last_joint_to_next ) = self.src_querier.token(self.token_pos-n_tokens as usize); | 244 | if !is_delimiter(kind) { |
245 | // if !last_joint_to_next && last_kind.is_punct() { | 245 | let (last_kind, _, last_joint_to_next) = self.src_querier.token(self.token_pos - 1); |
246 | // let (cur_kind, _, _ ) = self.src_querier.token(self.token_pos); | 246 | if !last_joint_to_next && last_kind.is_punct() { |
247 | // if cur_kind.is_punct() { | 247 | let (cur_kind, _, _) = self.src_querier.token(self.token_pos); |
248 | // self.inner.token(WHITESPACE, " ".into()); | 248 | if !is_delimiter(cur_kind) { |
249 | // } | 249 | if cur_kind.is_punct() { |
250 | // } | 250 | self.inner.token(WHITESPACE, " ".into()); |
251 | } | ||
252 | } | ||
253 | } | ||
254 | } | ||
251 | } | 255 | } |
252 | 256 | ||
253 | fn start_node(&mut self, kind: SyntaxKind) { | 257 | fn start_node(&mut self, kind: SyntaxKind) { |
diff --git a/crates/ra_mbe/src/tt_cursor.rs b/crates/ra_mbe/src/tt_cursor.rs index eef642a9c..53bc305be 100644 --- a/crates/ra_mbe/src/tt_cursor.rs +++ b/crates/ra_mbe/src/tt_cursor.rs | |||
@@ -1,6 +1,5 @@ | |||
1 | use crate::ParseError; | 1 | use crate::ParseError; |
2 | use crate::subtree_parser::Parser; | 2 | use crate::subtree_parser::Parser; |
3 | use crate::subtree_source::TokenPeek; | ||
4 | use smallvec::{SmallVec, smallvec}; | 3 | use smallvec::{SmallVec, smallvec}; |
5 | 4 | ||
6 | #[derive(Debug, Clone)] | 5 | #[derive(Debug, Clone)] |
@@ -153,7 +152,7 @@ impl<'a> TtCursor<'a> { | |||
153 | pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> { | 152 | pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> { |
154 | let parser = Parser::new(&mut self.pos, self.subtree); | 153 | let parser = Parser::new(&mut self.pos, self.subtree); |
155 | parser.parse_vis() | 154 | parser.parse_vis() |
156 | } | 155 | } |
157 | 156 | ||
158 | pub(crate) fn expect_char(&mut self, char: char) -> Result<(), ParseError> { | 157 | pub(crate) fn expect_char(&mut self, char: char) -> Result<(), ParseError> { |
159 | if self.at_char(char) { | 158 | if self.at_char(char) { |
@@ -262,3 +261,48 @@ impl<'a> TtCursor<'a> { | |||
262 | self.pos = memento.pos; | 261 | self.pos = memento.pos; |
263 | } | 262 | } |
264 | } | 263 | } |
264 | |||
265 | pub(crate) struct TokenPeek<'a, I> | ||
266 | where | ||
267 | I: Iterator<Item = &'a tt::TokenTree>, | ||
268 | { | ||
269 | iter: itertools::MultiPeek<I>, | ||
270 | } | ||
271 | |||
272 | // helper function | ||
273 | fn to_punct(tt: &tt::TokenTree) -> Option<&tt::Punct> { | ||
274 | if let tt::TokenTree::Leaf(tt::Leaf::Punct(pp)) = tt { | ||
275 | return Some(pp); | ||
276 | } | ||
277 | None | ||
278 | } | ||
279 | |||
280 | impl<'a, I> TokenPeek<'a, I> | ||
281 | where | ||
282 | I: Iterator<Item = &'a tt::TokenTree>, | ||
283 | { | ||
284 | pub fn new(iter: I) -> Self { | ||
285 | TokenPeek { iter: itertools::multipeek(iter) } | ||
286 | } | ||
287 | |||
288 | pub fn current_punct2(&mut self, p: &tt::Punct) -> Option<((char, char), bool)> { | ||
289 | if p.spacing != tt::Spacing::Joint { | ||
290 | return None; | ||
291 | } | ||
292 | |||
293 | self.iter.reset_peek(); | ||
294 | let p1 = to_punct(self.iter.peek()?)?; | ||
295 | Some(((p.char, p1.char), p1.spacing == tt::Spacing::Joint)) | ||
296 | } | ||
297 | |||
298 | pub fn current_punct3(&mut self, p: &tt::Punct) -> Option<((char, char, char), bool)> { | ||
299 | self.current_punct2(p).and_then(|((p0, p1), last_joint)| { | ||
300 | if !last_joint { | ||
301 | None | ||
302 | } else { | ||
303 | let p2 = to_punct(*self.iter.peek()?)?; | ||
304 | Some(((p0, p1, p2.char), p2.spacing == tt::Spacing::Joint)) | ||
305 | } | ||
306 | }) | ||
307 | } | ||
308 | } | ||