aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_mbe')
-rw-r--r--crates/ra_mbe/src/lib.rs32
-rw-r--r--crates/ra_mbe/src/mbe_expander.rs61
-rw-r--r--crates/ra_mbe/src/mbe_expander/matcher.rs212
-rw-r--r--crates/ra_mbe/src/mbe_expander/transcriber.rs69
-rw-r--r--crates/ra_mbe/src/tests.rs4
5 files changed, 254 insertions, 124 deletions
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs
index 43afe24cc..6a9037bfc 100644
--- a/crates/ra_mbe/src/lib.rs
+++ b/crates/ra_mbe/src/lib.rs
@@ -150,7 +150,7 @@ impl MacroRules {
150 Ok(MacroRules { rules, shift: Shift::new(tt) }) 150 Ok(MacroRules { rules, shift: Shift::new(tt) })
151 } 151 }
152 152
153 pub fn expand(&self, tt: &tt::Subtree) -> Result<tt::Subtree, ExpandError> { 153 pub fn expand(&self, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
154 // apply shift 154 // apply shift
155 let mut tt = tt.clone(); 155 let mut tt = tt.clone();
156 self.shift.shift_all(&mut tt); 156 self.shift.shift_all(&mut tt);
@@ -209,5 +209,35 @@ fn validate(pattern: &tt::Subtree) -> Result<(), ParseError> {
209 Ok(()) 209 Ok(())
210} 210}
211 211
212pub struct ExpandResult<T>(pub T, pub Option<ExpandError>);
213
214impl<T> ExpandResult<T> {
215 pub fn ok(t: T) -> ExpandResult<T> {
216 ExpandResult(t, None)
217 }
218
219 pub fn only_err(err: ExpandError) -> ExpandResult<T>
220 where
221 T: Default,
222 {
223 ExpandResult(Default::default(), Some(err))
224 }
225
226 pub fn map<U>(self, f: impl FnOnce(T) -> U) -> ExpandResult<U> {
227 ExpandResult(f(self.0), self.1)
228 }
229
230 pub fn result(self) -> Result<T, ExpandError> {
231 self.1.map(Err).unwrap_or(Ok(self.0))
232 }
233}
234
235impl<T: Default> From<Result<T, ExpandError>> for ExpandResult<T> {
236 fn from(result: Result<T, ExpandError>) -> ExpandResult<T> {
237 result
238 .map_or_else(|e| ExpandResult(Default::default(), Some(e)), |it| ExpandResult(it, None))
239 }
240}
241
212#[cfg(test)] 242#[cfg(test)]
213mod tests; 243mod tests;
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs
index b455b7321..b1eacf124 100644
--- a/crates/ra_mbe/src/mbe_expander.rs
+++ b/crates/ra_mbe/src/mbe_expander.rs
@@ -8,19 +8,51 @@ mod transcriber;
8use ra_syntax::SmolStr; 8use ra_syntax::SmolStr;
9use rustc_hash::FxHashMap; 9use rustc_hash::FxHashMap;
10 10
11use crate::ExpandError; 11use crate::{ExpandError, ExpandResult};
12 12
13pub(crate) fn expand( 13pub(crate) fn expand(rules: &crate::MacroRules, input: &tt::Subtree) -> ExpandResult<tt::Subtree> {
14 rules: &crate::MacroRules, 14 expand_rules(&rules.rules, input)
15 input: &tt::Subtree,
16) -> Result<tt::Subtree, ExpandError> {
17 rules.rules.iter().find_map(|it| expand_rule(it, input).ok()).ok_or(ExpandError::NoMatchingRule)
18} 15}
19 16
20fn expand_rule(rule: &crate::Rule, input: &tt::Subtree) -> Result<tt::Subtree, ExpandError> { 17fn expand_rules(rules: &[crate::Rule], input: &tt::Subtree) -> ExpandResult<tt::Subtree> {
21 let bindings = matcher::match_(&rule.lhs, input)?; 18 let mut match_: Option<(matcher::Match, &crate::Rule)> = None;
22 let res = transcriber::transcribe(&rule.rhs, &bindings)?; 19 for rule in rules {
23 Ok(res) 20 let new_match = match matcher::match_(&rule.lhs, input) {
21 Ok(m) => m,
22 Err(_e) => {
23 // error in pattern parsing
24 continue;
25 }
26 };
27 if new_match.err.is_none() {
28 // If we find a rule that applies without errors, we're done.
29 // Unconditionally returning the transcription here makes the
30 // `test_repeat_bad_var` test fail.
31 let ExpandResult(res, transcribe_err) =
32 transcriber::transcribe(&rule.rhs, &new_match.bindings);
33 if transcribe_err.is_none() {
34 return ExpandResult::ok(res);
35 }
36 }
37 // Use the rule if we matched more tokens, or had fewer errors
38 if let Some((prev_match, _)) = &match_ {
39 if (new_match.unmatched_tts, new_match.err_count)
40 < (prev_match.unmatched_tts, prev_match.err_count)
41 {
42 match_ = Some((new_match, rule));
43 }
44 } else {
45 match_ = Some((new_match, rule));
46 }
47 }
48 if let Some((match_, rule)) = match_ {
49 // if we got here, there was no match without errors
50 let ExpandResult(result, transcribe_err) =
51 transcriber::transcribe(&rule.rhs, &match_.bindings);
52 ExpandResult(result, match_.err.or(transcribe_err))
53 } else {
54 ExpandResult(tt::Subtree::default(), Some(ExpandError::NoMatchingRule))
55 }
24} 56}
25 57
26/// The actual algorithm for expansion is not too hard, but is pretty tricky. 58/// The actual algorithm for expansion is not too hard, but is pretty tricky.
@@ -111,7 +143,7 @@ mod tests {
111 } 143 }
112 144
113 fn assert_err(macro_body: &str, invocation: &str, err: ExpandError) { 145 fn assert_err(macro_body: &str, invocation: &str, err: ExpandError) {
114 assert_eq!(expand_first(&create_rules(&format_macro(macro_body)), invocation), Err(err)); 146 assert_eq!(expand_first(&create_rules(&format_macro(macro_body)), invocation).1, Some(err));
115 } 147 }
116 148
117 fn format_macro(macro_body: &str) -> String { 149 fn format_macro(macro_body: &str) -> String {
@@ -135,10 +167,7 @@ mod tests {
135 crate::MacroRules::parse(&definition_tt).unwrap() 167 crate::MacroRules::parse(&definition_tt).unwrap()
136 } 168 }
137 169
138 fn expand_first( 170 fn expand_first(rules: &crate::MacroRules, invocation: &str) -> ExpandResult<tt::Subtree> {
139 rules: &crate::MacroRules,
140 invocation: &str,
141 ) -> Result<tt::Subtree, ExpandError> {
142 let source_file = ast::SourceFile::parse(invocation).ok().unwrap(); 171 let source_file = ast::SourceFile::parse(invocation).ok().unwrap();
143 let macro_invocation = 172 let macro_invocation =
144 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); 173 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
@@ -146,6 +175,6 @@ mod tests {
146 let (invocation_tt, _) = 175 let (invocation_tt, _) =
147 ast_to_token_tree(&macro_invocation.token_tree().unwrap()).unwrap(); 176 ast_to_token_tree(&macro_invocation.token_tree().unwrap()).unwrap();
148 177
149 expand_rule(&rules.rules[0], &invocation_tt) 178 expand_rules(&rules.rules, &invocation_tt)
150 } 179 }
151} 180}
diff --git a/crates/ra_mbe/src/mbe_expander/matcher.rs b/crates/ra_mbe/src/mbe_expander/matcher.rs
index 49c53183a..2579382da 100644
--- a/crates/ra_mbe/src/mbe_expander/matcher.rs
+++ b/crates/ra_mbe/src/mbe_expander/matcher.rs
@@ -8,6 +8,7 @@ use crate::{
8 ExpandError, 8 ExpandError,
9}; 9};
10 10
11use super::ExpandResult;
11use ra_parser::{FragmentKind::*, TreeSink}; 12use ra_parser::{FragmentKind::*, TreeSink};
12use ra_syntax::{SmolStr, SyntaxKind}; 13use ra_syntax::{SmolStr, SyntaxKind};
13use tt::buffer::{Cursor, TokenBuffer}; 14use tt::buffer::{Cursor, TokenBuffer};
@@ -58,36 +59,61 @@ macro_rules! err {
58 }; 59 };
59} 60}
60 61
61macro_rules! bail { 62#[derive(Debug, Default)]
62 ($($tt:tt)*) => { 63pub(super) struct Match {
63 return Err(err!($($tt)*)) 64 pub bindings: Bindings,
64 }; 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,
65} 70}
66 71
67pub(super) fn match_(pattern: &tt::Subtree, src: &tt::Subtree) -> Result<Bindings, ExpandError> { 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> {
68 assert!(pattern.delimiter == None); 87 assert!(pattern.delimiter == None);
69 88
70 let mut res = Bindings::default(); 89 let mut res = Match::default();
71 let mut src = TtIter::new(src); 90 let mut src = TtIter::new(src);
72 91
73 match_subtree(&mut res, pattern, &mut src)?; 92 match_subtree(&mut res, pattern, &mut src)?;
74 93
75 if src.len() > 0 { 94 if src.len() > 0 {
76 bail!("leftover tokens"); 95 res.unmatched_tts += src.len();
96 res.add_err(err!("leftover tokens"));
77 } 97 }
78 98
79 Ok(res) 99 Ok(res)
80} 100}
81 101
82fn match_subtree( 102fn match_subtree(
83 bindings: &mut Bindings, 103 res: &mut Match,
84 pattern: &tt::Subtree, 104 pattern: &tt::Subtree,
85 src: &mut TtIter, 105 src: &mut TtIter,
86) -> Result<(), ExpandError> { 106) -> Result<(), ExpandError> {
87 for op in parse_pattern(pattern) { 107 for op in parse_pattern(pattern) {
88 match op? { 108 match op? {
89 Op::TokenTree(tt::TokenTree::Leaf(lhs)) => { 109 Op::TokenTree(tt::TokenTree::Leaf(lhs)) => {
90 let rhs = src.expect_leaf().map_err(|()| err!("expected 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 };
91 match (lhs, rhs) { 117 match (lhs, rhs) {
92 ( 118 (
93 tt::Leaf::Punct(tt::Punct { char: lhs, .. }), 119 tt::Leaf::Punct(tt::Punct { char: lhs, .. }),
@@ -101,31 +127,51 @@ fn match_subtree(
101 tt::Leaf::Literal(tt::Literal { text: lhs, .. }), 127 tt::Leaf::Literal(tt::Literal { text: lhs, .. }),
102 tt::Leaf::Literal(tt::Literal { text: rhs, .. }), 128 tt::Leaf::Literal(tt::Literal { text: rhs, .. }),
103 ) if lhs == rhs => (), 129 ) if lhs == rhs => (),
104 _ => return Err(ExpandError::UnexpectedToken), 130 _ => {
131 res.add_err(ExpandError::UnexpectedToken);
132 }
105 } 133 }
106 } 134 }
107 Op::TokenTree(tt::TokenTree::Subtree(lhs)) => { 135 Op::TokenTree(tt::TokenTree::Subtree(lhs)) => {
108 let rhs = src.expect_subtree().map_err(|()| err!("expected subtree"))?; 136 let rhs = match src.expect_subtree() {
137 Ok(s) => s,
138 Err(()) => {
139 res.add_err(err!("expected subtree"));
140 continue;
141 }
142 };
109 if lhs.delimiter_kind() != rhs.delimiter_kind() { 143 if lhs.delimiter_kind() != rhs.delimiter_kind() {
110 bail!("mismatched delimiter") 144 res.add_err(err!("mismatched delimiter"));
145 continue;
111 } 146 }
112 let mut src = TtIter::new(rhs); 147 let mut src = TtIter::new(rhs);
113 match_subtree(bindings, lhs, &mut src)?; 148 match_subtree(res, lhs, &mut src)?;
114 if src.len() > 0 { 149 if src.len() > 0 {
115 bail!("leftover tokens"); 150 res.add_err(err!("leftover tokens"));
116 } 151 }
117 } 152 }
118 Op::Var { name, kind } => { 153 Op::Var { name, kind } => {
119 let kind = kind.as_ref().ok_or(ExpandError::UnexpectedToken)?; 154 let kind = match kind {
120 match match_meta_var(kind.as_str(), src)? { 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 {
121 Some(fragment) => { 163 Some(fragment) => {
122 bindings.inner.insert(name.clone(), Binding::Fragment(fragment)); 164 res.bindings.inner.insert(name.clone(), Binding::Fragment(fragment));
123 } 165 }
124 None => bindings.push_optional(name), 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);
125 } 171 }
126 } 172 }
127 Op::Repeat { subtree, kind, separator } => { 173 Op::Repeat { subtree, kind, separator } => {
128 match_repeat(bindings, subtree, kind, separator, src)? 174 match_repeat(res, subtree, kind, separator, src)?;
129 } 175 }
130 } 176 }
131 } 177 }
@@ -221,7 +267,7 @@ impl<'a> TtIter<'a> {
221 pub(crate) fn expect_fragment( 267 pub(crate) fn expect_fragment(
222 &mut self, 268 &mut self,
223 fragment_kind: ra_parser::FragmentKind, 269 fragment_kind: ra_parser::FragmentKind,
224 ) -> Result<tt::TokenTree, ()> { 270 ) -> ExpandResult<Option<tt::TokenTree>> {
225 pub(crate) struct OffsetTokenSink<'a> { 271 pub(crate) struct OffsetTokenSink<'a> {
226 pub(crate) cursor: Cursor<'a>, 272 pub(crate) cursor: Cursor<'a>,
227 pub(crate) error: bool, 273 pub(crate) error: bool,
@@ -246,45 +292,51 @@ impl<'a> TtIter<'a> {
246 292
247 ra_parser::parse_fragment(&mut src, &mut sink, fragment_kind); 293 ra_parser::parse_fragment(&mut src, &mut sink, fragment_kind);
248 294
295 let mut err = None;
249 if !sink.cursor.is_root() || sink.error { 296 if !sink.cursor.is_root() || sink.error {
250 // FIXME better recovery in this case would help completion inside macros immensely 297 err = Some(err!("expected {:?}", fragment_kind));
251 return Err(());
252 } 298 }
253 299
254 let mut curr = buffer.begin(); 300 let mut curr = buffer.begin();
255 let mut res = vec![]; 301 let mut res = vec![];
256 302
257 while curr != sink.cursor { 303 if sink.cursor.is_root() {
258 if let Some(token) = curr.token_tree() { 304 while curr != sink.cursor {
259 res.push(token); 305 if let Some(token) = curr.token_tree() {
306 res.push(token);
307 }
308 curr = curr.bump();
260 } 309 }
261 curr = curr.bump();
262 } 310 }
263 self.inner = self.inner.as_slice()[res.len()..].iter(); 311 self.inner = self.inner.as_slice()[res.len()..].iter();
264 match res.len() { 312 if res.len() == 0 && err.is_none() {
265 0 => Err(()), 313 err = Some(err!("no tokens consumed"));
266 1 => Ok(res[0].clone()), 314 }
267 _ => Ok(tt::TokenTree::Subtree(tt::Subtree { 315 let res = match res.len() {
316 1 => Some(res[0].clone()),
317 0 => None,
318 _ => Some(tt::TokenTree::Subtree(tt::Subtree {
268 delimiter: None, 319 delimiter: None,
269 token_trees: res.into_iter().cloned().collect(), 320 token_trees: res.into_iter().cloned().collect(),
270 })), 321 })),
271 } 322 };
323 ExpandResult(res, err)
272 } 324 }
273 325
274 pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> { 326 pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> {
275 let mut fork = self.clone(); 327 let mut fork = self.clone();
276 match fork.expect_fragment(Visibility) { 328 match fork.expect_fragment(Visibility) {
277 Ok(tt) => { 329 ExpandResult(tt, None) => {
278 *self = fork; 330 *self = fork;
279 Some(tt) 331 tt
280 } 332 }
281 Err(()) => None, 333 ExpandResult(_, Some(_)) => None,
282 } 334 }
283 } 335 }
284} 336}
285 337
286pub(super) fn match_repeat( 338pub(super) fn match_repeat(
287 bindings: &mut Bindings, 339 res: &mut Match,
288 pattern: &tt::Subtree, 340 pattern: &tt::Subtree,
289 kind: RepeatKind, 341 kind: RepeatKind,
290 separator: Option<Separator>, 342 separator: Option<Separator>,
@@ -304,36 +356,46 @@ pub(super) fn match_repeat(
304 } 356 }
305 } 357 }
306 358
307 let mut nested = Bindings::default(); 359 let mut nested = Match::default();
308 match match_subtree(&mut nested, pattern, &mut fork) { 360 match_subtree(&mut nested, pattern, &mut fork)?;
309 Ok(()) => { 361 if nested.err.is_none() {
310 limit -= 1; 362 limit -= 1;
311 if limit == 0 { 363 if limit == 0 {
312 log::warn!("match_lhs excced in repeat pattern exceed limit => {:#?}\n{:#?}\n{:#?}\n{:#?}", pattern, src, kind, separator); 364 log::warn!(
313 break; 365 "match_lhs exceeded repeat pattern limit => {:#?}\n{:#?}\n{:#?}\n{:#?}",
314 } 366 pattern,
315 *src = fork; 367 src,
368 kind,
369 separator
370 );
371 break;
372 }
373 *src = fork;
316 374
317 bindings.push_nested(counter, nested)?; 375 if let Err(err) = res.bindings.push_nested(counter, nested.bindings) {
318 counter += 1; 376 res.add_err(err);
319 if counter == 1 { 377 }
320 if let RepeatKind::ZeroOrOne = kind { 378 counter += 1;
321 break; 379 if counter == 1 {
322 } 380 if let RepeatKind::ZeroOrOne = kind {
381 break;
323 } 382 }
324 } 383 }
325 Err(_) => break, 384 } else {
385 break;
326 } 386 }
327 } 387 }
328 388
329 match (kind, counter) { 389 match (kind, counter) {
330 (RepeatKind::OneOrMore, 0) => return Err(ExpandError::UnexpectedToken), 390 (RepeatKind::OneOrMore, 0) => {
391 res.add_err(ExpandError::UnexpectedToken);
392 }
331 (_, 0) => { 393 (_, 0) => {
332 // Collect all empty variables in subtrees 394 // Collect all empty variables in subtrees
333 let mut vars = Vec::new(); 395 let mut vars = Vec::new();
334 collect_vars(&mut vars, pattern)?; 396 collect_vars(&mut vars, pattern)?;
335 for var in vars { 397 for var in vars {
336 bindings.push_empty(&var) 398 res.bindings.push_empty(&var)
337 } 399 }
338 } 400 }
339 _ => (), 401 _ => (),
@@ -341,7 +403,7 @@ pub(super) fn match_repeat(
341 Ok(()) 403 Ok(())
342} 404}
343 405
344fn match_meta_var(kind: &str, input: &mut TtIter) -> Result<Option<Fragment>, ExpandError> { 406fn match_meta_var(kind: &str, input: &mut TtIter) -> ExpandResult<Option<Fragment>> {
345 let fragment = match kind { 407 let fragment = match kind {
346 "path" => Path, 408 "path" => Path,
347 "expr" => Expr, 409 "expr" => Expr,
@@ -352,34 +414,32 @@ fn match_meta_var(kind: &str, input: &mut TtIter) -> Result<Option<Fragment>, Ex
352 "meta" => MetaItem, 414 "meta" => MetaItem,
353 "item" => Item, 415 "item" => Item,
354 _ => { 416 _ => {
355 let tt = match kind { 417 let tt_result = match kind {
356 "ident" => { 418 "ident" => input
357 let ident = input.expect_ident().map_err(|()| err!("expected ident"))?.clone(); 419 .expect_ident()
358 tt::Leaf::from(ident).into() 420 .map(|ident| Some(tt::Leaf::from(ident.clone()).into()))
359 } 421 .map_err(|()| err!("expected ident")),
360 "tt" => input.expect_tt().map_err(|()| err!())?.clone(), 422 "tt" => input.expect_tt().map(Some).map_err(|()| err!()),
361 "lifetime" => { 423 "lifetime" => input
362 let ident = input.expect_lifetime().map_err(|()| err!())?; 424 .expect_lifetime()
363 tt::Leaf::Ident(ident.clone()).into() 425 .map(|ident| Some(tt::Leaf::Ident(ident.clone()).into()))
364 } 426 .map_err(|()| err!("expected lifetime")),
365 "literal" => { 427 "literal" => input
366 let literal = input.expect_literal().map_err(|()| err!())?.clone(); 428 .expect_literal()
367 tt::Leaf::from(literal).into() 429 .map(|literal| Some(tt::Leaf::from(literal.clone()).into()))
368 } 430 .map_err(|()| err!()),
369 // `vis` is optional 431 // `vis` is optional
370 "vis" => match input.eat_vis() { 432 "vis" => match input.eat_vis() {
371 Some(vis) => vis, 433 Some(vis) => Ok(Some(vis)),
372 None => return Ok(None), 434 None => Ok(None),
373 }, 435 },
374 _ => return Err(ExpandError::UnexpectedToken), 436 _ => Err(ExpandError::UnexpectedToken),
375 }; 437 };
376 return Ok(Some(Fragment::Tokens(tt))); 438 return tt_result.map(|it| it.map(Fragment::Tokens)).into();
377 } 439 }
378 }; 440 };
379 let tt = 441 let result = input.expect_fragment(fragment);
380 input.expect_fragment(fragment).map_err(|()| err!("fragment did not parse as {}", kind))?; 442 result.map(|tt| if kind == "expr" { tt.map(Fragment::Ast) } else { tt.map(Fragment::Tokens) })
381 let fragment = if kind == "expr" { Fragment::Ast(tt) } else { Fragment::Tokens(tt) };
382 Ok(Some(fragment))
383} 443}
384 444
385fn collect_vars(buf: &mut Vec<SmolStr>, pattern: &tt::Subtree) -> Result<(), ExpandError> { 445fn collect_vars(buf: &mut Vec<SmolStr>, pattern: &tt::Subtree) -> Result<(), ExpandError> {
diff --git a/crates/ra_mbe/src/mbe_expander/transcriber.rs b/crates/ra_mbe/src/mbe_expander/transcriber.rs
index 7662020f3..4b173edd3 100644
--- a/crates/ra_mbe/src/mbe_expander/transcriber.rs
+++ b/crates/ra_mbe/src/mbe_expander/transcriber.rs
@@ -3,6 +3,7 @@
3 3
4use ra_syntax::SmolStr; 4use ra_syntax::SmolStr;
5 5
6use super::ExpandResult;
6use crate::{ 7use crate::{
7 mbe_expander::{Binding, Bindings, Fragment}, 8 mbe_expander::{Binding, Bindings, Fragment},
8 parser::{parse_template, Op, RepeatKind, Separator}, 9 parser::{parse_template, Op, RepeatKind, Separator},
@@ -49,10 +50,7 @@ impl Bindings {
49 } 50 }
50} 51}
51 52
52pub(super) fn transcribe( 53pub(super) fn transcribe(template: &tt::Subtree, bindings: &Bindings) -> ExpandResult<tt::Subtree> {
53 template: &tt::Subtree,
54 bindings: &Bindings,
55) -> Result<tt::Subtree, ExpandError> {
56 assert!(template.delimiter == None); 54 assert!(template.delimiter == None);
57 let mut ctx = ExpandCtx { bindings: &bindings, nesting: Vec::new() }; 55 let mut ctx = ExpandCtx { bindings: &bindings, nesting: Vec::new() };
58 expand_subtree(&mut ctx, template) 56 expand_subtree(&mut ctx, template)
@@ -75,35 +73,46 @@ struct ExpandCtx<'a> {
75 nesting: Vec<NestingState>, 73 nesting: Vec<NestingState>,
76} 74}
77 75
78fn expand_subtree(ctx: &mut ExpandCtx, template: &tt::Subtree) -> Result<tt::Subtree, ExpandError> { 76fn expand_subtree(ctx: &mut ExpandCtx, template: &tt::Subtree) -> ExpandResult<tt::Subtree> {
79 let mut buf: Vec<tt::TokenTree> = Vec::new(); 77 let mut buf: Vec<tt::TokenTree> = Vec::new();
78 let mut err = None;
80 for op in parse_template(template) { 79 for op in parse_template(template) {
81 match op? { 80 let op = match op {
81 Ok(op) => op,
82 Err(e) => {
83 err = Some(e);
84 break;
85 }
86 };
87 match op {
82 Op::TokenTree(tt @ tt::TokenTree::Leaf(..)) => buf.push(tt.clone()), 88 Op::TokenTree(tt @ tt::TokenTree::Leaf(..)) => buf.push(tt.clone()),
83 Op::TokenTree(tt::TokenTree::Subtree(tt)) => { 89 Op::TokenTree(tt::TokenTree::Subtree(tt)) => {
84 let tt = expand_subtree(ctx, tt)?; 90 let ExpandResult(tt, e) = expand_subtree(ctx, tt);
91 err = err.or(e);
85 buf.push(tt.into()); 92 buf.push(tt.into());
86 } 93 }
87 Op::Var { name, kind: _ } => { 94 Op::Var { name, kind: _ } => {
88 let fragment = expand_var(ctx, name)?; 95 let ExpandResult(fragment, e) = expand_var(ctx, name);
96 err = err.or(e);
89 push_fragment(&mut buf, fragment); 97 push_fragment(&mut buf, fragment);
90 } 98 }
91 Op::Repeat { subtree, kind, separator } => { 99 Op::Repeat { subtree, kind, separator } => {
92 let fragment = expand_repeat(ctx, subtree, kind, separator)?; 100 let ExpandResult(fragment, e) = expand_repeat(ctx, subtree, kind, separator);
101 err = err.or(e);
93 push_fragment(&mut buf, fragment) 102 push_fragment(&mut buf, fragment)
94 } 103 }
95 } 104 }
96 } 105 }
97 Ok(tt::Subtree { delimiter: template.delimiter, token_trees: buf }) 106 ExpandResult(tt::Subtree { delimiter: template.delimiter, token_trees: buf }, err)
98} 107}
99 108
100fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> Result<Fragment, ExpandError> { 109fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> {
101 let res = if v == "crate" { 110 if v == "crate" {
102 // We simply produce identifier `$crate` here. And it will be resolved when lowering ast to Path. 111 // We simply produce identifier `$crate` here. And it will be resolved when lowering ast to Path.
103 let tt = 112 let tt =
104 tt::Leaf::from(tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() }) 113 tt::Leaf::from(tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() })
105 .into(); 114 .into();
106 Fragment::Tokens(tt) 115 ExpandResult::ok(Fragment::Tokens(tt))
107 } else if !ctx.bindings.contains(v) { 116 } else if !ctx.bindings.contains(v) {
108 // Note that it is possible to have a `$var` inside a macro which is not bound. 117 // Note that it is possible to have a `$var` inside a macro which is not bound.
109 // For example: 118 // For example:
@@ -132,11 +141,13 @@ fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> Result<Fragment, ExpandError>
132 ], 141 ],
133 } 142 }
134 .into(); 143 .into();
135 Fragment::Tokens(tt) 144 ExpandResult::ok(Fragment::Tokens(tt))
136 } else { 145 } else {
137 ctx.bindings.get(&v, &mut ctx.nesting)?.clone() 146 ctx.bindings.get(&v, &mut ctx.nesting).map_or_else(
138 }; 147 |e| ExpandResult(Fragment::Tokens(tt::TokenTree::empty()), Some(e)),
139 Ok(res) 148 |b| ExpandResult::ok(b.clone()),
149 )
150 }
140} 151}
141 152
142fn expand_repeat( 153fn expand_repeat(
@@ -144,17 +155,17 @@ fn expand_repeat(
144 template: &tt::Subtree, 155 template: &tt::Subtree,
145 kind: RepeatKind, 156 kind: RepeatKind,
146 separator: Option<Separator>, 157 separator: Option<Separator>,
147) -> Result<Fragment, ExpandError> { 158) -> ExpandResult<Fragment> {
148 let mut buf: Vec<tt::TokenTree> = Vec::new(); 159 let mut buf: Vec<tt::TokenTree> = Vec::new();
149 ctx.nesting.push(NestingState { idx: 0, at_end: false, hit: false }); 160 ctx.nesting.push(NestingState { idx: 0, at_end: false, hit: false });
150 // Dirty hack to make macro-expansion terminate. 161 // Dirty hack to make macro-expansion terminate.
151 // This should be replaced by a propper macro-by-example implementation 162 // This should be replaced by a proper macro-by-example implementation
152 let limit = 65536; 163 let limit = 65536;
153 let mut has_seps = 0; 164 let mut has_seps = 0;
154 let mut counter = 0; 165 let mut counter = 0;
155 166
156 loop { 167 loop {
157 let res = expand_subtree(ctx, template); 168 let ExpandResult(mut t, e) = expand_subtree(ctx, template);
158 let nesting_state = ctx.nesting.last_mut().unwrap(); 169 let nesting_state = ctx.nesting.last_mut().unwrap();
159 if nesting_state.at_end || !nesting_state.hit { 170 if nesting_state.at_end || !nesting_state.hit {
160 break; 171 break;
@@ -172,10 +183,10 @@ fn expand_repeat(
172 break; 183 break;
173 } 184 }
174 185
175 let mut t = match res { 186 if e.is_some() {
176 Ok(t) => t, 187 continue;
177 Err(_) => continue, 188 }
178 }; 189
179 t.delimiter = None; 190 t.delimiter = None;
180 push_subtree(&mut buf, t); 191 push_subtree(&mut buf, t);
181 192
@@ -209,14 +220,14 @@ fn expand_repeat(
209 buf.pop(); 220 buf.pop();
210 } 221 }
211 222
212 if RepeatKind::OneOrMore == kind && counter == 0 {
213 return Err(ExpandError::UnexpectedToken);
214 }
215
216 // Check if it is a single token subtree without any delimiter 223 // Check if it is a single token subtree without any delimiter
217 // e.g {Delimiter:None> ['>'] /Delimiter:None>} 224 // e.g {Delimiter:None> ['>'] /Delimiter:None>}
218 let tt = tt::Subtree { delimiter: None, token_trees: buf }.into(); 225 let tt = tt::Subtree { delimiter: None, token_trees: buf }.into();
219 Ok(Fragment::Tokens(tt)) 226
227 if RepeatKind::OneOrMore == kind && counter == 0 {
228 return ExpandResult(Fragment::Tokens(tt), Some(ExpandError::UnexpectedToken));
229 }
230 ExpandResult::ok(Fragment::Tokens(tt))
220} 231}
221 232
222fn push_fragment(buf: &mut Vec<tt::TokenTree>, fragment: Fragment) { 233fn push_fragment(buf: &mut Vec<tt::TokenTree>, fragment: Fragment) {
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs
index 6d5d1e9e6..44f381938 100644
--- a/crates/ra_mbe/src/tests.rs
+++ b/crates/ra_mbe/src/tests.rs
@@ -1430,7 +1430,7 @@ impl MacroFixture {
1430 let (invocation_tt, _) = 1430 let (invocation_tt, _) =
1431 ast_to_token_tree(&macro_invocation.token_tree().unwrap()).unwrap(); 1431 ast_to_token_tree(&macro_invocation.token_tree().unwrap()).unwrap();
1432 1432
1433 self.rules.expand(&invocation_tt) 1433 self.rules.expand(&invocation_tt).result()
1434 } 1434 }
1435 1435
1436 fn assert_expand_err(&self, invocation: &str, err: &ExpandError) { 1436 fn assert_expand_err(&self, invocation: &str, err: &ExpandError) {
@@ -1662,5 +1662,5 @@ fn test_expand_bad_literal() {
1662 macro_rules! foo { ($i:literal) => {}; } 1662 macro_rules! foo { ($i:literal) => {}; }
1663 "#, 1663 "#,
1664 ) 1664 )
1665 .assert_expand_err(r#"foo!(&k");"#, &ExpandError::NoMatchingRule); 1665 .assert_expand_err(r#"foo!(&k");"#, &ExpandError::BindingError("".to_string()));
1666} 1666}