From cff2201c30bda7b346e3b47875d95a2cf9cafaa3 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 2 Feb 2021 04:42:37 +0800 Subject: NFA parser for mbe matcher --- crates/mbe/src/benchmark.rs | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) (limited to 'crates/mbe/src/benchmark.rs') diff --git a/crates/mbe/src/benchmark.rs b/crates/mbe/src/benchmark.rs index 0d0acd589..13db5eef1 100644 --- a/crates/mbe/src/benchmark.rs +++ b/crates/mbe/src/benchmark.rs @@ -40,18 +40,12 @@ fn benchmark_expand_macro_rules() { .into_iter() .map(|(id, tt)| { let res = rules[&id].expand(&tt); - if res.err.is_some() { - // FIXME: - // Currently `invocation_fixtures` will generate some correct invocations but - // cannot be expanded by mbe. We ignore errors here. - // See: https://github.com/rust-analyzer/rust-analyzer/issues/4777 - eprintln!("err from {} {:?}", id, res.err); - } + assert!(res.err.is_none()); res.value.token_trees.len() }) .sum() }; - assert_eq!(hash, 66995); + assert_eq!(hash, 69413); } fn macro_rules_fixtures() -> FxHashMap { @@ -77,7 +71,7 @@ fn macro_rules_fixtures_tt() -> FxHashMap { .collect() } -// Generate random invocation fixtures from rules +/// Generate random invocation fixtures from rules fn invocation_fixtures(rules: &FxHashMap) -> Vec<(String, tt::Subtree)> { let mut seed = 123456789; let mut res = Vec::new(); @@ -86,11 +80,31 @@ fn invocation_fixtures(rules: &FxHashMap) -> Vec<(String, tt for rule in &it.rules { // Generate twice for _ in 0..2 { - let mut subtree = tt::Subtree::default(); - for op in rule.lhs.iter() { - collect_from_op(op, &mut subtree, &mut seed); + // The input are generated by filling the `Op` randomly. + // However, there are some cases generated are ambiguous for expanding, for example: + // ```rust + // macro_rules! m { + // ($($t:ident),* as $ty:ident) => {} + // } + // m!(as u32); // error: local ambiguity: multiple parsing options: built-in NTs ident ('t') or 1 other option. + // ``` + // + // So we just skip any error cases and try again + let mut try_cnt = 0; + loop { + let mut subtree = tt::Subtree::default(); + for op in rule.lhs.iter() { + collect_from_op(op, &mut subtree, &mut seed); + } + if it.expand(&subtree).err.is_none() { + res.push((name.clone(), subtree)); + break; + } + try_cnt += 1; + if try_cnt > 100 { + panic!("invocaton fixture {} cannot be generated.\n", name); + } } - res.push((name.clone(), subtree)); } } } -- cgit v1.2.3