add block matcher

This commit is contained in:
Edwin Cheng 2019-04-19 19:33:29 +08:00
parent 8092b6487f
commit 762819864f
6 changed files with 64 additions and 0 deletions

View file

@ -743,4 +743,23 @@ MACRO_ITEMS@[0; 40)
);
assert_expansion(&rules, "foo! { { 1; } }", "fn foo () {1 ;}");
}
#[test]
fn test_meta() {
let rules = create_rules(
r#"
macro_rules! foo {
($ i:meta) => (
#[$ i]
fn bar() {}
)
}
"#,
);
assert_expansion(
&rules,
r#"foo! { cfg(target_os = "windows") }"#,
r#"# [cfg (target_os = "windows")] fn bar () {}"#,
);
}
}

View file

@ -166,6 +166,11 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings,
input.eat_block().ok_or(ExpandError::UnexpectedToken)?.clone();
res.inner.insert(text.clone(), Binding::Simple(block.into()));
}
"meta" => {
let meta =
input.eat_meta().ok_or(ExpandError::UnexpectedToken)?.clone();
res.inner.insert(text.clone(), Binding::Simple(meta.into()));
}
"item" => {
let item =
input.eat_item().ok_or(ExpandError::UnexpectedToken)?.clone();

View file

@ -50,6 +50,10 @@ impl<'a> Parser<'a> {
self.parse(ra_parser::parse_block)
}
pub fn parse_meta(self) -> Option<tt::TokenTree> {
self.parse(ra_parser::parse_meta)
}
pub fn parse_item(self) -> Option<tt::TokenTree> {
self.parse(ra_parser::parse_item)
}

View file

@ -109,6 +109,11 @@ impl<'a> TtCursor<'a> {
parser.parse_block()
}
pub(crate) fn eat_meta(&mut self) -> Option<tt::TokenTree> {
let parser = Parser::new(&mut self.pos, self.subtree);
parser.parse_meta()
}
pub(crate) fn eat_item(&mut self) -> Option<tt::TokenTree> {
let parser = Parser::new(&mut self.pos, self.subtree);
parser.parse_item()

View file

@ -99,6 +99,33 @@ pub(crate) fn block(p: &mut Parser) {
expressions::block(p);
}
// Parse a meta item , which excluded [], e.g : #[ MetaItem ]
pub(crate) fn meta_item(p: &mut Parser) {
fn is_delimiter(p: &mut Parser) -> bool {
match p.current() {
L_CURLY | L_PAREN | L_BRACK => true,
_ => false,
}
}
if is_delimiter(p) {
items::token_tree(p);
return;
}
let m = p.start();
while !p.at(EOF) {
if is_delimiter(p) {
items::token_tree(p);
break;
} else {
p.bump();
}
}
m.complete(p, TOKEN_TREE);
}
pub(crate) fn item(p: &mut Parser) {
items::item_or_macro(p, true, items::ItemFlavor::Mod)
}

View file

@ -98,6 +98,10 @@ pub fn parse_block(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink)
parse_from_tokens(token_source, tree_sink, grammar::block);
}
pub fn parse_meta(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) {
parse_from_tokens(token_source, tree_sink, grammar::meta_item);
}
/// Parse given tokens into the given sink as an item
pub fn parse_item(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) {
parse_from_tokens(token_source, tree_sink, grammar::item);