Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
7fdffe18
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,发现更多精彩内容 >>
提交
7fdffe18
编写于
8月 01, 2020
作者:
A
Aleksey Kladov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Use NonterminalKind for MetaVarDecl
This is more type safe and allows us to remove a few dead branches
上级
2595d75e
变更
5
显示空白变更内容
内联
并排
Showing
5 changed file
with
95 addition
and
134 deletion
+95
-134
src/librustc_ast/token.rs
src/librustc_ast/token.rs
+24
-1
src/librustc_expand/mbe.rs
src/librustc_expand/mbe.rs
+2
-2
src/librustc_expand/mbe/macro_parser.rs
src/librustc_expand/mbe/macro_parser.rs
+8
-13
src/librustc_expand/mbe/macro_rules.rs
src/librustc_expand/mbe/macro_rules.rs
+42
-115
src/librustc_expand/mbe/quoted.rs
src/librustc_expand/mbe/quoted.rs
+19
-3
未找到文件。
src/librustc_ast/token.rs
浏览文件 @
7fdffe18
...
...
@@ -760,7 +760,7 @@ pub enum Nonterminal {
#[cfg(target_arch
=
"x86_64"
)]
rustc_data_structures
::
static_assert_size!
(
Nonterminal
,
40
);
#[derive(
Copy,
Clon
e)]
#[derive(
Debug,
Copy,
Clone,
PartialEq,
RustcEncodable,
RustcDecodabl
e)]
pub
enum
NonterminalKind
{
Item
,
Block
,
...
...
@@ -796,6 +796,29 @@ pub fn from_symbol(symbol: Symbol) -> Option<NonterminalKind> {
_
=>
return
None
,
})
}
fn
symbol
(
self
)
->
Symbol
{
match
self
{
NonterminalKind
::
Item
=>
sym
::
item
,
NonterminalKind
::
Block
=>
sym
::
block
,
NonterminalKind
::
Stmt
=>
sym
::
stmt
,
NonterminalKind
::
Pat
=>
sym
::
pat
,
NonterminalKind
::
Expr
=>
sym
::
expr
,
NonterminalKind
::
Ty
=>
sym
::
ty
,
NonterminalKind
::
Ident
=>
sym
::
ident
,
NonterminalKind
::
Lifetime
=>
sym
::
lifetime
,
NonterminalKind
::
Literal
=>
sym
::
literal
,
NonterminalKind
::
Meta
=>
sym
::
meta
,
NonterminalKind
::
Path
=>
sym
::
path
,
NonterminalKind
::
Vis
=>
sym
::
vis
,
NonterminalKind
::
TT
=>
sym
::
tt
,
}
}
}
impl
fmt
::
Display
for
NonterminalKind
{
fn
fmt
(
&
self
,
f
:
&
mut
fmt
::
Formatter
<
'_
>
)
->
fmt
::
Result
{
write!
(
f
,
"{}"
,
self
.symbol
())
}
}
impl
Nonterminal
{
...
...
src/librustc_expand/mbe.rs
浏览文件 @
7fdffe18
...
...
@@ -9,7 +9,7 @@
crate
mod
quoted
;
crate
mod
transcribe
;
use
rustc_ast
::
token
::{
self
,
Token
,
TokenKind
};
use
rustc_ast
::
token
::{
self
,
NonterminalKind
,
Token
,
TokenKind
};
use
rustc_ast
::
tokenstream
::
DelimSpan
;
use
rustc_span
::
symbol
::
Ident
;
...
...
@@ -84,7 +84,7 @@ enum TokenTree {
/// e.g., `$var`
MetaVar
(
Span
,
Ident
),
/// e.g., `$var:expr`. This is only used in the left hand side of MBE macros.
MetaVarDecl
(
Span
,
Ident
/* name to bind */
,
Ident
/* kind of nonterminal */
),
MetaVarDecl
(
Span
,
Ident
/* name to bind */
,
Option
<
NonterminalKind
>
),
}
impl
TokenTree
{
...
...
src/librustc_expand/mbe/macro_parser.rs
浏览文件 @
7fdffe18
...
...
@@ -76,10 +76,10 @@
use
crate
::
mbe
::{
self
,
TokenTree
};
use
rustc_ast
::
token
::{
self
,
DocComment
,
Nonterminal
,
NonterminalKind
,
Token
};
use
rustc_ast
::
token
::{
self
,
DocComment
,
Nonterminal
,
Token
};
use
rustc_parse
::
parser
::
Parser
;
use
rustc_session
::
parse
::
ParseSess
;
use
rustc_span
::
symbol
::
{
kw
,
MacroRulesNormalizedIdent
}
;
use
rustc_span
::
symbol
::
MacroRulesNormalizedIdent
;
use
smallvec
::{
smallvec
,
SmallVec
};
...
...
@@ -378,7 +378,7 @@ fn n_rec<I: Iterator<Item = NamedMatch>>(
n_rec
(
sess
,
next_m
,
res
.by_ref
(),
ret_val
)
?
;
}
}
TokenTree
::
MetaVarDecl
(
span
,
_
,
id
)
if
id
.name
==
kw
::
Invalid
=>
{
TokenTree
::
MetaVarDecl
(
span
,
_
,
None
)
=>
{
if
sess
.missing_fragment_specifiers
.borrow_mut
()
.remove
(
&
span
)
.is_some
()
{
return
Err
((
span
,
"missing fragment specifier"
.to_string
()));
}
...
...
@@ -561,7 +561,7 @@ fn inner_parse_loop<'root, 'tt>(
}
// We need to match a metavar (but the identifier is invalid)... this is an error
TokenTree
::
MetaVarDecl
(
span
,
_
,
id
)
if
id
.name
==
kw
::
Invalid
=>
{
TokenTree
::
MetaVarDecl
(
span
,
_
,
None
)
=>
{
if
sess
.missing_fragment_specifiers
.borrow_mut
()
.remove
(
&
span
)
.is_some
()
{
return
Error
(
span
,
"missing fragment specifier"
.to_string
());
}
...
...
@@ -569,10 +569,9 @@ fn inner_parse_loop<'root, 'tt>(
// We need to match a metavar with a valid ident... call out to the black-box
// parser by adding an item to `bb_items`.
TokenTree
::
MetaVarDecl
(
_
,
_
,
id
)
=>
{
TokenTree
::
MetaVarDecl
(
_
,
_
,
Some
(
kind
)
)
=>
{
// Built-in nonterminals never start with these tokens,
// so we can eliminate them from consideration.
let
kind
=
NonterminalKind
::
from_symbol
(
id
.name
)
.unwrap
();
if
Parser
::
nonterminal_may_begin_with
(
kind
,
token
)
{
bb_items
.push
(
item
);
}
...
...
@@ -703,7 +702,7 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
let
nts
=
bb_items
.iter
()
.map
(|
item
|
match
item
.top_elts
.get_tt
(
item
.idx
)
{
TokenTree
::
MetaVarDecl
(
_
,
bind
,
name
)
=>
format!
(
"{} ('{}')"
,
name
,
bind
),
TokenTree
::
MetaVarDecl
(
_
,
bind
,
Some
(
kind
))
=>
format!
(
"{} ('{}')"
,
kind
,
bind
),
_
=>
panic!
(),
})
.collect
::
<
Vec
<
String
>>
()
...
...
@@ -733,17 +732,13 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
assert_eq!
(
bb_items
.len
(),
1
);
let
mut
item
=
bb_items
.pop
()
.unwrap
();
if
let
TokenTree
::
MetaVarDecl
(
span
,
_
,
ident
)
=
item
.top_elts
.get_tt
(
item
.idx
)
{
if
let
TokenTree
::
MetaVarDecl
(
span
,
_
,
Some
(
kind
)
)
=
item
.top_elts
.get_tt
(
item
.idx
)
{
let
match_cur
=
item
.match_cur
;
let
kind
=
NonterminalKind
::
from_symbol
(
ident
.name
)
.unwrap
();
let
nt
=
match
parser
.to_mut
()
.parse_nonterminal
(
kind
)
{
Err
(
mut
err
)
=>
{
err
.span_label
(
span
,
format!
(
"while parsing argument for this `{}` macro fragment"
,
ident
.name
),
format!
(
"while parsing argument for this `{}` macro fragment"
,
kind
),
)
.emit
();
return
ErrorReported
;
...
...
src/librustc_expand/mbe/macro_rules.rs
浏览文件 @
7fdffe18
...
...
@@ -21,7 +21,7 @@
use
rustc_session
::
parse
::
ParseSess
;
use
rustc_span
::
edition
::
Edition
;
use
rustc_span
::
hygiene
::
Transparency
;
use
rustc_span
::
symbol
::{
kw
,
sym
,
Ident
,
MacroRulesNormalizedIdent
,
Symbol
};
use
rustc_span
::
symbol
::{
kw
,
sym
,
Ident
,
MacroRulesNormalizedIdent
};
use
rustc_span
::
Span
;
use
log
::
debug
;
...
...
@@ -29,10 +29,6 @@
use
std
::
collections
::
hash_map
::
Entry
;
use
std
::{
mem
,
slice
};
const
VALID_FRAGMENT_NAMES_MSG
:
&
str
=
"valid fragment specifiers are
\
`ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`,
\
`literal`, `path`, `meta`, `tt`, `item` and `vis`"
;
crate
struct
ParserAnyMacro
<
'a
>
{
parser
:
Parser
<
'a
>
,
...
...
@@ -403,7 +399,7 @@ pub fn compile_declarative_macro(
let
diag
=
&
sess
.span_diagnostic
;
let
lhs_nm
=
Ident
::
new
(
sym
::
lhs
,
def
.span
);
let
rhs_nm
=
Ident
::
new
(
sym
::
rhs
,
def
.span
);
let
tt_spec
=
Ident
::
new
(
sym
::
tt
,
def
.span
);
let
tt_spec
=
Some
(
NonterminalKind
::
TT
);
// Parse the macro_rules! invocation
let
(
macro_rules
,
body
)
=
match
&
def
.kind
{
...
...
@@ -571,7 +567,7 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool {
TokenTree
::
Sequence
(
span
,
ref
seq
)
=>
{
if
seq
.separator
.is_none
()
&&
seq
.tts
.iter
()
.all
(|
seq_tt
|
match
*
seq_tt
{
TokenTree
::
MetaVarDecl
(
_
,
_
,
id
)
=>
id
.name
==
sym
::
vis
,
TokenTree
::
MetaVarDecl
(
_
,
_
,
Some
(
NonterminalKind
::
Vis
))
=>
true
,
TokenTree
::
Sequence
(
_
,
ref
sub_seq
)
=>
{
sub_seq
.kleene.op
==
mbe
::
KleeneOp
::
ZeroOrMore
||
sub_seq
.kleene.op
==
mbe
::
KleeneOp
::
ZeroOrOne
...
...
@@ -890,21 +886,7 @@ fn check_matcher_core(
// of NT tokens that might end the sequence `... token`.
match
*
token
{
TokenTree
::
Token
(
..
)
|
TokenTree
::
MetaVar
(
..
)
|
TokenTree
::
MetaVarDecl
(
..
)
=>
{
let
can_be_followed_by_any
;
if
let
Err
(
bad_frag
)
=
has_legal_fragment_specifier
(
sess
,
features
,
attrs
,
token
)
{
let
msg
=
format!
(
"invalid fragment specifier `{}`"
,
bad_frag
);
sess
.span_diagnostic
.struct_span_err
(
token
.span
(),
&
msg
)
.help
(
VALID_FRAGMENT_NAMES_MSG
)
.emit
();
// (This eliminates false positives and duplicates
// from error messages.)
can_be_followed_by_any
=
true
;
}
else
{
can_be_followed_by_any
=
token_can_be_followed_by_any
(
token
);
}
if
can_be_followed_by_any
{
if
token_can_be_followed_by_any
(
token
)
{
// don't need to track tokens that work with any,
last
.replace_with_irrelevant
();
// ... and don't need to check tokens that can be
...
...
@@ -967,19 +949,10 @@ fn check_matcher_core(
// Now `last` holds the complete set of NT tokens that could
// end the sequence before SUFFIX. Check that every one works with `suffix`.
'each_last
:
for
token
in
&
last
.tokens
{
if
let
TokenTree
::
MetaVarDecl
(
_
,
name
,
frag_spec
)
=
*
token
{
for
token
in
&
last
.tokens
{
if
let
TokenTree
::
MetaVarDecl
(
_
,
name
,
Some
(
kind
)
)
=
*
token
{
for
next_token
in
&
suffix_first
.tokens
{
match
is_in_follow
(
next_token
,
frag_spec
.name
)
{
IsInFollow
::
Invalid
(
msg
,
help
)
=>
{
sess
.span_diagnostic
.struct_span_err
(
next_token
.span
(),
&
msg
)
.help
(
help
)
.emit
();
// don't bother reporting every source of
// conflict for a particular element of `last`.
continue
'each_last
;
}
match
is_in_follow
(
next_token
,
kind
)
{
IsInFollow
::
Yes
=>
{}
IsInFollow
::
No
(
possible
)
=>
{
let
may_be
=
if
last
.tokens
.len
()
==
1
&&
suffix_first
.tokens
.len
()
==
1
...
...
@@ -996,22 +969,19 @@ fn check_matcher_core(
"`${name}:{frag}` {may_be} followed by `{next}`, which
\
is not allowed for `{frag}` fragments"
,
name
=
name
,
frag
=
frag_spec
,
frag
=
kind
,
next
=
quoted_tt_to_string
(
next_token
),
may_be
=
may_be
),
);
err
.span_label
(
sp
,
format!
(
"not allowed after `{}` fragments"
,
frag_spec
),
);
err
.span_label
(
sp
,
format!
(
"not allowed after `{}` fragments"
,
kind
));
let
msg
=
"allowed there are: "
;
match
possible
{
&
[]
=>
{}
&
[
t
]
=>
{
err
.note
(
&
format!
(
"only {} is allowed after `{}` fragments"
,
t
,
frag_spec
,
t
,
kind
,
));
}
ts
=>
{
...
...
@@ -1038,8 +1008,8 @@ fn check_matcher_core(
}
fn
token_can_be_followed_by_any
(
tok
:
&
mbe
::
TokenTree
)
->
bool
{
if
let
mbe
::
TokenTree
::
MetaVarDecl
(
_
,
_
,
frag_spec
)
=
*
tok
{
frag_can_be_followed_by_any
(
frag_spec
.name
)
if
let
mbe
::
TokenTree
::
MetaVarDecl
(
_
,
_
,
Some
(
kind
)
)
=
*
tok
{
frag_can_be_followed_by_any
(
kind
)
}
else
{
// (Non NT's can always be followed by anything in matchers.)
true
...
...
@@ -1054,26 +1024,23 @@ fn token_can_be_followed_by_any(tok: &mbe::TokenTree) -> bool {
/// specifier which consumes at most one token tree can be followed by
/// a fragment specifier (indeed, these fragments can be followed by
/// ANYTHING without fear of future compatibility hazards).
fn
frag_can_be_followed_by_any
(
frag
:
Symbol
)
->
bool
{
match
frag
{
sym
::
item
|
// always terminated by `}` or `;`
sym
::
block
|
// exactly one token tree
sym
::
ident
|
// exactly one token tree
sym
::
literal
|
// exactly one token tree
sym
::
meta
|
// exactly one token tree
sym
::
lifetime
|
// exactly one token tree
sym
::
tt
=>
// exactly one token tree
true
,
_
=>
false
,
fn
frag_can_be_followed_by_any
(
kind
:
NonterminalKind
)
->
bool
{
match
kind
{
NonterminalKind
::
Item
// always terminated by `}` or `;`
|
NonterminalKind
::
Block
// exactly one token tree
|
NonterminalKind
::
Ident
// exactly one token tree
|
NonterminalKind
::
Literal
// exactly one token tree
|
NonterminalKind
::
Meta
// exactly one token tree
|
NonterminalKind
::
Lifetime
// exactly one token tree
|
NonterminalKind
::
TT
=>
true
,
// exactly one token tree
_
=>
false
,
}
}
enum
IsInFollow
{
Yes
,
No
(
&
'static
[
&
'static
str
]),
Invalid
(
String
,
&
'static
str
),
}
/// Returns `true` if `frag` can legally be followed by the token `tok`. For
...
...
@@ -1084,7 +1051,7 @@ enum IsInFollow {
/// break macros that were relying on that binary operator as a
/// separator.
// when changing this do not forget to update doc/book/macros.md!
fn
is_in_follow
(
tok
:
&
mbe
::
TokenTree
,
frag
:
Symbol
)
->
IsInFollow
{
fn
is_in_follow
(
tok
:
&
mbe
::
TokenTree
,
kind
:
NonterminalKind
)
->
IsInFollow
{
use
mbe
::
TokenTree
;
if
let
TokenTree
::
Token
(
Token
{
kind
:
token
::
CloseDelim
(
_
),
..
})
=
*
tok
{
...
...
@@ -1092,18 +1059,18 @@ fn is_in_follow(tok: &mbe::TokenTree, frag: Symbol) -> IsInFollow {
// iow, we always require that `(` and `)` match, etc.
IsInFollow
::
Yes
}
else
{
match
frag
{
sym
::
i
tem
=>
{
match
kind
{
NonterminalKind
::
I
tem
=>
{
// since items *must* be followed by either a `;` or a `}`, we can
// accept anything after them
IsInFollow
::
Yes
}
sym
::
b
lock
=>
{
NonterminalKind
::
B
lock
=>
{
// anything can follow block, the braces provide an easy boundary to
// maintain
IsInFollow
::
Yes
}
sym
::
stmt
|
sym
::
e
xpr
=>
{
NonterminalKind
::
Stmt
|
NonterminalKind
::
E
xpr
=>
{
const
TOKENS
:
&
[
&
str
]
=
&
[
"`=>`"
,
"`,`"
,
"`;`"
];
match
tok
{
TokenTree
::
Token
(
token
)
=>
match
token
.kind
{
...
...
@@ -1113,7 +1080,7 @@ fn is_in_follow(tok: &mbe::TokenTree, frag: Symbol) -> IsInFollow {
_
=>
IsInFollow
::
No
(
TOKENS
),
}
}
sym
::
p
at
=>
{
NonterminalKind
::
P
at
=>
{
const
TOKENS
:
&
[
&
str
]
=
&
[
"`=>`"
,
"`,`"
,
"`=`"
,
"`|`"
,
"`if`"
,
"`in`"
];
match
tok
{
TokenTree
::
Token
(
token
)
=>
match
token
.kind
{
...
...
@@ -1124,7 +1091,7 @@ fn is_in_follow(tok: &mbe::TokenTree, frag: Symbol) -> IsInFollow {
_
=>
IsInFollow
::
No
(
TOKENS
),
}
}
sym
::
path
|
sym
::
t
y
=>
{
NonterminalKind
::
Path
|
NonterminalKind
::
T
y
=>
{
const
TOKENS
:
&
[
&
str
]
=
&
[
"`{`"
,
"`[`"
,
"`=>`"
,
"`,`"
,
"`>`"
,
"`=`"
,
"`:`"
,
"`;`"
,
"`|`"
,
"`as`"
,
"`where`"
,
...
...
@@ -1146,26 +1113,24 @@ fn is_in_follow(tok: &mbe::TokenTree, frag: Symbol) -> IsInFollow {
}
_
=>
IsInFollow
::
No
(
TOKENS
),
},
TokenTree
::
MetaVarDecl
(
_
,
_
,
frag
)
if
frag
.name
==
sym
::
block
=>
{
IsInFollow
::
Yes
}
TokenTree
::
MetaVarDecl
(
_
,
_
,
Some
(
NonterminalKind
::
Block
))
=>
IsInFollow
::
Yes
,
_
=>
IsInFollow
::
No
(
TOKENS
),
}
}
sym
::
ident
|
sym
::
l
ifetime
=>
{
NonterminalKind
::
Ident
|
NonterminalKind
::
L
ifetime
=>
{
// being a single token, idents and lifetimes are harmless
IsInFollow
::
Yes
}
sym
::
l
iteral
=>
{
NonterminalKind
::
L
iteral
=>
{
// literals may be of a single token, or two tokens (negative numbers)
IsInFollow
::
Yes
}
sym
::
meta
|
sym
::
tt
=>
{
NonterminalKind
::
Meta
|
NonterminalKind
::
TT
=>
{
// being either a single token or a delimited sequence, tt is
// harmless
IsInFollow
::
Yes
}
sym
::
v
is
=>
{
NonterminalKind
::
V
is
=>
{
// Explicitly disallow `priv`, on the off chance it comes back.
const
TOKENS
:
&
[
&
str
]
=
&
[
"`,`"
,
"an ident"
,
"a type"
];
match
tok
{
...
...
@@ -1180,62 +1145,24 @@ fn is_in_follow(tok: &mbe::TokenTree, frag: Symbol) -> IsInFollow {
}
}
},
TokenTree
::
MetaVarDecl
(
_
,
_
,
frag
)
if
frag
.name
==
sym
::
ident
||
frag
.name
==
sym
::
ty
||
frag
.name
==
sym
::
path
=>
{
IsInFollow
::
Yes
}
TokenTree
::
MetaVarDecl
(
_
,
_
,
Some
(
NonterminalKind
::
Ident
|
NonterminalKind
::
Ty
|
NonterminalKind
::
Path
),
)
=>
IsInFollow
::
Yes
,
_
=>
IsInFollow
::
No
(
TOKENS
),
}
}
kw
::
Invalid
=>
IsInFollow
::
Yes
,
_
=>
IsInFollow
::
Invalid
(
format!
(
"invalid fragment specifier `{}`"
,
frag
),
VALID_FRAGMENT_NAMES_MSG
,
),
}
}
}
fn
has_legal_fragment_specifier
(
sess
:
&
ParseSess
,
features
:
&
Features
,
attrs
:
&
[
ast
::
Attribute
],
tok
:
&
mbe
::
TokenTree
,
)
->
Result
<
(),
String
>
{
debug!
(
"has_legal_fragment_specifier({:?})"
,
tok
);
if
let
mbe
::
TokenTree
::
MetaVarDecl
(
_
,
_
,
ref
frag_spec
)
=
*
tok
{
let
frag_span
=
tok
.span
();
if
!
is_legal_fragment_specifier
(
sess
,
features
,
attrs
,
frag_spec
.name
,
frag_span
)
{
return
Err
(
frag_spec
.to_string
());
}
}
Ok
(())
}
fn
is_legal_fragment_specifier
(
_
sess
:
&
ParseSess
,
_
features
:
&
Features
,
_
attrs
:
&
[
ast
::
Attribute
],
frag_name
:
Symbol
,
_
frag_span
:
Span
,
)
->
bool
{
/*
* If new fragment specifiers are invented in nightly, `_sess`,
* `_features`, `_attrs`, and `_frag_span` will be useful here
* for checking against feature gates. See past versions of
* this function.
*/
NonterminalKind
::
from_symbol
(
frag_name
)
.is_some
()
||
frag_name
==
kw
::
Invalid
}
fn
quoted_tt_to_string
(
tt
:
&
mbe
::
TokenTree
)
->
String
{
match
*
tt
{
mbe
::
TokenTree
::
Token
(
ref
token
)
=>
pprust
::
token_to_string
(
&
token
),
mbe
::
TokenTree
::
MetaVar
(
_
,
name
)
=>
format!
(
"${}"
,
name
),
mbe
::
TokenTree
::
MetaVarDecl
(
_
,
name
,
kind
)
=>
format!
(
"${}:{}"
,
name
,
kind
),
mbe
::
TokenTree
::
MetaVarDecl
(
_
,
name
,
Some
(
kind
))
=>
format!
(
"${}:{}"
,
name
,
kind
),
mbe
::
TokenTree
::
MetaVarDecl
(
_
,
name
,
None
)
=>
format!
(
"${}:"
,
name
),
_
=>
panic!
(
"unexpected mbe::TokenTree::{{Sequence or Delimited}}
\
in follow set checker"
...
...
src/librustc_expand/mbe/quoted.rs
浏览文件 @
7fdffe18
...
...
@@ -12,6 +12,10 @@
use
rustc_data_structures
::
sync
::
Lrc
;
const
VALID_FRAGMENT_NAMES_MSG
:
&
str
=
"valid fragment specifiers are
\
`ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`,
\
`literal`, `path`, `meta`, `tt`, `item` and `vis`"
;
/// Takes a `tokenstream::TokenStream` and returns a `Vec<self::TokenTree>`. Specifically, this
/// takes a generic `TokenStream`, such as is used in the rest of the compiler, and returns a
/// collection of `TokenTree` for use in parsing a macro.
...
...
@@ -55,9 +59,21 @@ pub(super) fn parse(
Some
(
tokenstream
::
TokenTree
::
Token
(
Token
{
kind
:
token
::
Colon
,
span
}))
=>
{
match
trees
.next
()
{
Some
(
tokenstream
::
TokenTree
::
Token
(
token
))
=>
match
token
.ident
()
{
Some
((
kind
,
_
))
=>
{
Some
((
frag
,
_
))
=>
{
let
span
=
token
.span
.with_lo
(
start_sp
.lo
());
result
.push
(
TokenTree
::
MetaVarDecl
(
span
,
ident
,
kind
));
let
kind
=
token
::
NonterminalKind
::
from_symbol
(
frag
.name
)
.unwrap_or_else
(||
{
let
msg
=
format!
(
"invalid fragment specifier `{}`"
,
frag
.name
);
sess
.span_diagnostic
.struct_span_err
(
span
,
&
msg
)
.help
(
VALID_FRAGMENT_NAMES_MSG
)
.emit
();
token
::
NonterminalKind
::
Ident
});
result
.push
(
TokenTree
::
MetaVarDecl
(
span
,
ident
,
Some
(
kind
)));
continue
;
}
_
=>
token
.span
,
...
...
@@ -71,7 +87,7 @@ pub(super) fn parse(
// Macros loaded from other crates have dummy node ids.
sess
.missing_fragment_specifiers
.borrow_mut
()
.insert
(
span
,
node_id
);
}
result
.push
(
TokenTree
::
MetaVarDecl
(
span
,
ident
,
Ident
::
invalid
()
));
result
.push
(
TokenTree
::
MetaVarDecl
(
span
,
ident
,
None
));
}
// Not a metavar or no matchers allowed, so just return the tree
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录