aboutsummaryrefslogtreecommitdiff
path: root/crates/mbe
diff options
context:
space:
mode:
Diffstat (limited to 'crates/mbe')
-rw-r--r--crates/mbe/src/expander.rs (renamed from crates/mbe/src/mbe_expander.rs)9
-rw-r--r--crates/mbe/src/expander/matcher.rs (renamed from crates/mbe/src/mbe_expander/matcher.rs)366
-rw-r--r--crates/mbe/src/expander/transcriber.rs (renamed from crates/mbe/src/mbe_expander/transcriber.rs)25
-rw-r--r--crates/mbe/src/lib.rs50
-rw-r--r--crates/mbe/src/parser.rs52
-rw-r--r--crates/mbe/src/tests.rs17
6 files changed, 243 insertions, 276 deletions
diff --git a/crates/mbe/src/mbe_expander.rs b/crates/mbe/src/expander.rs
index 802c8fb0f..e7e14b3cc 100644
--- a/crates/mbe/src/mbe_expander.rs
+++ b/crates/mbe/src/expander.rs
@@ -16,13 +16,8 @@ pub(crate) fn expand_rules(
16) -> ExpandResult<tt::Subtree> { 16) -> ExpandResult<tt::Subtree> {
17 let mut match_: Option<(matcher::Match, &crate::Rule)> = None; 17 let mut match_: Option<(matcher::Match, &crate::Rule)> = None;
18 for rule in rules { 18 for rule in rules {
19 let new_match = match matcher::match_(&rule.lhs, input) { 19 let new_match = matcher::match_(&rule.lhs, input);
20 Ok(m) => m, 20
21 Err(_e) => {
22 // error in pattern parsing
23 continue;
24 }
25 };
26 if new_match.err.is_none() { 21 if new_match.err.is_none() {
27 // If we find a rule that applies without errors, we're done. 22 // If we find a rule that applies without errors, we're done.
28 // Unconditionally returning the transcription here makes the 23 // Unconditionally returning the transcription here makes the
diff --git a/crates/mbe/src/mbe_expander/matcher.rs b/crates/mbe/src/expander/matcher.rs
index d32e60521..800931cd1 100644
--- a/crates/mbe/src/mbe_expander/matcher.rs
+++ b/crates/mbe/src/expander/matcher.rs
@@ -1,7 +1,7 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use crate::{ 3use crate::{
4 mbe_expander::{Binding, Bindings, Fragment}, 4 expander::{Binding, Bindings, Fragment},
5 parser::{Op, RepeatKind, Separator}, 5 parser::{Op, RepeatKind, Separator},
6 subtree_source::SubtreeTokenSource, 6 subtree_source::SubtreeTokenSource,
7 tt_iter::TtIter, 7 tt_iter::TtIter,
@@ -70,69 +70,38 @@ pub(super) struct Match {
70} 70}
71 71
72impl Match { 72impl Match {
73 pub(super) fn add_err(&mut self, err: ExpandError) { 73 fn add_err(&mut self, err: ExpandError) {
74 let prev_err = self.err.take(); 74 let prev_err = self.err.take();
75 self.err = prev_err.or(Some(err)); 75 self.err = prev_err.or(Some(err));
76 self.err_count += 1; 76 self.err_count += 1;
77 } 77 }
78} 78}
79 79
80// General note: These functions have two channels to return errors, a `Result` 80/// Matching errors are added to the `Match`.
81// return value and the `&mut Match`. The returned Result is for pattern parsing 81pub(super) fn match_(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
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: &MetaTemplate, src: &tt::Subtree) -> Result<Match, ExpandError> {
87 assert!(pattern.delimiter == None);
88
89 let mut res = Match::default(); 82 let mut res = Match::default();
90 let mut src = TtIter::new(src); 83 let mut src = TtIter::new(src);
91 84
92 match_subtree(&mut res, pattern, &mut src)?; 85 match_tokens(&mut res, pattern, &mut src);
93 86
94 if src.len() > 0 { 87 if src.len() > 0 {
95 res.unmatched_tts += src.len(); 88 res.unmatched_tts += src.len();
96 res.add_err(err!("leftover tokens")); 89 res.add_err(err!("leftover tokens"));
97 } 90 }
98 91
99 Ok(res) 92 res
100} 93}
101 94
102fn match_subtree( 95fn match_tokens(res: &mut Match, pattern: &MetaTemplate, src: &mut TtIter) {
103 res: &mut Match,
104 pattern: &MetaTemplate,
105 src: &mut TtIter,
106) -> Result<(), ExpandError> {
107 for op in pattern.iter() { 96 for op in pattern.iter() {
108 match op.as_ref().map_err(|err| err.clone())? { 97 match op {
109 Op::Leaf(lhs) => { 98 Op::Leaf(lhs) => {
110 let rhs = match src.expect_leaf() { 99 if let Err(err) = match_leaf(lhs, src) {
111 Ok(l) => l, 100 res.add_err(err);
112 Err(()) => { 101 continue;
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 } 102 }
134 } 103 }
135 Op::Subtree(lhs) => { 104 Op::Subtree { tokens, delimiter: delim } => {
136 let rhs = match src.expect_subtree() { 105 let rhs = match src.expect_subtree() {
137 Ok(s) => s, 106 Ok(s) => s,
138 Err(()) => { 107 Err(()) => {
@@ -140,12 +109,12 @@ fn match_subtree(
140 continue; 109 continue;
141 } 110 }
142 }; 111 };
143 if lhs.delimiter_kind() != rhs.delimiter_kind() { 112 if delim.map(|it| it.kind) != rhs.delimiter_kind() {
144 res.add_err(err!("mismatched delimiter")); 113 res.add_err(err!("mismatched delimiter"));
145 continue; 114 continue;
146 } 115 }
147 let mut src = TtIter::new(rhs); 116 let mut src = TtIter::new(rhs);
148 match_subtree(res, lhs, &mut src)?; 117 match_tokens(res, tokens, &mut src);
149 if src.len() > 0 { 118 if src.len() > 0 {
150 res.add_err(err!("leftover tokens")); 119 res.add_err(err!("leftover tokens"));
151 } 120 }
@@ -171,14 +140,170 @@ fn match_subtree(
171 res.add_err(err); 140 res.add_err(err);
172 } 141 }
173 } 142 }
174 Op::Repeat { subtree, kind, separator } => { 143 Op::Repeat { tokens: subtree, kind, separator } => {
175 match_repeat(res, subtree, *kind, separator, src)?; 144 match_repeat(res, subtree, *kind, separator, src);
176 } 145 }
177 } 146 }
178 } 147 }
148}
149
150fn match_leaf(lhs: &tt::Leaf, src: &mut TtIter) -> Result<(), ExpandError> {
151 let rhs = match src.expect_leaf() {
152 Ok(l) => l,
153 Err(()) => {
154 return Err(err!("expected leaf: `{}`", lhs));
155 }
156 };
157 match (lhs, rhs) {
158 (
159 tt::Leaf::Punct(tt::Punct { char: lhs, .. }),
160 tt::Leaf::Punct(tt::Punct { char: rhs, .. }),
161 ) if lhs == rhs => (),
162 (
163 tt::Leaf::Ident(tt::Ident { text: lhs, .. }),
164 tt::Leaf::Ident(tt::Ident { text: rhs, .. }),
165 ) if lhs == rhs => (),
166 (
167 tt::Leaf::Literal(tt::Literal { text: lhs, .. }),
168 tt::Leaf::Literal(tt::Literal { text: rhs, .. }),
169 ) if lhs == rhs => (),
170 _ => {
171 return Err(ExpandError::UnexpectedToken);
172 }
173 }
174
179 Ok(()) 175 Ok(())
180} 176}
181 177
178fn match_repeat(
179 res: &mut Match,
180 pattern: &MetaTemplate,
181 kind: RepeatKind,
182 separator: &Option<Separator>,
183 src: &mut TtIter,
184) {
185 // Dirty hack to make macro-expansion terminate.
186 // This should be replaced by a proper macro-by-example implementation
187 let mut limit = 65536;
188 let mut counter = 0;
189
190 for i in 0.. {
191 let mut fork = src.clone();
192
193 if let Some(separator) = &separator {
194 if i != 0 && !fork.eat_separator(separator) {
195 break;
196 }
197 }
198
199 let mut nested = Match::default();
200 match_tokens(&mut nested, pattern, &mut fork);
201 if nested.err.is_none() {
202 limit -= 1;
203 if limit == 0 {
204 log::warn!(
205 "match_lhs exceeded repeat pattern limit => {:#?}\n{:#?}\n{:#?}\n{:#?}",
206 pattern,
207 src,
208 kind,
209 separator
210 );
211 break;
212 }
213 *src = fork;
214
215 if let Err(err) = res.bindings.push_nested(counter, nested.bindings) {
216 res.add_err(err);
217 }
218 counter += 1;
219 if counter == 1 {
220 if let RepeatKind::ZeroOrOne = kind {
221 break;
222 }
223 }
224 } else {
225 break;
226 }
227 }
228
229 match (kind, counter) {
230 (RepeatKind::OneOrMore, 0) => {
231 res.add_err(ExpandError::UnexpectedToken);
232 }
233 (_, 0) => {
234 // Collect all empty variables in subtrees
235 let mut vars = Vec::new();
236 collect_vars(&mut vars, pattern);
237 for var in vars {
238 res.bindings.push_empty(&var)
239 }
240 }
241 _ => (),
242 }
243}
244
245fn match_meta_var(kind: &str, input: &mut TtIter) -> ExpandResult<Option<Fragment>> {
246 let fragment = match kind {
247 "path" => Path,
248 "expr" => Expr,
249 "ty" => Type,
250 "pat" => Pattern,
251 "stmt" => Statement,
252 "block" => Block,
253 "meta" => MetaItem,
254 "item" => Item,
255 _ => {
256 let tt_result = match kind {
257 "ident" => input
258 .expect_ident()
259 .map(|ident| Some(tt::Leaf::from(ident.clone()).into()))
260 .map_err(|()| err!("expected ident")),
261 "tt" => input.expect_tt().map(Some).map_err(|()| err!()),
262 "lifetime" => input
263 .expect_lifetime()
264 .map(|tt| Some(tt))
265 .map_err(|()| err!("expected lifetime")),
266 "literal" => {
267 let neg = input.eat_char('-');
268 input
269 .expect_literal()
270 .map(|literal| {
271 let lit = tt::Leaf::from(literal.clone());
272 match neg {
273 None => Some(lit.into()),
274 Some(neg) => Some(tt::TokenTree::Subtree(tt::Subtree {
275 delimiter: None,
276 token_trees: vec![neg, lit.into()],
277 })),
278 }
279 })
280 .map_err(|()| err!())
281 }
282 // `vis` is optional
283 "vis" => match input.eat_vis() {
284 Some(vis) => Ok(Some(vis)),
285 None => Ok(None),
286 },
287 _ => Err(ExpandError::UnexpectedToken),
288 };
289 return tt_result.map(|it| it.map(Fragment::Tokens)).into();
290 }
291 };
292 let result = input.expect_fragment(fragment);
293 result.map(|tt| if kind == "expr" { tt.map(Fragment::Ast) } else { tt.map(Fragment::Tokens) })
294}
295
296fn collect_vars(buf: &mut Vec<SmolStr>, pattern: &MetaTemplate) {
297 for op in pattern.iter() {
298 match op {
299 Op::Var { name, .. } => buf.push(name.clone()),
300 Op::Leaf(_) => (),
301 Op::Subtree { tokens, .. } => collect_vars(buf, tokens),
302 Op::Repeat { tokens, .. } => collect_vars(buf, tokens),
303 }
304 }
305}
306
182impl<'a> TtIter<'a> { 307impl<'a> TtIter<'a> {
183 fn eat_separator(&mut self, separator: &Separator) -> bool { 308 fn eat_separator(&mut self, separator: &Separator) -> bool {
184 let mut fork = self.clone(); 309 let mut fork = self.clone();
@@ -206,7 +331,7 @@ impl<'a> TtIter<'a> {
206 ok 331 ok
207 } 332 }
208 333
209 pub(crate) fn expect_tt(&mut self) -> Result<tt::TokenTree, ()> { 334 fn expect_tt(&mut self) -> Result<tt::TokenTree, ()> {
210 match self.peek_n(0) { 335 match self.peek_n(0) {
211 Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) if punct.char == '\'' => { 336 Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) if punct.char == '\'' => {
212 return self.expect_lifetime(); 337 return self.expect_lifetime();
@@ -267,7 +392,7 @@ impl<'a> TtIter<'a> {
267 } 392 }
268 } 393 }
269 394
270 pub(crate) fn expect_lifetime(&mut self) -> Result<tt::TokenTree, ()> { 395 fn expect_lifetime(&mut self) -> Result<tt::TokenTree, ()> {
271 let punct = self.expect_punct()?; 396 let punct = self.expect_punct()?;
272 if punct.char != '\'' { 397 if punct.char != '\'' {
273 return Err(()); 398 return Err(());
@@ -284,13 +409,13 @@ impl<'a> TtIter<'a> {
284 .into()) 409 .into())
285 } 410 }
286 411
287 pub(crate) fn expect_fragment( 412 fn expect_fragment(
288 &mut self, 413 &mut self,
289 fragment_kind: parser::FragmentKind, 414 fragment_kind: parser::FragmentKind,
290 ) -> ExpandResult<Option<tt::TokenTree>> { 415 ) -> ExpandResult<Option<tt::TokenTree>> {
291 pub(crate) struct OffsetTokenSink<'a> { 416 struct OffsetTokenSink<'a> {
292 pub(crate) cursor: Cursor<'a>, 417 cursor: Cursor<'a>,
293 pub(crate) error: bool, 418 error: bool,
294 } 419 }
295 420
296 impl<'a> TreeSink for OffsetTokenSink<'a> { 421 impl<'a> TreeSink for OffsetTokenSink<'a> {
@@ -346,7 +471,7 @@ impl<'a> TtIter<'a> {
346 ExpandResult { value: res, err } 471 ExpandResult { value: res, err }
347 } 472 }
348 473
349 pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> { 474 fn eat_vis(&mut self) -> Option<tt::TokenTree> {
350 let mut fork = self.clone(); 475 let mut fork = self.clone();
351 match fork.expect_fragment(Visibility) { 476 match fork.expect_fragment(Visibility) {
352 ExpandResult { value: tt, err: None } => { 477 ExpandResult { value: tt, err: None } => {
@@ -357,7 +482,7 @@ impl<'a> TtIter<'a> {
357 } 482 }
358 } 483 }
359 484
360 pub(crate) fn eat_char(&mut self, c: char) -> Option<tt::TokenTree> { 485 fn eat_char(&mut self, c: char) -> Option<tt::TokenTree> {
361 let mut fork = self.clone(); 486 let mut fork = self.clone();
362 match fork.expect_char(c) { 487 match fork.expect_char(c) {
363 Ok(_) => { 488 Ok(_) => {
@@ -369,134 +494,3 @@ impl<'a> TtIter<'a> {
369 } 494 }
370 } 495 }
371} 496}
372
373pub(super) fn match_repeat(
374 res: &mut Match,
375 pattern: &MetaTemplate,
376 kind: RepeatKind,
377 separator: &Option<Separator>,
378 src: &mut TtIter,
379) -> Result<(), ExpandError> {
380 // Dirty hack to make macro-expansion terminate.
381 // This should be replaced by a proper macro-by-example implementation
382 let mut limit = 65536;
383 let mut counter = 0;
384
385 for i in 0.. {
386 let mut fork = src.clone();
387
388 if let Some(separator) = &separator {
389 if i != 0 && !fork.eat_separator(separator) {
390 break;
391 }
392 }
393
394 let mut nested = Match::default();
395 match_subtree(&mut nested, pattern, &mut fork)?;
396 if nested.err.is_none() {
397 limit -= 1;
398 if limit == 0 {
399 log::warn!(
400 "match_lhs exceeded repeat pattern limit => {:#?}\n{:#?}\n{:#?}\n{:#?}",
401 pattern,
402 src,
403 kind,
404 separator
405 );
406 break;
407 }
408 *src = fork;
409
410 if let Err(err) = res.bindings.push_nested(counter, nested.bindings) {
411 res.add_err(err);
412 }
413 counter += 1;
414 if counter == 1 {
415 if let RepeatKind::ZeroOrOne = kind {
416 break;
417 }
418 }
419 } else {
420 break;
421 }
422 }
423
424 match (kind, counter) {
425 (RepeatKind::OneOrMore, 0) => {
426 res.add_err(ExpandError::UnexpectedToken);
427 }
428 (_, 0) => {
429 // Collect all empty variables in subtrees
430 let mut vars = Vec::new();
431 collect_vars(&mut vars, pattern)?;
432 for var in vars {
433 res.bindings.push_empty(&var)
434 }
435 }
436 _ => (),
437 }
438 Ok(())
439}
440
441fn match_meta_var(kind: &str, input: &mut TtIter) -> ExpandResult<Option<Fragment>> {
442 let fragment = match kind {
443 "path" => Path,
444 "expr" => Expr,
445 "ty" => Type,
446 "pat" => Pattern,
447 "stmt" => Statement,
448 "block" => Block,
449 "meta" => MetaItem,
450 "item" => Item,
451 _ => {
452 let tt_result = match kind {
453 "ident" => input
454 .expect_ident()
455 .map(|ident| Some(tt::Leaf::from(ident.clone()).into()))
456 .map_err(|()| err!("expected ident")),
457 "tt" => input.expect_tt().map(Some).map_err(|()| err!()),
458 "lifetime" => input
459 .expect_lifetime()
460 .map(|tt| Some(tt))
461 .map_err(|()| err!("expected lifetime")),
462 "literal" => {
463 let neg = input.eat_char('-');
464 input
465 .expect_literal()
466 .map(|literal| {
467 let lit = tt::Leaf::from(literal.clone());
468 match neg {
469 None => Some(lit.into()),
470 Some(neg) => Some(tt::TokenTree::Subtree(tt::Subtree {
471 delimiter: None,
472 token_trees: vec![neg, lit.into()],
473 })),
474 }
475 })
476 .map_err(|()| err!())
477 }
478 // `vis` is optional
479 "vis" => match input.eat_vis() {
480 Some(vis) => Ok(Some(vis)),
481 None => Ok(None),
482 },
483 _ => Err(ExpandError::UnexpectedToken),
484 };
485 return tt_result.map(|it| it.map(Fragment::Tokens)).into();
486 }
487 };
488 let result = input.expect_fragment(fragment);
489 result.map(|tt| if kind == "expr" { tt.map(Fragment::Ast) } else { tt.map(Fragment::Tokens) })
490}
491
492fn collect_vars(buf: &mut Vec<SmolStr>, pattern: &MetaTemplate) -> Result<(), ExpandError> {
493 for op in pattern.iter() {
494 match op.as_ref().map_err(|e| e.clone())? {
495 Op::Var { name, .. } => buf.push(name.clone()),
496 Op::Leaf(_) => (),
497 Op::Subtree(subtree) => collect_vars(buf, subtree)?,
498 Op::Repeat { subtree, .. } => collect_vars(buf, subtree)?,
499 }
500 }
501 Ok(())
502}
diff --git a/crates/mbe/src/mbe_expander/transcriber.rs b/crates/mbe/src/expander/transcriber.rs
index 59a3c80a8..78368a33e 100644
--- a/crates/mbe/src/mbe_expander/transcriber.rs
+++ b/crates/mbe/src/expander/transcriber.rs
@@ -2,10 +2,11 @@
2//! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}` 2//! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}`
3 3
4use syntax::SmolStr; 4use syntax::SmolStr;
5use tt::Delimiter;
5 6
6use super::ExpandResult; 7use super::ExpandResult;
7use crate::{ 8use crate::{
8 mbe_expander::{Binding, Bindings, Fragment}, 9 expander::{Binding, Bindings, Fragment},
9 parser::{Op, RepeatKind, Separator}, 10 parser::{Op, RepeatKind, Separator},
10 ExpandError, MetaTemplate, 11 ExpandError, MetaTemplate,
11}; 12};
@@ -54,10 +55,9 @@ pub(super) fn transcribe(
54 template: &MetaTemplate, 55 template: &MetaTemplate,
55 bindings: &Bindings, 56 bindings: &Bindings,
56) -> ExpandResult<tt::Subtree> { 57) -> ExpandResult<tt::Subtree> {
57 assert!(template.delimiter == None);
58 let mut ctx = ExpandCtx { bindings: &bindings, nesting: Vec::new() }; 58 let mut ctx = ExpandCtx { bindings: &bindings, nesting: Vec::new() };
59 let mut arena: Vec<tt::TokenTree> = Vec::new(); 59 let mut arena: Vec<tt::TokenTree> = Vec::new();
60 expand_subtree(&mut ctx, template, &mut arena) 60 expand_subtree(&mut ctx, template, None, &mut arena)
61} 61}
62 62
63#[derive(Debug)] 63#[derive(Debug)]
@@ -80,23 +80,18 @@ struct ExpandCtx<'a> {
80fn expand_subtree( 80fn expand_subtree(
81 ctx: &mut ExpandCtx, 81 ctx: &mut ExpandCtx,
82 template: &MetaTemplate, 82 template: &MetaTemplate,
83 delimiter: Option<Delimiter>,
83 arena: &mut Vec<tt::TokenTree>, 84 arena: &mut Vec<tt::TokenTree>,
84) -> ExpandResult<tt::Subtree> { 85) -> ExpandResult<tt::Subtree> {
85 // 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 86 // 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
86 let start_elements = arena.len(); 87 let start_elements = arena.len();
87 let mut err = None; 88 let mut err = None;
88 for op in template.iter() { 89 for op in template.iter() {
89 let op = match op {
90 Ok(op) => op,
91 Err(e) => {
92 err = Some(e.clone());
93 break;
94 }
95 };
96 match op { 90 match op {
97 Op::Leaf(tt) => arena.push(tt.clone().into()), 91 Op::Leaf(tt) => arena.push(tt.clone().into()),
98 Op::Subtree(tt) => { 92 Op::Subtree { tokens, delimiter } => {
99 let ExpandResult { value: tt, err: e } = expand_subtree(ctx, &tt, arena); 93 let ExpandResult { value: tt, err: e } =
94 expand_subtree(ctx, &tokens, *delimiter, arena);
100 err = err.or(e); 95 err = err.or(e);
101 arena.push(tt.into()); 96 arena.push(tt.into());
102 } 97 }
@@ -105,7 +100,7 @@ fn expand_subtree(
105 err = err.or(e); 100 err = err.or(e);
106 push_fragment(arena, fragment); 101 push_fragment(arena, fragment);
107 } 102 }
108 Op::Repeat { subtree, kind, separator } => { 103 Op::Repeat { tokens: subtree, kind, separator } => {
109 let ExpandResult { value: fragment, err: e } = 104 let ExpandResult { value: fragment, err: e } =
110 expand_repeat(ctx, subtree, *kind, separator, arena); 105 expand_repeat(ctx, subtree, *kind, separator, arena);
111 err = err.or(e); 106 err = err.or(e);
@@ -115,7 +110,7 @@ fn expand_subtree(
115 } 110 }
116 // drain the elements added in this instance of expand_subtree 111 // drain the elements added in this instance of expand_subtree
117 let tts = arena.drain(start_elements..arena.len()).collect(); 112 let tts = arena.drain(start_elements..arena.len()).collect();
118 ExpandResult { value: tt::Subtree { delimiter: template.delimiter, token_trees: tts }, err } 113 ExpandResult { value: tt::Subtree { delimiter, token_trees: tts }, err }
119} 114}
120 115
121fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr, id: tt::TokenId) -> ExpandResult<Fragment> { 116fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr, id: tt::TokenId) -> ExpandResult<Fragment> {
@@ -169,7 +164,7 @@ fn expand_repeat(
169 let mut counter = 0; 164 let mut counter = 0;
170 165
171 loop { 166 loop {
172 let ExpandResult { value: mut t, err: e } = expand_subtree(ctx, template, arena); 167 let ExpandResult { value: mut t, err: e } = expand_subtree(ctx, template, None, arena);
173 let nesting_state = ctx.nesting.last_mut().unwrap(); 168 let nesting_state = ctx.nesting.last_mut().unwrap();
174 if nesting_state.at_end || !nesting_state.hit { 169 if nesting_state.at_end || !nesting_state.hit {
175 break; 170 break;
diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs
index 35cde5f10..d80bd7a33 100644
--- a/crates/mbe/src/lib.rs
+++ b/crates/mbe/src/lib.rs
@@ -4,7 +4,7 @@
4//! `TokenTree`s as well! 4//! `TokenTree`s as well!
5 5
6mod parser; 6mod parser;
7mod mbe_expander; 7mod expander;
8mod syntax_bridge; 8mod syntax_bridge;
9mod tt_iter; 9mod tt_iter;
10mod subtree_source; 10mod subtree_source;
@@ -24,7 +24,9 @@ use crate::{
24 24
25#[derive(Debug, PartialEq, Eq)] 25#[derive(Debug, PartialEq, Eq)]
26pub enum ParseError { 26pub enum ParseError {
27 UnexpectedToken(String),
27 Expected(String), 28 Expected(String),
29 InvalidRepeat,
28 RepetitionEmptyTokenTree, 30 RepetitionEmptyTokenTree,
29} 31}
30 32
@@ -34,7 +36,6 @@ pub enum ExpandError {
34 UnexpectedToken, 36 UnexpectedToken,
35 BindingError(String), 37 BindingError(String),
36 ConversionError, 38 ConversionError,
37 InvalidRepeat,
38 ProcMacroError(tt::ExpansionError), 39 ProcMacroError(tt::ExpansionError),
39 UnresolvedProcMacro, 40 UnresolvedProcMacro,
40 Other(String), 41 Other(String),
@@ -53,7 +54,6 @@ impl fmt::Display for ExpandError {
53 ExpandError::UnexpectedToken => f.write_str("unexpected token in input"), 54 ExpandError::UnexpectedToken => f.write_str("unexpected token in input"),
54 ExpandError::BindingError(e) => f.write_str(e), 55 ExpandError::BindingError(e) => f.write_str(e),
55 ExpandError::ConversionError => f.write_str("could not convert tokens"), 56 ExpandError::ConversionError => f.write_str("could not convert tokens"),
56 ExpandError::InvalidRepeat => f.write_str("invalid repeat expression"),
57 ExpandError::ProcMacroError(e) => e.fmt(f), 57 ExpandError::ProcMacroError(e) => e.fmt(f),
58 ExpandError::UnresolvedProcMacro => f.write_str("unresolved proc macro"), 58 ExpandError::UnresolvedProcMacro => f.write_str("unresolved proc macro"),
59 ExpandError::Other(e) => f.write_str(e), 59 ExpandError::Other(e) => f.write_str(e),
@@ -92,18 +92,11 @@ struct Rule {
92} 92}
93 93
94#[derive(Clone, Debug, PartialEq, Eq)] 94#[derive(Clone, Debug, PartialEq, Eq)]
95struct MetaTemplate { 95struct MetaTemplate(Vec<Op>);
96 delimiter: Option<Delimiter>,
97 tokens: Vec<Result<Op, ExpandError>>,
98}
99 96
100impl<'a> MetaTemplate { 97impl<'a> MetaTemplate {
101 fn iter(&self) -> impl Iterator<Item = &Result<Op, ExpandError>> { 98 fn iter(&self) -> impl Iterator<Item = &Op> {
102 self.tokens.iter() 99 self.0.iter()
103 }
104
105 fn delimiter_kind(&self) -> Option<DelimiterKind> {
106 self.delimiter.map(|it| it.kind)
107 } 100 }
108} 101}
109 102
@@ -209,7 +202,7 @@ impl MacroRules {
209 // apply shift 202 // apply shift
210 let mut tt = tt.clone(); 203 let mut tt = tt.clone();
211 self.shift.shift_all(&mut tt); 204 self.shift.shift_all(&mut tt);
212 mbe_expander::expand_rules(&self.rules, &tt) 205 expander::expand_rules(&self.rules, &tt)
213 } 206 }
214 207
215 pub fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId { 208 pub fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId {
@@ -260,7 +253,7 @@ impl MacroDef {
260 // apply shift 253 // apply shift
261 let mut tt = tt.clone(); 254 let mut tt = tt.clone();
262 self.shift.shift_all(&mut tt); 255 self.shift.shift_all(&mut tt);
263 mbe_expander::expand_rules(&self.rules, &tt) 256 expander::expand_rules(&self.rules, &tt)
264 } 257 }
265 258
266 pub fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId { 259 pub fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId {
@@ -288,47 +281,38 @@ impl Rule {
288 .expect_subtree() 281 .expect_subtree()
289 .map_err(|()| ParseError::Expected("expected subtree".to_string()))?; 282 .map_err(|()| ParseError::Expected("expected subtree".to_string()))?;
290 283
291 let lhs = MetaTemplate { tokens: parse_pattern(&lhs), delimiter: None }; 284 let lhs = MetaTemplate(parse_pattern(&lhs)?);
292 let rhs = MetaTemplate { tokens: parse_template(&rhs), delimiter: None }; 285 let rhs = MetaTemplate(parse_template(&rhs)?);
293 286
294 Ok(crate::Rule { lhs, rhs }) 287 Ok(crate::Rule { lhs, rhs })
295 } 288 }
296} 289}
297 290
298fn to_parse_error(e: &ExpandError) -> ParseError {
299 let msg = match e {
300 ExpandError::InvalidRepeat => "invalid repeat".to_string(),
301 _ => "invalid macro definition".to_string(),
302 };
303 ParseError::Expected(msg)
304}
305
306fn validate(pattern: &MetaTemplate) -> Result<(), ParseError> { 291fn validate(pattern: &MetaTemplate) -> Result<(), ParseError> {
307 for op in pattern.iter() { 292 for op in pattern.iter() {
308 let op = op.as_ref().map_err(|e| to_parse_error(&e))?;
309
310 match op { 293 match op {
311 Op::Subtree(subtree) => validate(&subtree)?, 294 Op::Subtree { tokens, .. } => validate(&tokens)?,
312 Op::Repeat { subtree, separator, .. } => { 295 Op::Repeat { tokens: subtree, separator, .. } => {
313 // Checks that no repetition which could match an empty token 296 // Checks that no repetition which could match an empty token
314 // https://github.com/rust-lang/rust/blob/a58b1ed44f5e06976de2bdc4d7dc81c36a96934f/src/librustc_expand/mbe/macro_rules.rs#L558 297 // https://github.com/rust-lang/rust/blob/a58b1ed44f5e06976de2bdc4d7dc81c36a96934f/src/librustc_expand/mbe/macro_rules.rs#L558
315 298
316 if separator.is_none() { 299 if separator.is_none() {
317 if subtree.iter().all(|child_op| { 300 if subtree.iter().all(|child_op| {
318 match child_op.as_ref().map_err(to_parse_error) { 301 match child_op {
319 Ok(Op::Var { kind, .. }) => { 302 Op::Var { kind, .. } => {
320 // vis is optional 303 // vis is optional
321 if kind.as_ref().map_or(false, |it| it == "vis") { 304 if kind.as_ref().map_or(false, |it| it == "vis") {
322 return true; 305 return true;
323 } 306 }
324 } 307 }
325 Ok(Op::Repeat { kind, .. }) => { 308 Op::Repeat { kind, .. } => {
326 return matches!( 309 return matches!(
327 kind, 310 kind,
328 parser::RepeatKind::ZeroOrMore | parser::RepeatKind::ZeroOrOne 311 parser::RepeatKind::ZeroOrMore | parser::RepeatKind::ZeroOrOne
329 ) 312 )
330 } 313 }
331 _ => {} 314 Op::Leaf(_) => {}
315 Op::Subtree { .. } => {}
332 } 316 }
333 false 317 false
334 }) { 318 }) {
diff --git a/crates/mbe/src/parser.rs b/crates/mbe/src/parser.rs
index f3047972d..f891ec29c 100644
--- a/crates/mbe/src/parser.rs
+++ b/crates/mbe/src/parser.rs
@@ -3,15 +3,16 @@
3 3
4use smallvec::SmallVec; 4use smallvec::SmallVec;
5use syntax::SmolStr; 5use syntax::SmolStr;
6use tt::Delimiter;
6 7
7use crate::{tt_iter::TtIter, ExpandError, MetaTemplate}; 8use crate::{tt_iter::TtIter, MetaTemplate, ParseError};
8 9
9#[derive(Clone, Debug, PartialEq, Eq)] 10#[derive(Clone, Debug, PartialEq, Eq)]
10pub(crate) enum Op { 11pub(crate) enum Op {
11 Var { name: SmolStr, kind: Option<SmolStr>, id: tt::TokenId }, 12 Var { name: SmolStr, kind: Option<SmolStr>, id: tt::TokenId },
12 Repeat { subtree: MetaTemplate, kind: RepeatKind, separator: Option<Separator> }, 13 Repeat { tokens: MetaTemplate, kind: RepeatKind, separator: Option<Separator> },
13 Leaf(tt::Leaf), 14 Leaf(tt::Leaf),
14 Subtree(MetaTemplate), 15 Subtree { tokens: MetaTemplate, delimiter: Option<Delimiter> },
15} 16}
16 17
17#[derive(Copy, Clone, Debug, PartialEq, Eq)] 18#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -46,12 +47,12 @@ impl PartialEq for Separator {
46 } 47 }
47} 48}
48 49
49pub(crate) fn parse_template(template: &tt::Subtree) -> Vec<Result<Op, ExpandError>> { 50pub(crate) fn parse_template(template: &tt::Subtree) -> Result<Vec<Op>, ParseError> {
50 parse_inner(&template, Mode::Template) 51 parse_inner(&template, Mode::Template).into_iter().collect()
51} 52}
52 53
53pub(crate) fn parse_pattern(pattern: &tt::Subtree) -> Vec<Result<Op, ExpandError>> { 54pub(crate) fn parse_pattern(pattern: &tt::Subtree) -> Result<Vec<Op>, ParseError> {
54 parse_inner(&pattern, Mode::Pattern) 55 parse_inner(&pattern, Mode::Pattern).into_iter().collect()
55} 56}
56 57
57#[derive(Clone, Copy)] 58#[derive(Clone, Copy)]
@@ -60,7 +61,7 @@ enum Mode {
60 Template, 61 Template,
61} 62}
62 63
63fn parse_inner(tt: &tt::Subtree, mode: Mode) -> Vec<Result<Op, ExpandError>> { 64fn parse_inner(tt: &tt::Subtree, mode: Mode) -> Vec<Result<Op, ParseError>> {
64 let mut src = TtIter::new(&tt); 65 let mut src = TtIter::new(&tt);
65 std::iter::from_fn(move || { 66 std::iter::from_fn(move || {
66 let first = src.next()?; 67 let first = src.next()?;
@@ -71,7 +72,7 @@ fn parse_inner(tt: &tt::Subtree, mode: Mode) -> Vec<Result<Op, ExpandError>> {
71 72
72macro_rules! err { 73macro_rules! err {
73 ($($tt:tt)*) => { 74 ($($tt:tt)*) => {
74 ExpandError::UnexpectedToken 75 ParseError::UnexpectedToken(($($tt)*).to_string())
75 }; 76 };
76} 77}
77 78
@@ -81,7 +82,7 @@ macro_rules! bail {
81 }; 82 };
82} 83}
83 84
84fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Result<Op, ExpandError> { 85fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Result<Op, ParseError> {
85 let res = match first { 86 let res = match first {
86 tt::TokenTree::Leaf(leaf @ tt::Leaf::Punct(tt::Punct { char: '$', .. })) => { 87 tt::TokenTree::Leaf(leaf @ tt::Leaf::Punct(tt::Punct { char: '$', .. })) => {
87 // Note that the '$' itself is a valid token inside macro_rules. 88 // Note that the '$' itself is a valid token inside macro_rules.
@@ -92,17 +93,17 @@ fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Resul
92 match second { 93 match second {
93 tt::TokenTree::Subtree(subtree) => { 94 tt::TokenTree::Subtree(subtree) => {
94 let (separator, kind) = parse_repeat(src)?; 95 let (separator, kind) = parse_repeat(src)?;
95 let delimiter = subtree.delimiter; 96 let tokens = parse_inner(&subtree, mode)
96 let tokens = parse_inner(&subtree, mode); 97 .into_iter()
97 let subtree = MetaTemplate { tokens, delimiter }; 98 .collect::<Result<Vec<Op>, ParseError>>()?;
98 Op::Repeat { subtree, separator, kind } 99 Op::Repeat { tokens: MetaTemplate(tokens), separator, kind }
99 } 100 }
100 tt::TokenTree::Leaf(leaf) => match leaf { 101 tt::TokenTree::Leaf(leaf) => match leaf {
101 tt::Leaf::Punct(punct) => { 102 tt::Leaf::Punct(punct) => {
102 static UNDERSCORE: SmolStr = SmolStr::new_inline("_"); 103 static UNDERSCORE: SmolStr = SmolStr::new_inline("_");
103 104
104 if punct.char != '_' { 105 if punct.char != '_' {
105 return Err(ExpandError::UnexpectedToken); 106 return Err(ParseError::Expected("_".to_string()));
106 } 107 }
107 let name = UNDERSCORE.clone(); 108 let name = UNDERSCORE.clone();
108 let kind = eat_fragment_kind(src, mode)?; 109 let kind = eat_fragment_kind(src, mode)?;
@@ -134,16 +135,15 @@ fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Resul
134 } 135 }
135 tt::TokenTree::Leaf(tt) => Op::Leaf(tt.clone()), 136 tt::TokenTree::Leaf(tt) => Op::Leaf(tt.clone()),
136 tt::TokenTree::Subtree(subtree) => { 137 tt::TokenTree::Subtree(subtree) => {
137 let delimiter = subtree.delimiter; 138 let tokens =
138 let tokens = parse_inner(&subtree, mode); 139 parse_inner(&subtree, mode).into_iter().collect::<Result<Vec<Op>, ParseError>>()?;
139 let subtree = MetaTemplate { tokens, delimiter }; 140 Op::Subtree { tokens: MetaTemplate(tokens), delimiter: subtree.delimiter }
140 Op::Subtree(subtree)
141 } 141 }
142 }; 142 };
143 Ok(res) 143 Ok(res)
144} 144}
145 145
146fn eat_fragment_kind<'a>(src: &mut TtIter<'a>, mode: Mode) -> Result<Option<SmolStr>, ExpandError> { 146fn eat_fragment_kind<'a>(src: &mut TtIter<'a>, mode: Mode) -> Result<Option<SmolStr>, ParseError> {
147 if let Mode::Pattern = mode { 147 if let Mode::Pattern = mode {
148 src.expect_char(':').map_err(|()| err!("bad fragment specifier 1"))?; 148 src.expect_char(':').map_err(|()| err!("bad fragment specifier 1"))?;
149 let ident = src.expect_ident().map_err(|()| err!("bad fragment specifier 1"))?; 149 let ident = src.expect_ident().map_err(|()| err!("bad fragment specifier 1"))?;
@@ -156,12 +156,12 @@ fn is_boolean_literal(lit: &tt::Literal) -> bool {
156 matches!(lit.text.as_str(), "true" | "false") 156 matches!(lit.text.as_str(), "true" | "false")
157} 157}
158 158
159fn parse_repeat(src: &mut TtIter) -> Result<(Option<Separator>, RepeatKind), ExpandError> { 159fn parse_repeat(src: &mut TtIter) -> Result<(Option<Separator>, RepeatKind), ParseError> {
160 let mut separator = Separator::Puncts(SmallVec::new()); 160 let mut separator = Separator::Puncts(SmallVec::new());
161 for tt in src { 161 for tt in src {
162 let tt = match tt { 162 let tt = match tt {
163 tt::TokenTree::Leaf(leaf) => leaf, 163 tt::TokenTree::Leaf(leaf) => leaf,
164 tt::TokenTree::Subtree(_) => return Err(ExpandError::InvalidRepeat), 164 tt::TokenTree::Subtree(_) => return Err(ParseError::InvalidRepeat),
165 }; 165 };
166 let has_sep = match &separator { 166 let has_sep = match &separator {
167 Separator::Puncts(puncts) => !puncts.is_empty(), 167 Separator::Puncts(puncts) => !puncts.is_empty(),
@@ -169,7 +169,7 @@ fn parse_repeat(src: &mut TtIter) -> Result<(Option<Separator>, RepeatKind), Exp
169 }; 169 };
170 match tt { 170 match tt {
171 tt::Leaf::Ident(_) | tt::Leaf::Literal(_) if has_sep => { 171 tt::Leaf::Ident(_) | tt::Leaf::Literal(_) if has_sep => {
172 return Err(ExpandError::InvalidRepeat) 172 return Err(ParseError::InvalidRepeat)
173 } 173 }
174 tt::Leaf::Ident(ident) => separator = Separator::Ident(ident.clone()), 174 tt::Leaf::Ident(ident) => separator = Separator::Ident(ident.clone()),
175 tt::Leaf::Literal(lit) => separator = Separator::Literal(lit.clone()), 175 tt::Leaf::Literal(lit) => separator = Separator::Literal(lit.clone()),
@@ -182,11 +182,11 @@ fn parse_repeat(src: &mut TtIter) -> Result<(Option<Separator>, RepeatKind), Exp
182 match &mut separator { 182 match &mut separator {
183 Separator::Puncts(puncts) => { 183 Separator::Puncts(puncts) => {
184 if puncts.len() == 3 { 184 if puncts.len() == 3 {
185 return Err(ExpandError::InvalidRepeat); 185 return Err(ParseError::InvalidRepeat);
186 } 186 }
187 puncts.push(punct.clone()) 187 puncts.push(punct.clone())
188 } 188 }
189 _ => return Err(ExpandError::InvalidRepeat), 189 _ => return Err(ParseError::InvalidRepeat),
190 } 190 }
191 continue; 191 continue;
192 } 192 }
@@ -196,5 +196,5 @@ fn parse_repeat(src: &mut TtIter) -> Result<(Option<Separator>, RepeatKind), Exp
196 } 196 }
197 } 197 }
198 } 198 }
199 Err(ExpandError::InvalidRepeat) 199 Err(ParseError::InvalidRepeat)
200} 200}
diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs
index 8d978163d..1c467facd 100644
--- a/crates/mbe/src/tests.rs
+++ b/crates/mbe/src/tests.rs
@@ -33,19 +33,18 @@ mod rule_parsing {
33 33
34 #[test] 34 #[test]
35 fn test_invalid_arms() { 35 fn test_invalid_arms() {
36 fn check(macro_body: &str, err: &str) { 36 fn check(macro_body: &str, err: ParseError) {
37 let m = parse_macro_arm(macro_body); 37 let m = parse_macro_arm(macro_body);
38 assert_eq!(m, Err(ParseError::Expected(String::from(err)))); 38 assert_eq!(m, Err(err.into()));
39 } 39 }
40 check("invalid", ParseError::Expected("expected subtree".into()));
40 41
41 check("invalid", "expected subtree"); 42 check("$i:ident => ()", ParseError::Expected("expected subtree".into()));
43 check("($i:ident) ()", ParseError::Expected("expected `=`".into()));
44 check("($($i:ident)_) => ()", ParseError::InvalidRepeat);
42 45
43 check("$i:ident => ()", "expected subtree"); 46 check("($i) => ($i)", ParseError::UnexpectedToken("bad fragment specifier 1".into()));
44 check("($i:ident) ()", "expected `=`"); 47 check("($i:) => ($i)", ParseError::UnexpectedToken("bad fragment specifier 1".into()));
45 check("($($i:ident)_) => ()", "invalid repeat");
46
47 check("($i) => ($i)", "invalid macro definition");
48 check("($i:) => ($i)", "invalid macro definition");
49 } 48 }
50 49
51 fn parse_macro_arm(arm_definition: &str) -> Result<crate::MacroRules, ParseError> { 50 fn parse_macro_arm(arm_definition: &str) -> Result<crate::MacroRules, ParseError> {