Merge #727
727: Fix macro_rules separator parsing. r=matklad a=jrmuizel macro_rules rules are separated by ';' including an optional ';' at the end Co-authored-by: Jeff Muizelaar <jrmuizel@gmail.com>
This commit is contained in:
commit
02bacf70fa
@ -160,4 +160,50 @@ impl_froms!(TokenTree: Leaf, Subtree);
|
|||||||
impl From < Subtree > for TokenTree {fn from (it : Subtree) -> TokenTree {TokenTree :: Subtree (it)}}"
|
impl From < Subtree > for TokenTree {fn from (it : Subtree) -> TokenTree {TokenTree :: Subtree (it)}}"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn assert_expansion(rules: &MacroRules, invocation: &str, expansion: &str) {
|
||||||
|
let source_file = ast::SourceFile::parse(invocation);
|
||||||
|
let macro_invocation = source_file
|
||||||
|
.syntax()
|
||||||
|
.descendants()
|
||||||
|
.find_map(ast::MacroCall::cast)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let invocation_tt = ast_to_token_tree(macro_invocation.token_tree().unwrap()).unwrap();
|
||||||
|
|
||||||
|
let expaned = rules.expand(&invocation_tt).unwrap();
|
||||||
|
assert_eq!(expaned.to_string(), expansion);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fail_match_pattern_by_token() {
|
||||||
|
let macro_definition = r#"
|
||||||
|
macro_rules! foo {
|
||||||
|
($ i:ident) => (
|
||||||
|
mod $ i {}
|
||||||
|
);
|
||||||
|
(= $ i:ident) => (
|
||||||
|
fn $ i() {}
|
||||||
|
);
|
||||||
|
(+ $ i:ident) => (
|
||||||
|
struct $ i;
|
||||||
|
)
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let source_file = ast::SourceFile::parse(macro_definition);
|
||||||
|
let macro_definition = source_file
|
||||||
|
.syntax()
|
||||||
|
.descendants()
|
||||||
|
.find_map(ast::MacroCall::cast)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let definition_tt = ast_to_token_tree(macro_definition.token_tree().unwrap()).unwrap();
|
||||||
|
let rules = crate::MacroRules::parse(&definition_tt).unwrap();
|
||||||
|
|
||||||
|
assert_expansion(&rules, "foo! { foo }", "mod foo {}");
|
||||||
|
assert_expansion(&rules, "foo! { = bar }", "fn bar () {}");
|
||||||
|
assert_expansion(&rules, "foo! { + Baz }", "struct Baz ;");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,13 @@ pub(crate) fn parse(tt: &tt::Subtree) -> Option<crate::MacroRules> {
|
|||||||
let mut parser = TtCursor::new(tt);
|
let mut parser = TtCursor::new(tt);
|
||||||
let mut rules = Vec::new();
|
let mut rules = Vec::new();
|
||||||
while !parser.is_eof() {
|
while !parser.is_eof() {
|
||||||
rules.push(parse_rule(&mut parser)?)
|
rules.push(parse_rule(&mut parser)?);
|
||||||
|
if parser.expect_char(';') == None {
|
||||||
|
if !parser.is_eof() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Some(crate::MacroRules { rules })
|
Some(crate::MacroRules { rules })
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user