提交 c6bbb95c 编写于 作者: A Alex Crichton

syntax: Accept meta matchers in macros

This removes the `attr` matcher and adds a `meta` matcher. The previous `attr`
matcher is now ambiguous because it doesn't disambiguate whether it means inner
attribute or outer attribute.

The new behavior can still be achieved by taking an argument of the form
`#[$foo:meta]` (the brackets are part of the macro pattern).

Closes #13067
上级 cbfc0a5e
......@@ -252,7 +252,7 @@
pub use comm::select::{Select, Handle};
macro_rules! test (
{ fn $name:ident() $b:block $($a:attr)*} => (
{ fn $name:ident() $b:block $(#[$a:meta])*} => (
mod $name {
#[allow(unused_imports)];
......@@ -265,8 +265,8 @@ mod $name {
fn f() $b
$($a)* #[test] fn uv() { f() }
$($a)* #[test] fn native() {
$(#[$a])* #[test] fn uv() { f() }
$(#[$a])* #[test] fn native() {
use native;
let (tx, rx) = channel();
native::task::spawn(proc() { tx.send(f()) });
......
......@@ -19,7 +19,7 @@
use sync::atomics::{AtomicUint, INIT_ATOMIC_UINT, Relaxed};
macro_rules! iotest (
{ fn $name:ident() $b:block $($a:attr)* } => (
{ fn $name:ident() $b:block $(#[$a:meta])* } => (
mod $name {
#[allow(unused_imports)];
......@@ -43,8 +43,8 @@ mod $name {
fn f() $b
$($a)* #[test] fn green() { f() }
$($a)* #[test] fn native() {
$(#[$a])* #[test] fn green() { f() }
$(#[$a])* #[test] fn native() {
use native;
let (tx, rx) = channel();
native::task::spawn(proc() { tx.send(f()) });
......
......@@ -441,7 +441,7 @@ pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal {
"path" => {
token::NtPath(~p.parse_path(LifetimeAndTypesWithoutColons).path)
}
"attr" => token::NtAttr(@p.parse_attribute(false)),
"meta" => token::NtMeta(p.parse_meta_item()),
"tt" => {
p.quote_depth += 1u; //but in theory, non-quoted tts might be useful
let res = token::NtTT(@p.parse_token_tree());
......
......@@ -34,9 +34,6 @@ fn parse_outer_attributes(&mut self) -> Vec<ast::Attribute> {
debug!("parse_outer_attributes: self.token={:?}",
self.token);
match self.token {
token::INTERPOLATED(token::NtAttr(..)) => {
attrs.push(self.parse_attribute(false));
}
token::POUND => {
attrs.push(self.parse_attribute(false));
}
......@@ -66,11 +63,6 @@ fn parse_attribute(&mut self, permit_inner: bool) -> ast::Attribute {
debug!("parse_attributes: permit_inner={:?} self.token={:?}",
permit_inner, self.token);
let (span, value, mut style) = match self.token {
INTERPOLATED(token::NtAttr(attr)) => {
assert!(attr.node.style == ast::AttrOuter);
self.bump();
(attr.span, attr.node.value, ast::AttrOuter)
}
token::POUND => {
let lo = self.span.lo;
self.bump();
......@@ -133,9 +125,6 @@ fn parse_inner_attrs_and_next(&mut self)
let mut next_outer_attrs: Vec<ast::Attribute> = Vec::new();
loop {
let attr = match self.token {
token::INTERPOLATED(token::NtAttr(..)) => {
self.parse_attribute(true)
}
token::POUND => {
self.parse_attribute(true)
}
......@@ -163,6 +152,14 @@ fn parse_inner_attrs_and_next(&mut self)
// | IDENT = lit
// | IDENT meta_seq
fn parse_meta_item(&mut self) -> @ast::MetaItem {
match self.token {
token::INTERPOLATED(token::NtMeta(e)) => {
self.bump();
return e
}
_ => {}
}
let lo = self.span.lo;
let ident = self.parse_ident();
let name = self.id_to_interned_str(ident);
......
......@@ -113,7 +113,7 @@ pub enum Nonterminal {
NtExpr(@ast::Expr),
NtTy( P<ast::Ty>),
NtIdent(~ast::Ident, bool),
NtAttr(@ast::Attribute), // #[foo]
NtMeta(@ast::MetaItem), // stuff inside brackets for attributes
NtPath(~ast::Path),
NtTT( @ast::TokenTree), // needs @ed to break a circularity
NtMatchers(Vec<ast::Matcher> )
......@@ -129,7 +129,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
NtExpr(..) => f.pad("NtExpr(..)"),
NtTy(..) => f.pad("NtTy(..)"),
NtIdent(..) => f.pad("NtIdent(..)"),
NtAttr(..) => f.pad("NtAttr(..)"),
NtMeta(..) => f.pad("NtMeta(..)"),
NtPath(..) => f.pad("NtPath(..)"),
NtTT(..) => f.pad("NtTT(..)"),
NtMatchers(..) => f.pad("NtMatchers(..)"),
......@@ -241,7 +241,7 @@ pub fn to_str(t: &Token) -> ~str {
INTERPOLATED(ref nt) => {
match nt {
&NtExpr(e) => ::print::pprust::expr_to_str(e),
&NtAttr(e) => ::print::pprust::attribute_to_str(e),
&NtMeta(e) => ::print::pprust::meta_item_to_str(e),
_ => {
~"an interpolated " +
match *nt {
......@@ -249,7 +249,7 @@ pub fn to_str(t: &Token) -> ~str {
NtBlock(..) => ~"block",
NtStmt(..) => ~"statement",
NtPat(..) => ~"pattern",
NtAttr(..) => fail!("should have been handled"),
NtMeta(..) => fail!("should have been handled"),
NtExpr(..) => fail!("should have been handled above"),
NtTy(..) => ~"type",
NtIdent(..) => ~"identifier",
......
......@@ -11,8 +11,8 @@
#[feature(macro_rules)];
macro_rules! test ( ($nm:ident,
$a:attr,
$i:item) => (mod $nm { $a; $i }); )
#[$a:meta],
$i:item) => (mod $nm { #![$a] $i }); )
test!(a,
#[cfg(qux)],
......
......@@ -11,8 +11,8 @@
#[feature(macro_rules)];
macro_rules! test ( ($nm:ident,
$a:attr,
$i:item) => (mod $nm { $a $i }); )
#[$a:meta],
$i:item) => (mod $nm { #[$a] $i }); )
test!(a,
#[cfg(qux)],
......
......@@ -13,11 +13,11 @@
#[feature(macro_rules)];
macro_rules! compiles_fine {
($at:attr) => {
(#[$at:meta]) => {
// test that the different types of attributes work
#[attribute]
/// Documentation!
$at
#[$at]
// check that the attributes are recognised by requiring this
// to be removed to avoid a compile error
......
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-pretty - token trees can't pretty print
// compile-flags: --cfg foo
#[feature(macro_rules)];
macro_rules! compiles_fine {
($at:meta) => {
#[cfg($at)]
static MISTYPED: () = "foo";
}
}
macro_rules! emit {
($at:meta) => {
#[cfg($at)]
static MISTYPED: &'static str = "foo";
}
}
// item
compiles_fine!(bar)
emit!(foo)
fn foo() {
println!("{}", MISTYPED);
}
pub fn main() {
// statement
compiles_fine!(baz);
emit!(baz);
println!("{}", MISTYPED);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册