aboutsummaryrefslogtreecommitdiff
path: root/crates/mbe/src/mbe_expander
diff options
context:
space:
mode:
Diffstat (limited to 'crates/mbe/src/mbe_expander')
-rw-r--r--crates/mbe/src/mbe_expander/matcher.rs477
-rw-r--r--crates/mbe/src/mbe_expander/transcriber.rs254
2 files changed, 731 insertions, 0 deletions
diff --git a/crates/mbe/src/mbe_expander/matcher.rs b/crates/mbe/src/mbe_expander/matcher.rs
new file mode 100644
index 000000000..b698b9832
--- /dev/null
+++ b/crates/mbe/src/mbe_expander/matcher.rs
@@ -0,0 +1,477 @@
1//! FIXME: write short doc here
2
3use crate::{
4 mbe_expander::{Binding, Bindings, Fragment},
5 parser::{parse_pattern, Op, RepeatKind, Separator},
6 subtree_source::SubtreeTokenSource,
7 tt_iter::TtIter,
8 ExpandError,
9};
10
11use super::ExpandResult;
12use parser::{FragmentKind::*, TreeSink};
13use syntax::{SmolStr, SyntaxKind};
14use tt::buffer::{Cursor, TokenBuffer};
15
16impl Bindings {
17 fn push_optional(&mut self, name: &SmolStr) {
18 // FIXME: Do we have a better way to represent an empty token ?
19 // Insert an empty subtree for empty token
20 let tt = tt::Subtree::default().into();
21 self.inner.insert(name.clone(), Binding::Fragment(Fragment::Tokens(tt)));
22 }
23
24 fn push_empty(&mut self, name: &SmolStr) {
25 self.inner.insert(name.clone(), Binding::Empty);
26 }
27
28 fn push_nested(&mut self, idx: usize, nested: Bindings) -> Result<(), ExpandError> {
29 for (key, value) in nested.inner {
30 if !self.inner.contains_key(&key) {
31 self.inner.insert(key.clone(), Binding::Nested(Vec::new()));
32 }
33 match self.inner.get_mut(&key) {
34 Some(Binding::Nested(it)) => {
35 // insert empty nested bindings before this one
36 while it.len() < idx {
37 it.push(Binding::Nested(vec![]));
38 }
39 it.push(value);
40 }
41 _ => {
42 return Err(ExpandError::BindingError(format!(
43 "could not find binding `{}`",
44 key
45 )));
46 }
47 }
48 }
49 Ok(())
50 }
51}
52
53macro_rules! err {
54 () => {
55 ExpandError::BindingError(format!(""))
56 };
57 ($($tt:tt)*) => {
58 ExpandError::BindingError(format!($($tt)*))
59 };
60}
61
62#[derive(Debug, Default)]
63pub(super) struct Match {
64 pub bindings: Bindings,
65 /// We currently just keep the first error and count the rest to compare matches.
66 pub err: Option<ExpandError>,
67 pub err_count: usize,
68 /// How many top-level token trees were left to match.
69 pub unmatched_tts: usize,
70}
71
72impl Match {
73 pub fn add_err(&mut self, err: ExpandError) {
74 let prev_err = self.err.take();
75 self.err = prev_err.or(Some(err));
76 self.err_count += 1;
77 }
78}
79
80// General note: These functions have two channels to return errors, a `Result`
81// return value and the `&mut Match`. The returned Result is for pattern parsing
82// errors; if a branch of the macro definition doesn't parse, it doesn't make
83// sense to try using it. Matching errors are added to the `Match`. It might
84// make sense to make pattern parsing a separate step?
85
86pub(super) fn match_(pattern: &tt::Subtree, src: &tt::Subtree) -> Result<Match, ExpandError> {
87 assert!(pattern.delimiter == None);
88
89 let mut res = Match::default();
90 let mut src = TtIter::new(src);
91
92 match_subtree(&mut res, pattern, &mut src)?;
93
94 if src.len() > 0 {
95 res.unmatched_tts += src.len();
96 res.add_err(err!("leftover tokens"));
97 }
98
99 Ok(res)
100}
101
102fn match_subtree(
103 res: &mut Match,
104 pattern: &tt::Subtree,
105 src: &mut TtIter,
106) -> Result<(), ExpandError> {
107 for op in parse_pattern(pattern) {
108 match op? {
109 Op::TokenTree(tt::TokenTree::Leaf(lhs)) => {
110 let rhs = match src.expect_leaf() {
111 Ok(l) => l,
112 Err(()) => {
113 res.add_err(err!("expected leaf: `{}`", lhs));
114 continue;
115 }
116 };
117 match (lhs, rhs) {
118 (
119 tt::Leaf::Punct(tt::Punct { char: lhs, .. }),
120 tt::Leaf::Punct(tt::Punct { char: rhs, .. }),
121 ) if lhs == rhs => (),
122 (
123 tt::Leaf::Ident(tt::Ident { text: lhs, .. }),
124 tt::Leaf::Ident(tt::Ident { text: rhs, .. }),
125 ) if lhs == rhs => (),
126 (
127 tt::Leaf::Literal(tt::Literal { text: lhs, .. }),
128 tt::Leaf::Literal(tt::Literal { text: rhs, .. }),
129 ) if lhs == rhs => (),
130 _ => {
131 res.add_err(ExpandError::UnexpectedToken);
132 }
133 }
134 }
135 Op::TokenTree(tt::TokenTree::Subtree(lhs)) => {
136 let rhs = match src.expect_subtree() {
137 Ok(s) => s,
138 Err(()) => {
139 res.add_err(err!("expected subtree"));
140 continue;
141 }
142 };
143 if lhs.delimiter_kind() != rhs.delimiter_kind() {
144 res.add_err(err!("mismatched delimiter"));
145 continue;
146 }
147 let mut src = TtIter::new(rhs);
148 match_subtree(res, lhs, &mut src)?;
149 if src.len() > 0 {
150 res.add_err(err!("leftover tokens"));
151 }
152 }
153 Op::Var { name, kind } => {
154 let kind = match kind {
155 Some(k) => k,
156 None => {
157 res.add_err(ExpandError::UnexpectedToken);
158 continue;
159 }
160 };
161 let ExpandResult(matched, match_err) = match_meta_var(kind.as_str(), src);
162 match matched {
163 Some(fragment) => {
164 res.bindings.inner.insert(name.clone(), Binding::Fragment(fragment));
165 }
166 None if match_err.is_none() => res.bindings.push_optional(name),
167 _ => {}
168 }
169 if let Some(err) = match_err {
170 res.add_err(err);
171 }
172 }
173 Op::Repeat { subtree, kind, separator } => {
174 match_repeat(res, subtree, kind, separator, src)?;
175 }
176 }
177 }
178 Ok(())
179}
180
181impl<'a> TtIter<'a> {
182 fn eat_separator(&mut self, separator: &Separator) -> bool {
183 let mut fork = self.clone();
184 let ok = match separator {
185 Separator::Ident(lhs) => match fork.expect_ident() {
186 Ok(rhs) => rhs.text == lhs.text,
187 _ => false,
188 },
189 Separator::Literal(lhs) => match fork.expect_literal() {
190 Ok(rhs) => match rhs {
191 tt::Leaf::Literal(rhs) => rhs.text == lhs.text,
192 tt::Leaf::Ident(rhs) => rhs.text == lhs.text,
193 tt::Leaf::Punct(_) => false,
194 },
195 _ => false,
196 },
197 Separator::Puncts(lhss) => lhss.iter().all(|lhs| match fork.expect_punct() {
198 Ok(rhs) => rhs.char == lhs.char,
199 _ => false,
200 }),
201 };
202 if ok {
203 *self = fork;
204 }
205 ok
206 }
207
208 pub(crate) fn expect_tt(&mut self) -> Result<tt::TokenTree, ()> {
209 match self.peek_n(0) {
210 Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) if punct.char == '\'' => {
211 return self.expect_lifetime();
212 }
213 _ => (),
214 }
215
216 let tt = self.next().ok_or_else(|| ())?.clone();
217 let punct = match tt {
218 tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if punct.spacing == tt::Spacing::Joint => {
219 punct
220 }
221 _ => return Ok(tt),
222 };
223
224 let (second, third) = match (self.peek_n(0), self.peek_n(1)) {
225 (
226 Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p2))),
227 Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p3))),
228 ) if p2.spacing == tt::Spacing::Joint => (p2.char, Some(p3.char)),
229 (Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p2))), _) => (p2.char, None),
230 _ => return Ok(tt),
231 };
232
233 match (punct.char, second, third) {
234 ('.', '.', Some('.'))
235 | ('.', '.', Some('='))
236 | ('<', '<', Some('='))
237 | ('>', '>', Some('=')) => {
238 let tt2 = self.next().unwrap().clone();
239 let tt3 = self.next().unwrap().clone();
240 Ok(tt::Subtree { delimiter: None, token_trees: vec![tt, tt2, tt3] }.into())
241 }
242 ('-', '=', None)
243 | ('-', '>', None)
244 | (':', ':', None)
245 | ('!', '=', None)
246 | ('.', '.', None)
247 | ('*', '=', None)
248 | ('/', '=', None)
249 | ('&', '&', None)
250 | ('&', '=', None)
251 | ('%', '=', None)
252 | ('^', '=', None)
253 | ('+', '=', None)
254 | ('<', '<', None)
255 | ('<', '=', None)
256 | ('=', '=', None)
257 | ('=', '>', None)
258 | ('>', '=', None)
259 | ('>', '>', None)
260 | ('|', '=', None)
261 | ('|', '|', None) => {
262 let tt2 = self.next().unwrap().clone();
263 Ok(tt::Subtree { delimiter: None, token_trees: vec![tt, tt2] }.into())
264 }
265 _ => Ok(tt),
266 }
267 }
268
269 pub(crate) fn expect_lifetime(&mut self) -> Result<tt::TokenTree, ()> {
270 let punct = self.expect_punct()?;
271 if punct.char != '\'' {
272 return Err(());
273 }
274 let ident = self.expect_ident()?;
275
276 Ok(tt::Subtree {
277 delimiter: None,
278 token_trees: vec![
279 tt::Leaf::Punct(*punct).into(),
280 tt::Leaf::Ident(ident.clone()).into(),
281 ],
282 }
283 .into())
284 }
285
286 pub(crate) fn expect_fragment(
287 &mut self,
288 fragment_kind: parser::FragmentKind,
289 ) -> ExpandResult<Option<tt::TokenTree>> {
290 pub(crate) struct OffsetTokenSink<'a> {
291 pub(crate) cursor: Cursor<'a>,
292 pub(crate) error: bool,
293 }
294
295 impl<'a> TreeSink for OffsetTokenSink<'a> {
296 fn token(&mut self, kind: SyntaxKind, mut n_tokens: u8) {
297 if kind == SyntaxKind::LIFETIME {
298 n_tokens = 2;
299 }
300 for _ in 0..n_tokens {
301 self.cursor = self.cursor.bump_subtree();
302 }
303 }
304 fn start_node(&mut self, _kind: SyntaxKind) {}
305 fn finish_node(&mut self) {}
306 fn error(&mut self, _error: parser::ParseError) {
307 self.error = true;
308 }
309 }
310
311 let buffer = TokenBuffer::new(&self.inner.as_slice());
312 let mut src = SubtreeTokenSource::new(&buffer);
313 let mut sink = OffsetTokenSink { cursor: buffer.begin(), error: false };
314
315 parser::parse_fragment(&mut src, &mut sink, fragment_kind);
316
317 let mut err = None;
318 if !sink.cursor.is_root() || sink.error {
319 err = Some(err!("expected {:?}", fragment_kind));
320 }
321
322 let mut curr = buffer.begin();
323 let mut res = vec![];
324
325 if sink.cursor.is_root() {
326 while curr != sink.cursor {
327 if let Some(token) = curr.token_tree() {
328 res.push(token);
329 }
330 curr = curr.bump();
331 }
332 }
333 self.inner = self.inner.as_slice()[res.len()..].iter();
334 if res.len() == 0 && err.is_none() {
335 err = Some(err!("no tokens consumed"));
336 }
337 let res = match res.len() {
338 1 => Some(res[0].clone()),
339 0 => None,
340 _ => Some(tt::TokenTree::Subtree(tt::Subtree {
341 delimiter: None,
342 token_trees: res.into_iter().cloned().collect(),
343 })),
344 };
345 ExpandResult(res, err)
346 }
347
348 pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> {
349 let mut fork = self.clone();
350 match fork.expect_fragment(Visibility) {
351 ExpandResult(tt, None) => {
352 *self = fork;
353 tt
354 }
355 ExpandResult(_, Some(_)) => None,
356 }
357 }
358}
359
360pub(super) fn match_repeat(
361 res: &mut Match,
362 pattern: &tt::Subtree,
363 kind: RepeatKind,
364 separator: Option<Separator>,
365 src: &mut TtIter,
366) -> Result<(), ExpandError> {
367 // Dirty hack to make macro-expansion terminate.
368 // This should be replaced by a propper macro-by-example implementation
369 let mut limit = 65536;
370 let mut counter = 0;
371
372 for i in 0.. {
373 let mut fork = src.clone();
374
375 if let Some(separator) = &separator {
376 if i != 0 && !fork.eat_separator(separator) {
377 break;
378 }
379 }
380
381 let mut nested = Match::default();
382 match_subtree(&mut nested, pattern, &mut fork)?;
383 if nested.err.is_none() {
384 limit -= 1;
385 if limit == 0 {
386 log::warn!(
387 "match_lhs exceeded repeat pattern limit => {:#?}\n{:#?}\n{:#?}\n{:#?}",
388 pattern,
389 src,
390 kind,
391 separator
392 );
393 break;
394 }
395 *src = fork;
396
397 if let Err(err) = res.bindings.push_nested(counter, nested.bindings) {
398 res.add_err(err);
399 }
400 counter += 1;
401 if counter == 1 {
402 if let RepeatKind::ZeroOrOne = kind {
403 break;
404 }
405 }
406 } else {
407 break;
408 }
409 }
410
411 match (kind, counter) {
412 (RepeatKind::OneOrMore, 0) => {
413 res.add_err(ExpandError::UnexpectedToken);
414 }
415 (_, 0) => {
416 // Collect all empty variables in subtrees
417 let mut vars = Vec::new();
418 collect_vars(&mut vars, pattern)?;
419 for var in vars {
420 res.bindings.push_empty(&var)
421 }
422 }
423 _ => (),
424 }
425 Ok(())
426}
427
428fn match_meta_var(kind: &str, input: &mut TtIter) -> ExpandResult<Option<Fragment>> {
429 let fragment = match kind {
430 "path" => Path,
431 "expr" => Expr,
432 "ty" => Type,
433 "pat" => Pattern,
434 "stmt" => Statement,
435 "block" => Block,
436 "meta" => MetaItem,
437 "item" => Item,
438 _ => {
439 let tt_result = match kind {
440 "ident" => input
441 .expect_ident()
442 .map(|ident| Some(tt::Leaf::from(ident.clone()).into()))
443 .map_err(|()| err!("expected ident")),
444 "tt" => input.expect_tt().map(Some).map_err(|()| err!()),
445 "lifetime" => input
446 .expect_lifetime()
447 .map(|tt| Some(tt))
448 .map_err(|()| err!("expected lifetime")),
449 "literal" => input
450 .expect_literal()
451 .map(|literal| Some(tt::Leaf::from(literal.clone()).into()))
452 .map_err(|()| err!()),
453 // `vis` is optional
454 "vis" => match input.eat_vis() {
455 Some(vis) => Ok(Some(vis)),
456 None => Ok(None),
457 },
458 _ => Err(ExpandError::UnexpectedToken),
459 };
460 return tt_result.map(|it| it.map(Fragment::Tokens)).into();
461 }
462 };
463 let result = input.expect_fragment(fragment);
464 result.map(|tt| if kind == "expr" { tt.map(Fragment::Ast) } else { tt.map(Fragment::Tokens) })
465}
466
467fn collect_vars(buf: &mut Vec<SmolStr>, pattern: &tt::Subtree) -> Result<(), ExpandError> {
468 for op in parse_pattern(pattern) {
469 match op? {
470 Op::Var { name, .. } => buf.push(name.clone()),
471 Op::TokenTree(tt::TokenTree::Leaf(_)) => (),
472 Op::TokenTree(tt::TokenTree::Subtree(subtree)) => collect_vars(buf, subtree)?,
473 Op::Repeat { subtree, .. } => collect_vars(buf, subtree)?,
474 }
475 }
476 Ok(())
477}
diff --git a/crates/mbe/src/mbe_expander/transcriber.rs b/crates/mbe/src/mbe_expander/transcriber.rs
new file mode 100644
index 000000000..c9525c5bf
--- /dev/null
+++ b/crates/mbe/src/mbe_expander/transcriber.rs
@@ -0,0 +1,254 @@
1//! Transcriber takes a template, like `fn $ident() {}`, a set of bindings like
2//! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}`
3
4use syntax::SmolStr;
5
6use super::ExpandResult;
7use crate::{
8 mbe_expander::{Binding, Bindings, Fragment},
9 parser::{parse_template, Op, RepeatKind, Separator},
10 ExpandError,
11};
12
13impl Bindings {
14 fn contains(&self, name: &str) -> bool {
15 self.inner.contains_key(name)
16 }
17
18 fn get(&self, name: &str, nesting: &mut [NestingState]) -> Result<&Fragment, ExpandError> {
19 let mut b = self.inner.get(name).ok_or_else(|| {
20 ExpandError::BindingError(format!("could not find binding `{}`", name))
21 })?;
22 for nesting_state in nesting.iter_mut() {
23 nesting_state.hit = true;
24 b = match b {
25 Binding::Fragment(_) => break,
26 Binding::Nested(bs) => bs.get(nesting_state.idx).ok_or_else(|| {
27 nesting_state.at_end = true;
28 ExpandError::BindingError(format!("could not find nested binding `{}`", name))
29 })?,
30 Binding::Empty => {
31 nesting_state.at_end = true;
32 return Err(ExpandError::BindingError(format!(
33 "could not find empty binding `{}`",
34 name
35 )));
36 }
37 };
38 }
39 match b {
40 Binding::Fragment(it) => Ok(it),
41 Binding::Nested(_) => Err(ExpandError::BindingError(format!(
42 "expected simple binding, found nested binding `{}`",
43 name
44 ))),
45 Binding::Empty => Err(ExpandError::BindingError(format!(
46 "expected simple binding, found empty binding `{}`",
47 name
48 ))),
49 }
50 }
51}
52
53pub(super) fn transcribe(template: &tt::Subtree, bindings: &Bindings) -> ExpandResult<tt::Subtree> {
54 assert!(template.delimiter == None);
55 let mut ctx = ExpandCtx { bindings: &bindings, nesting: Vec::new() };
56 let mut arena: Vec<tt::TokenTree> = Vec::new();
57 expand_subtree(&mut ctx, template, &mut arena)
58}
59
60#[derive(Debug)]
61struct NestingState {
62 idx: usize,
63 /// `hit` is currently necessary to tell `expand_repeat` if it should stop
64 /// because there is no variable in use by the current repetition
65 hit: bool,
66 /// `at_end` is currently necessary to tell `expand_repeat` if it should stop
67 /// because there is no more value avaible for the current repetition
68 at_end: bool,
69}
70
71#[derive(Debug)]
72struct ExpandCtx<'a> {
73 bindings: &'a Bindings,
74 nesting: Vec<NestingState>,
75}
76
77fn expand_subtree(
78 ctx: &mut ExpandCtx,
79 template: &tt::Subtree,
80 arena: &mut Vec<tt::TokenTree>,
81) -> ExpandResult<tt::Subtree> {
82 // remember how many elements are in the arena now - when returning, we want to drain exactly how many elements we added. This way, the recursive uses of the arena get their own "view" of the arena, but will reuse the allocation
83 let start_elements = arena.len();
84 let mut err = None;
85 for op in parse_template(template) {
86 let op = match op {
87 Ok(op) => op,
88 Err(e) => {
89 err = Some(e);
90 break;
91 }
92 };
93 match op {
94 Op::TokenTree(tt @ tt::TokenTree::Leaf(..)) => arena.push(tt.clone()),
95 Op::TokenTree(tt::TokenTree::Subtree(tt)) => {
96 let ExpandResult(tt, e) = expand_subtree(ctx, tt, arena);
97 err = err.or(e);
98 arena.push(tt.into());
99 }
100 Op::Var { name, kind: _ } => {
101 let ExpandResult(fragment, e) = expand_var(ctx, name);
102 err = err.or(e);
103 push_fragment(arena, fragment);
104 }
105 Op::Repeat { subtree, kind, separator } => {
106 let ExpandResult(fragment, e) = expand_repeat(ctx, subtree, kind, separator, arena);
107 err = err.or(e);
108 push_fragment(arena, fragment)
109 }
110 }
111 }
112 // drain the elements added in this instance of expand_subtree
113 let tts = arena.drain(start_elements..arena.len()).collect();
114 ExpandResult(tt::Subtree { delimiter: template.delimiter, token_trees: tts }, err)
115}
116
117fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> {
118 if v == "crate" {
119 // We simply produce identifier `$crate` here. And it will be resolved when lowering ast to Path.
120 let tt =
121 tt::Leaf::from(tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() })
122 .into();
123 ExpandResult::ok(Fragment::Tokens(tt))
124 } else if !ctx.bindings.contains(v) {
125 // Note that it is possible to have a `$var` inside a macro which is not bound.
126 // For example:
127 // ```
128 // macro_rules! foo {
129 // ($a:ident, $b:ident, $c:tt) => {
130 // macro_rules! bar {
131 // ($bi:ident) => {
132 // fn $bi() -> u8 {$c}
133 // }
134 // }
135 // }
136 // ```
137 // We just treat it a normal tokens
138 let tt = tt::Subtree {
139 delimiter: None,
140 token_trees: vec![
141 tt::Leaf::from(tt::Punct {
142 char: '$',
143 spacing: tt::Spacing::Alone,
144 id: tt::TokenId::unspecified(),
145 })
146 .into(),
147 tt::Leaf::from(tt::Ident { text: v.clone(), id: tt::TokenId::unspecified() })
148 .into(),
149 ],
150 }
151 .into();
152 ExpandResult::ok(Fragment::Tokens(tt))
153 } else {
154 ctx.bindings.get(&v, &mut ctx.nesting).map_or_else(
155 |e| ExpandResult(Fragment::Tokens(tt::TokenTree::empty()), Some(e)),
156 |b| ExpandResult::ok(b.clone()),
157 )
158 }
159}
160
161fn expand_repeat(
162 ctx: &mut ExpandCtx,
163 template: &tt::Subtree,
164 kind: RepeatKind,
165 separator: Option<Separator>,
166 arena: &mut Vec<tt::TokenTree>,
167) -> ExpandResult<Fragment> {
168 let mut buf: Vec<tt::TokenTree> = Vec::new();
169 ctx.nesting.push(NestingState { idx: 0, at_end: false, hit: false });
170 // Dirty hack to make macro-expansion terminate.
171 // This should be replaced by a proper macro-by-example implementation
172 let limit = 65536;
173 let mut has_seps = 0;
174 let mut counter = 0;
175
176 loop {
177 let ExpandResult(mut t, e) = expand_subtree(ctx, template, arena);
178 let nesting_state = ctx.nesting.last_mut().unwrap();
179 if nesting_state.at_end || !nesting_state.hit {
180 break;
181 }
182 nesting_state.idx += 1;
183 nesting_state.hit = false;
184
185 counter += 1;
186 if counter == limit {
187 log::warn!(
188 "expand_tt excced in repeat pattern exceed limit => {:#?}\n{:#?}",
189 template,
190 ctx
191 );
192 break;
193 }
194
195 if e.is_some() {
196 continue;
197 }
198
199 t.delimiter = None;
200 push_subtree(&mut buf, t);
201
202 if let Some(ref sep) = separator {
203 match sep {
204 Separator::Ident(ident) => {
205 has_seps = 1;
206 buf.push(tt::Leaf::from(ident.clone()).into());
207 }
208 Separator::Literal(lit) => {
209 has_seps = 1;
210 buf.push(tt::Leaf::from(lit.clone()).into());
211 }
212
213 Separator::Puncts(puncts) => {
214 has_seps = puncts.len();
215 for punct in puncts {
216 buf.push(tt::Leaf::from(*punct).into());
217 }
218 }
219 }
220 }
221
222 if RepeatKind::ZeroOrOne == kind {
223 break;
224 }
225 }
226
227 ctx.nesting.pop().unwrap();
228 for _ in 0..has_seps {
229 buf.pop();
230 }
231
232 // Check if it is a single token subtree without any delimiter
233 // e.g {Delimiter:None> ['>'] /Delimiter:None>}
234 let tt = tt::Subtree { delimiter: None, token_trees: buf }.into();
235
236 if RepeatKind::OneOrMore == kind && counter == 0 {
237 return ExpandResult(Fragment::Tokens(tt), Some(ExpandError::UnexpectedToken));
238 }
239 ExpandResult::ok(Fragment::Tokens(tt))
240}
241
242fn push_fragment(buf: &mut Vec<tt::TokenTree>, fragment: Fragment) {
243 match fragment {
244 Fragment::Tokens(tt::TokenTree::Subtree(tt)) => push_subtree(buf, tt),
245 Fragment::Tokens(tt) | Fragment::Ast(tt) => buf.push(tt),
246 }
247}
248
249fn push_subtree(buf: &mut Vec<tt::TokenTree>, tt: tt::Subtree) {
250 match tt.delimiter {
251 None => buf.extend(tt.token_trees),
252 _ => buf.push(tt.into()),
253 }
254}