aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe/src/mbe_expander.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_mbe/src/mbe_expander.rs')
-rw-r--r--crates/ra_mbe/src/mbe_expander.rs118
1 files changed, 54 insertions, 64 deletions
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs
index 01641fdee..78df96880 100644
--- a/crates/ra_mbe/src/mbe_expander.rs
+++ b/crates/ra_mbe/src/mbe_expander.rs
@@ -81,21 +81,26 @@ struct Bindings {
81 81
82#[derive(Debug)] 82#[derive(Debug)]
83enum Binding { 83enum Binding {
84 Simple(tt::TokenTree), 84 Fragment(Fragment),
85 Nested(Vec<Binding>), 85 Nested(Vec<Binding>),
86 Empty, 86 Empty,
87} 87}
88 88
89#[derive(Debug, Clone)]
90enum Fragment {
91 /// token fragments are just copy-pasted into the output
92 Tokens(tt::TokenTree),
93 /// Ast fragments are inserted with fake delimiters, so as to make things
94 /// like `$i * 2` where `$i = 1 + 1` work as expectd.
95 Ast(tt::TokenTree),
96}
97
89impl Bindings { 98impl Bindings {
90 fn push_optional(&mut self, name: &SmolStr) { 99 fn push_optional(&mut self, name: &SmolStr) {
91 // FIXME: Do we have a better way to represent an empty token ? 100 // FIXME: Do we have a better way to represent an empty token ?
92 // Insert an empty subtree for empty token 101 // Insert an empty subtree for empty token
93 self.inner.insert( 102 let tt = tt::Subtree { delimiter: tt::Delimiter::None, token_trees: vec![] }.into();
94 name.clone(), 103 self.inner.insert(name.clone(), Binding::Fragment(Fragment::Tokens(tt)));
95 Binding::Simple(
96 tt::Subtree { delimiter: tt::Delimiter::None, token_trees: vec![] }.into(),
97 ),
98 );
99 } 104 }
100 105
101 fn push_empty(&mut self, name: &SmolStr) { 106 fn push_empty(&mut self, name: &SmolStr) {
@@ -106,13 +111,13 @@ impl Bindings {
106 self.inner.contains_key(name) 111 self.inner.contains_key(name)
107 } 112 }
108 113
109 fn get(&self, name: &SmolStr, nesting: &[usize]) -> Result<&tt::TokenTree, ExpandError> { 114 fn get(&self, name: &SmolStr, nesting: &[usize]) -> Result<&Fragment, ExpandError> {
110 let mut b = self.inner.get(name).ok_or_else(|| { 115 let mut b = self.inner.get(name).ok_or_else(|| {
111 ExpandError::BindingError(format!("could not find binding `{}`", name)) 116 ExpandError::BindingError(format!("could not find binding `{}`", name))
112 })?; 117 })?;
113 for &idx in nesting.iter() { 118 for &idx in nesting.iter() {
114 b = match b { 119 b = match b {
115 Binding::Simple(_) => break, 120 Binding::Fragment(_) => break,
116 Binding::Nested(bs) => bs.get(idx).ok_or_else(|| { 121 Binding::Nested(bs) => bs.get(idx).ok_or_else(|| {
117 ExpandError::BindingError(format!("could not find nested binding `{}`", name)) 122 ExpandError::BindingError(format!("could not find nested binding `{}`", name))
118 })?, 123 })?,
@@ -125,7 +130,7 @@ impl Bindings {
125 }; 130 };
126 } 131 }
127 match b { 132 match b {
128 Binding::Simple(it) => Ok(it), 133 Binding::Fragment(it) => Ok(it),
129 Binding::Nested(_) => Err(ExpandError::BindingError(format!( 134 Binding::Nested(_) => Err(ExpandError::BindingError(format!(
130 "expected simple binding, found nested binding `{}`", 135 "expected simple binding, found nested binding `{}`",
131 name 136 name
@@ -195,8 +200,8 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings,
195 crate::Leaf::Var(crate::Var { text, kind }) => { 200 crate::Leaf::Var(crate::Var { text, kind }) => {
196 let kind = kind.as_ref().ok_or(ExpandError::UnexpectedToken)?; 201 let kind = kind.as_ref().ok_or(ExpandError::UnexpectedToken)?;
197 match match_meta_var(kind.as_str(), input)? { 202 match match_meta_var(kind.as_str(), input)? {
198 Some(tt) => { 203 Some(fragment) => {
199 res.inner.insert(text.clone(), Binding::Simple(tt)); 204 res.inner.insert(text.clone(), Binding::Fragment(fragment));
200 } 205 }
201 None => res.push_optional(text), 206 None => res.push_optional(text),
202 } 207 }
@@ -292,7 +297,7 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings,
292 Ok(res) 297 Ok(res)
293} 298}
294 299
295fn match_meta_var(kind: &str, input: &mut TtCursor) -> Result<Option<tt::TokenTree>, ExpandError> { 300fn match_meta_var(kind: &str, input: &mut TtCursor) -> Result<Option<Fragment>, ExpandError> {
296 let fragment = match kind { 301 let fragment = match kind {
297 "path" => Path, 302 "path" => Path,
298 "expr" => Expr, 303 "expr" => Expr,
@@ -303,7 +308,7 @@ fn match_meta_var(kind: &str, input: &mut TtCursor) -> Result<Option<tt::TokenTr
303 "meta" => MetaItem, 308 "meta" => MetaItem,
304 "item" => Item, 309 "item" => Item,
305 _ => { 310 _ => {
306 let binding = match kind { 311 let tt = match kind {
307 "ident" => { 312 "ident" => {
308 let ident = input.eat_ident().ok_or(ExpandError::UnexpectedToken)?.clone(); 313 let ident = input.eat_ident().ok_or(ExpandError::UnexpectedToken)?.clone();
309 tt::Leaf::from(ident).into() 314 tt::Leaf::from(ident).into()
@@ -321,11 +326,12 @@ fn match_meta_var(kind: &str, input: &mut TtCursor) -> Result<Option<tt::TokenTr
321 }, 326 },
322 _ => return Err(ExpandError::UnexpectedToken), 327 _ => return Err(ExpandError::UnexpectedToken),
323 }; 328 };
324 return Ok(Some(binding)); 329 return Ok(Some(Fragment::Tokens(tt)));
325 } 330 }
326 }; 331 };
327 let binding = input.eat_fragment(fragment).ok_or(ExpandError::UnexpectedToken)?; 332 let tt = input.eat_fragment(fragment).ok_or(ExpandError::UnexpectedToken)?;
328 Ok(Some(binding)) 333 let fragment = if kind == "expr" { Fragment::Ast(tt) } else { Fragment::Tokens(tt) };
334 Ok(Some(fragment))
329} 335}
330 336
331#[derive(Debug)] 337#[derive(Debug)]
@@ -339,45 +345,20 @@ fn expand_subtree(
339 template: &crate::Subtree, 345 template: &crate::Subtree,
340 ctx: &mut ExpandCtx, 346 ctx: &mut ExpandCtx,
341) -> Result<tt::Subtree, ExpandError> { 347) -> Result<tt::Subtree, ExpandError> {
342 let token_trees = template 348 let mut buf: Vec<tt::TokenTree> = Vec::new();
343 .token_trees 349 for tt in template.token_trees.iter() {
344 .iter() 350 let tt = expand_tt(tt, ctx)?;
345 .map(|it| expand_tt(it, ctx)) 351 push_fragment(&mut buf, tt);
346 .filter(|it| {
347 // Filter empty subtree
348 if let Ok(tt::TokenTree::Subtree(subtree)) = it {
349 subtree.delimiter != tt::Delimiter::None || !subtree.token_trees.is_empty()
350 } else {
351 true
352 }
353 })
354 .collect::<Result<Vec<_>, ExpandError>>()?;
355
356 Ok(tt::Subtree { token_trees, delimiter: template.delimiter })
357}
358
359/// Reduce single token subtree to single token
360/// In `tt` matcher case, all tt tokens will be braced by a Delimiter::None
361/// which makes all sort of problems.
362fn reduce_single_token(mut subtree: tt::Subtree) -> tt::TokenTree {
363 if subtree.delimiter != tt::Delimiter::None || subtree.token_trees.len() != 1 {
364 return subtree.into();
365 } 352 }
366 353
367 match subtree.token_trees.pop().unwrap() { 354 Ok(tt::Subtree { delimiter: template.delimiter, token_trees: buf })
368 tt::TokenTree::Subtree(subtree) => reduce_single_token(subtree),
369 tt::TokenTree::Leaf(token) => token.into(),
370 }
371} 355}
372 356
373fn expand_tt( 357fn expand_tt(template: &crate::TokenTree, ctx: &mut ExpandCtx) -> Result<Fragment, ExpandError> {
374 template: &crate::TokenTree,
375 ctx: &mut ExpandCtx,
376) -> Result<tt::TokenTree, ExpandError> {
377 let res: tt::TokenTree = match template { 358 let res: tt::TokenTree = match template {
378 crate::TokenTree::Subtree(subtree) => expand_subtree(subtree, ctx)?.into(), 359 crate::TokenTree::Subtree(subtree) => expand_subtree(subtree, ctx)?.into(),
379 crate::TokenTree::Repeat(repeat) => { 360 crate::TokenTree::Repeat(repeat) => {
380 let mut token_trees: Vec<tt::TokenTree> = Vec::new(); 361 let mut buf: Vec<tt::TokenTree> = Vec::new();
381 ctx.nesting.push(0); 362 ctx.nesting.push(0);
382 // Dirty hack to make macro-expansion terminate. 363 // Dirty hack to make macro-expansion terminate.
383 // This should be replaced by a propper macro-by-example implementation 364 // This should be replaced by a propper macro-by-example implementation
@@ -418,23 +399,23 @@ fn expand_tt(
418 399
419 let idx = ctx.nesting.pop().unwrap(); 400 let idx = ctx.nesting.pop().unwrap();
420 ctx.nesting.push(idx + 1); 401 ctx.nesting.push(idx + 1);
421 token_trees.push(reduce_single_token(t)); 402 push_subtree(&mut buf, t);
422 403
423 if let Some(ref sep) = repeat.separator { 404 if let Some(ref sep) = repeat.separator {
424 match sep { 405 match sep {
425 crate::Separator::Ident(ident) => { 406 crate::Separator::Ident(ident) => {
426 has_seps = 1; 407 has_seps = 1;
427 token_trees.push(tt::Leaf::from(ident.clone()).into()); 408 buf.push(tt::Leaf::from(ident.clone()).into());
428 } 409 }
429 crate::Separator::Literal(lit) => { 410 crate::Separator::Literal(lit) => {
430 has_seps = 1; 411 has_seps = 1;
431 token_trees.push(tt::Leaf::from(lit.clone()).into()); 412 buf.push(tt::Leaf::from(lit.clone()).into());
432 } 413 }
433 414
434 crate::Separator::Puncts(puncts) => { 415 crate::Separator::Puncts(puncts) => {
435 has_seps = puncts.len(); 416 has_seps = puncts.len();
436 for punct in puncts { 417 for punct in puncts {
437 token_trees.push(tt::Leaf::from(*punct).into()); 418 buf.push(tt::Leaf::from(*punct).into());
438 } 419 }
439 } 420 }
440 } 421 }
@@ -450,16 +431,16 @@ fn expand_tt(
450 431
451 ctx.nesting.pop().unwrap(); 432 ctx.nesting.pop().unwrap();
452 for _ in 0..has_seps { 433 for _ in 0..has_seps {
453 token_trees.pop(); 434 buf.pop();
454 } 435 }
455 436
456 if crate::RepeatKind::OneOrMore == repeat.kind && counter == 0 { 437 if crate::RepeatKind::OneOrMore == repeat.kind && counter == 0 {
457 return Err(ExpandError::UnexpectedToken); 438 return Err(ExpandError::UnexpectedToken);
458 } 439 }
459 440
460 // Check if it is a singel token subtree without any delimiter 441 // Check if it is a single token subtree without any delimiter
461 // e.g {Delimiter:None> ['>'] /Delimiter:None>} 442 // e.g {Delimiter:None> ['>'] /Delimiter:None>}
462 reduce_single_token(tt::Subtree { token_trees, delimiter: tt::Delimiter::None }) 443 tt::Subtree { delimiter: tt::Delimiter::None, token_trees: buf }.into()
463 } 444 }
464 crate::TokenTree::Leaf(leaf) => match leaf { 445 crate::TokenTree::Leaf(leaf) => match leaf {
465 crate::Leaf::Ident(ident) => { 446 crate::Leaf::Ident(ident) => {
@@ -500,20 +481,15 @@ fn expand_tt(
500 } 481 }
501 .into() 482 .into()
502 } else { 483 } else {
503 let tkn = ctx.bindings.get(&v.text, &ctx.nesting)?.clone(); 484 let fragment = ctx.bindings.get(&v.text, &ctx.nesting)?.clone();
504 ctx.var_expanded = true; 485 ctx.var_expanded = true;
505 486 return Ok(fragment);
506 if let tt::TokenTree::Subtree(subtree) = tkn {
507 reduce_single_token(subtree)
508 } else {
509 tkn
510 }
511 } 487 }
512 } 488 }
513 crate::Leaf::Literal(l) => tt::Leaf::from(tt::Literal { text: l.text.clone() }).into(), 489 crate::Leaf::Literal(l) => tt::Leaf::from(tt::Literal { text: l.text.clone() }).into(),
514 }, 490 },
515 }; 491 };
516 Ok(res) 492 Ok(Fragment::Tokens(res))
517} 493}
518 494
519#[cfg(test)] 495#[cfg(test)]
@@ -586,3 +562,17 @@ mod tests {
586 expand_rule(&rules.rules[0], &invocation_tt) 562 expand_rule(&rules.rules[0], &invocation_tt)
587 } 563 }
588} 564}
565
566fn push_fragment(buf: &mut Vec<tt::TokenTree>, fragment: Fragment) {
567 match fragment {
568 Fragment::Tokens(tt::TokenTree::Subtree(tt)) => push_subtree(buf, tt),
569 Fragment::Tokens(tt) | Fragment::Ast(tt) => buf.push(tt),
570 }
571}
572
573fn push_subtree(buf: &mut Vec<tt::TokenTree>, tt: tt::Subtree) {
574 match tt.delimiter {
575 tt::Delimiter::None => buf.extend(tt.token_trees),
576 _ => buf.push(tt.into()),
577 }
578}