NFA parser for mbe matcher

This commit is contained in:
Edwin Cheng 2021-02-02 04:42:37 +08:00
parent 7f57a01b3d
commit cff2201c30
9 changed files with 592 additions and 175 deletions

View file

@ -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<String, MacroRules> {
@ -77,7 +71,7 @@ fn macro_rules_fixtures_tt() -> FxHashMap<String, tt::Subtree> {
.collect()
}
// Generate random invocation fixtures from rules
/// Generate random invocation fixtures from rules
fn invocation_fixtures(rules: &FxHashMap<String, MacroRules>) -> Vec<(String, tt::Subtree)> {
let mut seed = 123456789;
let mut res = Vec::new();
@ -86,11 +80,31 @@ fn invocation_fixtures(rules: &FxHashMap<String, MacroRules>) -> 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));
}
}
}