Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
33c6d3fd
R
Rust
项目概览
int
/
Rust
大约 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
33c6d3fd
编写于
8月 08, 2013
作者:
N
Niko Matsakis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Allow attributes to appear as macro arguments
Fixes #8393
上级
8f65dbfc
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
137 addition
and
59 deletion
+137
-59
src/libsyntax/ext/tt/macro_parser.rs
src/libsyntax/ext/tt/macro_parser.rs
+2
-0
src/libsyntax/parse/attr.rs
src/libsyntax/parse/attr.rs
+74
-57
src/libsyntax/parse/lexer.rs
src/libsyntax/parse/lexer.rs
+5
-1
src/libsyntax/parse/parser.rs
src/libsyntax/parse/parser.rs
+13
-1
src/libsyntax/parse/token.rs
src/libsyntax/parse/token.rs
+3
-0
src/test/compile-fail/macro-inner-attributes.rs
src/test/compile-fail/macro-inner-attributes.rs
+21
-0
src/test/compile-fail/macro-outer-attributes.rs
src/test/compile-fail/macro-outer-attributes.rs
+19
-0
未找到文件。
src/libsyntax/ext/tt/macro_parser.rs
浏览文件 @
33c6d3fd
...
...
@@ -17,6 +17,7 @@
use
parse
::
lexer
::
*
;
//resolve bug?
use
parse
::
ParseSess
;
use
parse
::
parser
::
Parser
;
use
parse
::
attr
::
parser_attr
;
use
parse
::
token
::{
Token
,
EOF
,
to_str
,
nonterminal
,
get_ident_interner
,
ident_to_str
};
use
parse
::
token
;
...
...
@@ -430,6 +431,7 @@ pub fn parse_nt(p: &Parser, name: &str) -> nonterminal {
+
token
::
to_str
(
get_ident_interner
(),
p
.token
))
},
"path"
=>
token
::
nt_path
(
p
.parse_path_with_tps
(
false
)),
"attr"
=>
token
::
nt_attr
(
@
p
.parse_attribute
(
false
)),
"tt"
=>
{
*
p
.quote_depth
+=
1u
;
//but in theory, non-quoted tts might be useful
let
res
=
token
::
nt_tt
(
@
p
.parse_token_tree
());
...
...
src/libsyntax/parse/attr.rs
浏览文件 @
33c6d3fd
...
...
@@ -9,21 +9,17 @@
// except according to those terms.
use
ast
;
use
codemap
::
spanned
;
use
codemap
::
{
spanned
,
mk_sp
}
;
use
codemap
::
BytePos
;
use
parse
::
common
::
*
;
//resolve bug?
use
parse
::
token
;
use
parse
::
parser
::
Parser
;
use
parse
::
token
::
INTERPOLATED
;
// a parser that can parse attributes.
pub
trait
parser_attr
{
fn
parse_outer_attributes
(
&
self
)
->
~
[
ast
::
Attribute
];
fn
parse_attribute
(
&
self
,
style
:
ast
::
AttrStyle
)
->
ast
::
Attribute
;
fn
parse_attribute_naked
(
&
self
,
style
:
ast
::
AttrStyle
,
lo
:
BytePos
)
->
ast
::
Attribute
;
fn
parse_attribute
(
&
self
,
permit_inner
:
bool
)
->
ast
::
Attribute
;
fn
parse_inner_attrs_and_next
(
&
self
)
->
(
~
[
ast
::
Attribute
],
~
[
ast
::
Attribute
]);
fn
parse_meta_item
(
&
self
)
->
@
ast
::
MetaItem
;
...
...
@@ -37,12 +33,17 @@ impl parser_attr for Parser {
fn
parse_outer_attributes
(
&
self
)
->
~
[
ast
::
Attribute
]
{
let
mut
attrs
:
~
[
ast
::
Attribute
]
=
~
[];
loop
{
debug!
(
"parse_outer_attributes: self.token=%?"
,
self
.token
);
match
*
self
.token
{
token
::
INTERPOLATED
(
token
::
nt_attr
(
*
))
=>
{
attrs
.push
(
self
.parse_attribute
(
false
));
}
token
::
POUND
=>
{
if
self
.look_ahead
(
1
,
|
t
|
*
t
!=
token
::
LBRACKET
)
{
break
;
}
attrs
.push
(
self
.parse_attribute
(
ast
::
AttrOuter
));
attrs
.push
(
self
.parse_attribute
(
false
));
}
token
::
DOC_COMMENT
(
s
)
=>
{
let
attr
=
::
attr
::
mk_sugared_doc_attr
(
...
...
@@ -62,23 +63,49 @@ fn parse_outer_attributes(&self) -> ~[ast::Attribute] {
return
attrs
;
}
// matches attribute = # attribute_naked
fn
parse_attribute
(
&
self
,
style
:
ast
::
AttrStyle
)
->
ast
::
Attribute
{
let
lo
=
self
.span.lo
;
self
.expect
(
&
token
::
POUND
);
return
self
.parse_attribute_naked
(
style
,
lo
);
// matches attribute = # [ meta_item ]
//
// if permit_inner is true, then a trailing `;` indicates an inner
// attribute
fn
parse_attribute
(
&
self
,
permit_inner
:
bool
)
->
ast
::
Attribute
{
debug!
(
"parse_attributes: permit_inner=%? self.token=%?"
,
permit_inner
,
self
.token
);
let
(
span
,
value
)
=
match
*
self
.token
{
INTERPOLATED
(
token
::
nt_attr
(
attr
))
=>
{
assert
!
(
attr
.node.style
==
ast
::
AttrOuter
);
self
.bump
();
(
attr
.span
,
attr
.node.value
)
}
token
::
POUND
=>
{
let
lo
=
self
.span.lo
;
self
.bump
();
self
.expect
(
&
token
::
LBRACKET
);
let
meta_item
=
self
.parse_meta_item
();
self
.expect
(
&
token
::
RBRACKET
);
let
hi
=
self
.span.hi
;
(
mk_sp
(
lo
,
hi
),
meta_item
)
}
_
=>
{
self
.fatal
(
fmt!
(
"expected `#` but found `%s`"
,
self
.this_token_to_str
()));
}
};
let
style
=
if
permit_inner
&&
*
self
.token
==
token
::
SEMI
{
self
.bump
();
ast
::
AttrInner
}
else
{
ast
::
AttrOuter
};
return
spanned
{
span
:
span
,
node
:
ast
::
Attribute_
{
style
:
style
,
value
:
value
,
is_sugared_doc
:
false
}
};
}
// matches attribute_naked = [ meta_item ]
fn
parse_attribute_naked
(
&
self
,
style
:
ast
::
AttrStyle
,
lo
:
BytePos
)
->
ast
::
Attribute
{
self
.expect
(
&
token
::
LBRACKET
);
let
meta_item
=
self
.parse_meta_item
();
self
.expect
(
&
token
::
RBRACKET
);
let
hi
=
self
.span.hi
;
return
spanned
(
lo
,
hi
,
ast
::
Attribute_
{
style
:
style
,
value
:
meta_item
,
is_sugared_doc
:
false
});
}
// Parse attributes that appear after the opening of an item, each
// terminated by a semicolon. In addition to a vector of inner attributes,
// this function also returns a vector that may contain the first outer
...
...
@@ -89,47 +116,37 @@ fn parse_attribute_naked(&self, style: ast::AttrStyle, lo: BytePos) ->
// matches inner_attrs* outer_attr?
// you can make the 'next' field an Option, but the result is going to be
// more useful as a vector.
fn
parse_inner_attrs_and_next
(
&
self
)
->
(
~
[
ast
::
Attribute
],
~
[
ast
::
Attribute
])
{
fn
parse_inner_attrs_and_next
(
&
self
)
->
(
~
[
ast
::
Attribute
],
~
[
ast
::
Attribute
])
{
let
mut
inner_attrs
:
~
[
ast
::
Attribute
]
=
~
[];
let
mut
next_outer_attrs
:
~
[
ast
::
Attribute
]
=
~
[];
loop
{
match
*
self
.token
{
token
::
POUND
=>
{
if
self
.look_ahead
(
1
,
|
t
|
*
t
!=
token
::
LBRACKET
)
{
// This is an extension
break
;
let
attr
=
match
*
self
.token
{
token
::
INTERPOLATED
(
token
::
nt_attr
(
*
))
=>
{
self
.parse_attribute
(
true
)
}
token
::
POUND
=>
{
if
self
.look_ahead
(
1
,
|
t
|
*
t
!=
token
::
LBRACKET
)
{
// This is an extension
break
;
}
self
.parse_attribute
(
true
)
}
let
attr
=
self
.parse_attribute
(
ast
::
AttrInner
);
if
*
self
.token
==
token
::
SEMI
{
token
::
DOC_COMMENT
(
s
)
=>
{
self
.bump
();
inner_attrs
.push
(
attr
);
}
else
{
// It's not really an inner attribute
let
outer_attr
=
spanned
(
attr
.span.lo
,
attr
.span.hi
,
ast
::
Attribute_
{
style
:
ast
::
AttrOuter
,
value
:
attr
.node.value
,
is_sugared_doc
:
false
});
next_outer_attrs
.push
(
outer_attr
);
break
;
::
attr
::
mk_sugared_doc_attr
(
self
.id_to_str
(
s
),
self
.span.lo
,
self
.span.hi
)
}
}
token
::
DOC_COMMENT
(
s
)
=>
{
let
attr
=
::
attr
::
mk_sugared_doc_attr
(
self
.id_to_str
(
s
),
self
.span.lo
,
self
.span.hi
);
self
.bump
();
if
attr
.node.style
==
ast
::
AttrInner
{
inner_attrs
.push
(
attr
);
}
else
{
next_outer_attrs
.push
(
attr
);
break
;
_
=>
{
break
;
}
}
_
=>
break
};
if
attr
.node.style
==
ast
::
AttrInner
{
inner_attrs
.push
(
attr
);
}
else
{
next_outer_attrs
.push
(
attr
);
break
;
}
}
(
inner_attrs
,
next_outer_attrs
)
...
...
src/libsyntax/parse/lexer.rs
浏览文件 @
33c6d3fd
...
...
@@ -129,7 +129,11 @@ fn dup(@mut self) -> @reader { dup_string_reader(self) as @reader }
impl
reader
for
TtReader
{
fn
is_eof
(
@
mut
self
)
->
bool
{
self
.cur_tok
==
token
::
EOF
}
fn
next_token
(
@
mut
self
)
->
TokenAndSpan
{
tt_next_token
(
self
)
}
fn
next_token
(
@
mut
self
)
->
TokenAndSpan
{
let
r
=
tt_next_token
(
self
);
debug!
(
"TtReader: r=%?"
,
r
);
return
r
;
}
fn
fatal
(
@
mut
self
,
m
:
~
str
)
->
!
{
self
.sp_diag
.span_fatal
(
self
.cur_span
,
m
);
}
...
...
src/libsyntax/parse/parser.rs
浏览文件 @
33c6d3fd
...
...
@@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_escape]
;
use
abi
;
use
abi
::
AbiSet
;
use
ast
::{
Sigil
,
BorrowedSigil
,
ManagedSigil
,
OwnedSigil
};
...
...
@@ -4452,7 +4454,17 @@ fn parse_item_or_view_item(&self,
attrs
:
~
[
Attribute
],
macros_allowed
:
bool
)
->
item_or_view_item
{
maybe_whole!
(
iovi
self
,
nt_item
);
match
*
self
.token
{
INTERPOLATED
(
token
::
nt_item
(
item
))
=>
{
self
.bump
();
let
new_attrs
=
vec
::
append
(
attrs
,
item
.attrs
);
return
iovi_item
(
@
ast
::
item
{
attrs
:
new_attrs
,
..
(
*
item
)
.clone
()});
}
_
=>
{}
}
let
lo
=
self
.span.lo
;
let
visibility
=
self
.parse_non_priv_visibility
();
...
...
src/libsyntax/parse/token.rs
浏览文件 @
33c6d3fd
...
...
@@ -105,6 +105,7 @@ pub enum nonterminal {
nt_expr
(
@
ast
::
expr
),
nt_ty
(
ast
::
Ty
),
nt_ident
(
ast
::
ident
,
bool
),
nt_attr
(
@
ast
::
Attribute
),
// #[foo]
nt_path
(
ast
::
Path
),
nt_tt
(
@
ast
::
token_tree
),
//needs @ed to break a circularity
nt_matchers
(
~
[
ast
::
matcher
])
...
...
@@ -205,6 +206,7 @@ pub fn to_str(input: @ident_interner, t: &Token) -> ~str {
INTERPOLATED
(
ref
nt
)
=>
{
match
nt
{
&
nt_expr
(
e
)
=>
::
print
::
pprust
::
expr_to_str
(
e
,
input
),
&
nt_attr
(
e
)
=>
::
print
::
pprust
::
attribute_to_str
(
e
,
input
),
_
=>
{
~
"an interpolated "
+
match
(
*
nt
)
{
...
...
@@ -212,6 +214,7 @@ pub fn to_str(input: @ident_interner, t: &Token) -> ~str {
nt_block
(
*
)
=>
~
"block"
,
nt_stmt
(
*
)
=>
~
"statement"
,
nt_pat
(
*
)
=>
~
"pattern"
,
nt_attr
(
*
)
=>
fail
!
(
"should have been handled"
),
nt_expr
(
*
)
=>
fail
!
(
"should have been handled above"
),
nt_ty
(
*
)
=>
~
"type"
,
nt_ident
(
*
)
=>
~
"identifier"
,
...
...
src/test/compile-fail/macro-inner-attributes.rs
0 → 100644
浏览文件 @
33c6d3fd
macro_rules!
test
(
(
$nm:ident
,
$a:attr
,
$i:item
)
=>
(
mod
$nm
{
$a
;
$i
});
)
test!
(
a
,
#[cfg(qux)]
,
pub
fn
bar
()
{
})
test!
(
b
,
#[cfg(not(qux))]
,
pub
fn
bar
()
{
})
#[qux]
fn
main
()
{
a
::
bar
();
//~^ ERROR use of undeclared module `a`
//~^^ ERROR unresolved name
//~^^^ ERROR unresolved name `a::bar`
b
::
bar
();
}
src/test/compile-fail/macro-outer-attributes.rs
0 → 100644
浏览文件 @
33c6d3fd
macro_rules!
test
(
(
$nm:ident
,
$a:attr
,
$i:item
)
=>
(
mod
$nm
{
$a
$i
});
)
test!
(
a
,
#[cfg(qux)]
,
pub
fn
bar
()
{
})
test!
(
b
,
#[cfg(not(qux))]
,
pub
fn
bar
()
{
})
// test1!(#[bar])
#[qux]
fn
main
()
{
a
::
bar
();
//~ ERROR unresolved name `a::bar`
b
::
bar
();
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录