aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe/src/mbe_expander.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-09-10 18:09:43 +0100
committerAleksey Kladov <[email protected]>2019-09-10 18:26:41 +0100
commit6e5198cd6dc0572ffaddcdea29d5541085ec5300 (patch)
tree43ab118e6a00130814f012fe0386f0f421c2ef34 /crates/ra_mbe/src/mbe_expander.rs
parent9d3c78e2eee6635772c99d7351b621cefb08bac5 (diff)
add fragmets to expansion
Diffstat (limited to 'crates/ra_mbe/src/mbe_expander.rs')
-rw-r--r--crates/ra_mbe/src/mbe_expander.rs73
1 files changed, 40 insertions, 33 deletions
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs
index 08b0519d2..db05c6253 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)]
@@ -342,7 +348,7 @@ fn expand_subtree(
342 let mut buf: Vec<tt::TokenTree> = Vec::new(); 348 let mut buf: Vec<tt::TokenTree> = Vec::new();
343 for tt in template.token_trees.iter() { 349 for tt in template.token_trees.iter() {
344 let tt = expand_tt(tt, ctx)?; 350 let tt = expand_tt(tt, ctx)?;
345 push_tt(&mut buf, tt); 351 push_fragment(&mut buf, tt);
346 } 352 }
347 353
348 Ok(tt::Subtree { delimiter: template.delimiter, token_trees: buf }) 354 Ok(tt::Subtree { delimiter: template.delimiter, token_trees: buf })
@@ -362,10 +368,7 @@ fn reduce_single_token(mut subtree: tt::Subtree) -> tt::TokenTree {
362 } 368 }
363} 369}
364 370
365fn expand_tt( 371fn expand_tt(template: &crate::TokenTree, ctx: &mut ExpandCtx) -> Result<Fragment, ExpandError> {
366 template: &crate::TokenTree,
367 ctx: &mut ExpandCtx,
368) -> Result<tt::TokenTree, ExpandError> {
369 let res: tt::TokenTree = match template { 372 let res: tt::TokenTree = match template {
370 crate::TokenTree::Subtree(subtree) => expand_subtree(subtree, ctx)?.into(), 373 crate::TokenTree::Subtree(subtree) => expand_subtree(subtree, ctx)?.into(),
371 crate::TokenTree::Repeat(repeat) => { 374 crate::TokenTree::Repeat(repeat) => {
@@ -492,20 +495,24 @@ fn expand_tt(
492 } 495 }
493 .into() 496 .into()
494 } else { 497 } else {
495 let tkn = ctx.bindings.get(&v.text, &ctx.nesting)?.clone(); 498 let fragment = ctx.bindings.get(&v.text, &ctx.nesting)?.clone();
496 ctx.var_expanded = true; 499 ctx.var_expanded = true;
497 500 match fragment {
498 if let tt::TokenTree::Subtree(subtree) = tkn { 501 Fragment::Tokens(tt) => {
499 reduce_single_token(subtree) 502 if let tt::TokenTree::Subtree(subtree) = tt {
500 } else { 503 reduce_single_token(subtree)
501 tkn 504 } else {
505 tt
506 }
507 }
508 Fragment::Ast(_) => return Ok(fragment),
502 } 509 }
503 } 510 }
504 } 511 }
505 crate::Leaf::Literal(l) => tt::Leaf::from(tt::Literal { text: l.text.clone() }).into(), 512 crate::Leaf::Literal(l) => tt::Leaf::from(tt::Literal { text: l.text.clone() }).into(),
506 }, 513 },
507 }; 514 };
508 Ok(res) 515 Ok(Fragment::Tokens(res))
509} 516}
510 517
511#[cfg(test)] 518#[cfg(test)]
@@ -579,10 +586,10 @@ mod tests {
579 } 586 }
580} 587}
581 588
582fn push_tt(buf: &mut Vec<tt::TokenTree>, tt: tt::TokenTree) { 589fn push_fragment(buf: &mut Vec<tt::TokenTree>, fragment: Fragment) {
583 match tt { 590 match fragment {
584 tt::TokenTree::Subtree(tt) => push_subtree(buf, tt), 591 Fragment::Tokens(tt::TokenTree::Subtree(tt)) => push_subtree(buf, tt),
585 _ => buf.push(tt), 592 Fragment::Tokens(tt) | Fragment::Ast(tt) => buf.push(tt),
586 } 593 }
587} 594}
588 595