Reduce the size of Token
and make it cheaper to clone by refactoring
`Token::Interpolated(Nonterminal)` -> `Token::Interpolated(Rc<Nonterminal>)`.
This commit is contained in:
parent
5f280a5c60
commit
eb3ac29a10
@ -80,67 +80,71 @@ pub mod rt {
|
||||
|
||||
impl ToTokens for ast::Path {
|
||||
fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
|
||||
vec![TokenTree::Token(DUMMY_SP,
|
||||
token::Interpolated(token::NtPath(Box::new(self.clone()))))]
|
||||
let nt = token::NtPath(self.clone());
|
||||
vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))]
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for ast::Ty {
|
||||
fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
|
||||
vec![TokenTree::Token(self.span, token::Interpolated(token::NtTy(P(self.clone()))))]
|
||||
let nt = token::NtTy(P(self.clone()));
|
||||
vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))]
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for ast::Block {
|
||||
fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
|
||||
vec![TokenTree::Token(self.span, token::Interpolated(token::NtBlock(P(self.clone()))))]
|
||||
let nt = token::NtBlock(P(self.clone()));
|
||||
vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))]
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for ast::Generics {
|
||||
fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
|
||||
vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtGenerics(self.clone())))]
|
||||
let nt = token::NtGenerics(self.clone());
|
||||
vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))]
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for ast::WhereClause {
|
||||
fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
|
||||
vec![TokenTree::Token(DUMMY_SP,
|
||||
token::Interpolated(token::NtWhereClause(self.clone())))]
|
||||
let nt = token::NtWhereClause(self.clone());
|
||||
vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))]
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for P<ast::Item> {
|
||||
fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
|
||||
vec![TokenTree::Token(self.span, token::Interpolated(token::NtItem(self.clone())))]
|
||||
let nt = token::NtItem(self.clone());
|
||||
vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))]
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for ast::ImplItem {
|
||||
fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
|
||||
vec![TokenTree::Token(self.span,
|
||||
token::Interpolated(token::NtImplItem(P(self.clone()))))]
|
||||
let nt = token::NtImplItem(self.clone());
|
||||
vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))]
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for P<ast::ImplItem> {
|
||||
fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
|
||||
vec![TokenTree::Token(self.span, token::Interpolated(token::NtImplItem(self.clone())))]
|
||||
let nt = token::NtImplItem((**self).clone());
|
||||
vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))]
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for ast::TraitItem {
|
||||
fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
|
||||
vec![TokenTree::Token(self.span,
|
||||
token::Interpolated(token::NtTraitItem(P(self.clone()))))]
|
||||
let nt = token::NtTraitItem(self.clone());
|
||||
vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))]
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for ast::Stmt {
|
||||
fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
|
||||
let mut tts = vec![
|
||||
TokenTree::Token(self.span, token::Interpolated(token::NtStmt(P(self.clone()))))
|
||||
];
|
||||
let nt = token::NtStmt(self.clone());
|
||||
let mut tts = vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))];
|
||||
|
||||
// Some statements require a trailing semicolon.
|
||||
if classify::stmt_ends_with_semi(&self.node) {
|
||||
@ -153,31 +157,36 @@ pub mod rt {
|
||||
|
||||
impl ToTokens for P<ast::Expr> {
|
||||
fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
|
||||
vec![TokenTree::Token(self.span, token::Interpolated(token::NtExpr(self.clone())))]
|
||||
let nt = token::NtExpr(self.clone());
|
||||
vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))]
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for P<ast::Pat> {
|
||||
fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
|
||||
vec![TokenTree::Token(self.span, token::Interpolated(token::NtPat(self.clone())))]
|
||||
let nt = token::NtPat(self.clone());
|
||||
vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))]
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for ast::Arm {
|
||||
fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
|
||||
vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtArm(self.clone())))]
|
||||
let nt = token::NtArm(self.clone());
|
||||
vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))]
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for ast::Arg {
|
||||
fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
|
||||
vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtArg(self.clone())))]
|
||||
let nt = token::NtArg(self.clone());
|
||||
vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))]
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for P<ast::Block> {
|
||||
fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
|
||||
vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtBlock(self.clone())))]
|
||||
let nt = token::NtBlock(self.clone());
|
||||
vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))]
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,7 +213,8 @@ pub mod rt {
|
||||
|
||||
impl ToTokens for P<ast::MetaItem> {
|
||||
fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
|
||||
vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtMeta(self.clone())))]
|
||||
let nt = token::NtMeta(self.clone());
|
||||
vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,6 @@ use parse::token::{DocComment, MatchNt, SubstNt};
|
||||
use parse::token::{Token, Nonterminal};
|
||||
use parse::token;
|
||||
use print::pprust;
|
||||
use ptr::P;
|
||||
use tokenstream::{self, TokenTree};
|
||||
use util::small_vector::SmallVector;
|
||||
|
||||
@ -198,7 +197,7 @@ pub fn initial_matcher_pos(ms: Vec<TokenTree>, sep: Option<Token>, lo: BytePos)
|
||||
|
||||
pub enum NamedMatch {
|
||||
MatchedSeq(Vec<Rc<NamedMatch>>, syntax_pos::Span),
|
||||
MatchedNonterminal(Nonterminal)
|
||||
MatchedNonterminal(Rc<Nonterminal>)
|
||||
}
|
||||
|
||||
pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc<NamedMatch>])
|
||||
@ -482,7 +481,7 @@ pub fn parse(sess: &ParseSess, mut rdr: TtReader, ms: &[TokenTree]) -> NamedPars
|
||||
if let TokenTree::Token(span, MatchNt(_, ident)) = ei.top_elts.get_tt(ei.idx) {
|
||||
let match_cur = ei.match_cur;
|
||||
(&mut ei.matches[match_cur]).push(Rc::new(MatchedNonterminal(
|
||||
parse_nt(&mut rust_parser, span, &ident.name.as_str()))));
|
||||
Rc::new(parse_nt(&mut rust_parser, span, &ident.name.as_str())))));
|
||||
ei.idx += 1;
|
||||
ei.match_cur += 1;
|
||||
} else {
|
||||
@ -503,7 +502,7 @@ pub fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
|
||||
"tt" => {
|
||||
p.quote_depth += 1; //but in theory, non-quoted tts might be useful
|
||||
let res: ::parse::PResult<'a, _> = p.parse_token_tree();
|
||||
let res = token::NtTT(P(panictry!(res)));
|
||||
let res = token::NtTT(panictry!(res));
|
||||
p.quote_depth -= 1;
|
||||
return res;
|
||||
}
|
||||
@ -521,7 +520,7 @@ pub fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
|
||||
},
|
||||
"block" => token::NtBlock(panictry!(p.parse_block())),
|
||||
"stmt" => match panictry!(p.parse_stmt()) {
|
||||
Some(s) => token::NtStmt(P(s)),
|
||||
Some(s) => token::NtStmt(s),
|
||||
None => {
|
||||
p.fatal("expected a statement").emit();
|
||||
panic!(FatalError);
|
||||
@ -534,7 +533,7 @@ pub fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
|
||||
"ident" => match p.token {
|
||||
token::Ident(sn) => {
|
||||
p.bump();
|
||||
token::NtIdent(Box::new(Spanned::<Ident>{node: sn, span: p.span}))
|
||||
token::NtIdent(Spanned::<Ident>{node: sn, span: p.span})
|
||||
}
|
||||
_ => {
|
||||
let token_str = pprust::token_to_string(&p.token);
|
||||
@ -544,7 +543,7 @@ pub fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
|
||||
}
|
||||
},
|
||||
"path" => {
|
||||
token::NtPath(Box::new(panictry!(p.parse_path(PathStyle::Type))))
|
||||
token::NtPath(panictry!(p.parse_path(PathStyle::Type)))
|
||||
},
|
||||
"meta" => token::NtMeta(panictry!(p.parse_meta_item())),
|
||||
// this is not supposed to happen, since it has been checked
|
||||
|
@ -236,12 +236,14 @@ pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension {
|
||||
// Extract the arguments:
|
||||
let lhses = match **argument_map.get(&lhs_nm).unwrap() {
|
||||
MatchedSeq(ref s, _) => {
|
||||
s.iter().map(|m| match **m {
|
||||
MatchedNonterminal(NtTT(ref tt)) => {
|
||||
valid &= check_lhs_nt_follows(sess, tt);
|
||||
(**tt).clone()
|
||||
s.iter().map(|m| {
|
||||
if let MatchedNonterminal(ref nt) = **m {
|
||||
if let NtTT(ref tt) = **nt {
|
||||
valid &= check_lhs_nt_follows(sess, tt);
|
||||
return (*tt).clone();
|
||||
}
|
||||
}
|
||||
_ => sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs")
|
||||
sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs")
|
||||
}).collect::<Vec<TokenTree>>()
|
||||
}
|
||||
_ => sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs")
|
||||
@ -249,9 +251,13 @@ pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension {
|
||||
|
||||
let rhses = match **argument_map.get(&rhs_nm).unwrap() {
|
||||
MatchedSeq(ref s, _) => {
|
||||
s.iter().map(|m| match **m {
|
||||
MatchedNonterminal(NtTT(ref tt)) => (**tt).clone(),
|
||||
_ => sess.span_diagnostic.span_bug(def.span, "wrong-structured rhs")
|
||||
s.iter().map(|m| {
|
||||
if let MatchedNonterminal(ref nt) = **m {
|
||||
if let NtTT(ref tt) = **nt {
|
||||
return (*tt).clone();
|
||||
}
|
||||
}
|
||||
sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs")
|
||||
}).collect()
|
||||
}
|
||||
_ => sess.span_diagnostic.span_bug(def.span, "wrong-structured rhs")
|
||||
|
@ -277,39 +277,37 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
|
||||
return ret_val;
|
||||
// this can't be 0 length, just like TokenTree::Delimited
|
||||
}
|
||||
Some(cur_matched) => {
|
||||
match *cur_matched {
|
||||
Some(cur_matched) => if let MatchedNonterminal(ref nt) = *cur_matched {
|
||||
match **nt {
|
||||
// sidestep the interpolation tricks for ident because
|
||||
// (a) idents can be in lots of places, so it'd be a pain
|
||||
// (b) we actually can, since it's a token.
|
||||
MatchedNonterminal(NtIdent(ref sn)) => {
|
||||
NtIdent(ref sn) => {
|
||||
r.stack.last_mut().unwrap().idx += 1;
|
||||
r.cur_span = sn.span;
|
||||
r.cur_tok = token::Ident(sn.node);
|
||||
return ret_val;
|
||||
}
|
||||
MatchedNonterminal(NtTT(ref tt)) => {
|
||||
NtTT(_) => {
|
||||
r.stack.push(TtFrame {
|
||||
forest: TokenTree::Token(sp, Interpolated(NtTT(tt.clone()))),
|
||||
forest: TokenTree::Token(sp, Interpolated(nt.clone())),
|
||||
idx: 0,
|
||||
dotdotdoted: false,
|
||||
sep: None,
|
||||
});
|
||||
}
|
||||
MatchedNonterminal(ref other_whole_nt) => {
|
||||
_ => {
|
||||
r.stack.last_mut().unwrap().idx += 1;
|
||||
// FIXME(pcwalton): Bad copy.
|
||||
r.cur_span = sp;
|
||||
r.cur_tok = Interpolated((*other_whole_nt).clone());
|
||||
r.cur_tok = Interpolated(nt.clone());
|
||||
return ret_val;
|
||||
}
|
||||
MatchedSeq(..) => {
|
||||
panic!(r.sp_diag.span_fatal(
|
||||
sp, /* blame the macro writer */
|
||||
&format!("variable '{}' is still repeating at this depth",
|
||||
ident)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
panic!(r.sp_diag.span_fatal(
|
||||
sp, /* blame the macro writer */
|
||||
&format!("variable '{}' is still repeating at this depth", ident)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -576,7 +576,13 @@ pub fn noop_fold_token<T: Folder>(t: token::Token, fld: &mut T) -> token::Token
|
||||
match t {
|
||||
token::Ident(id) => token::Ident(fld.fold_ident(id)),
|
||||
token::Lifetime(id) => token::Lifetime(fld.fold_ident(id)),
|
||||
token::Interpolated(nt) => token::Interpolated(fld.fold_interpolated(nt)),
|
||||
token::Interpolated(nt) => {
|
||||
let nt = match Rc::try_unwrap(nt) {
|
||||
Ok(nt) => nt,
|
||||
Err(nt) => (*nt).clone(),
|
||||
};
|
||||
token::Interpolated(Rc::new(fld.fold_interpolated(nt)))
|
||||
}
|
||||
token::SubstNt(ident) => token::SubstNt(fld.fold_ident(ident)),
|
||||
token::MatchNt(name, kind) => token::MatchNt(fld.fold_ident(name), fld.fold_ident(kind)),
|
||||
_ => t
|
||||
@ -614,26 +620,25 @@ pub fn noop_fold_interpolated<T: Folder>(nt: token::Nonterminal, fld: &mut T)
|
||||
.expect_one("expected fold to produce exactly one item")),
|
||||
token::NtBlock(block) => token::NtBlock(fld.fold_block(block)),
|
||||
token::NtStmt(stmt) =>
|
||||
token::NtStmt(stmt.map(|stmt| fld.fold_stmt(stmt)
|
||||
token::NtStmt(fld.fold_stmt(stmt)
|
||||
// this is probably okay, because the only folds likely
|
||||
// to peek inside interpolated nodes will be renamings/markings,
|
||||
// which map single items to single items
|
||||
.expect_one("expected fold to produce exactly one statement"))),
|
||||
.expect_one("expected fold to produce exactly one statement")),
|
||||
token::NtPat(pat) => token::NtPat(fld.fold_pat(pat)),
|
||||
token::NtExpr(expr) => token::NtExpr(fld.fold_expr(expr)),
|
||||
token::NtTy(ty) => token::NtTy(fld.fold_ty(ty)),
|
||||
token::NtIdent(id) =>
|
||||
token::NtIdent(Box::new(Spanned::<Ident>{node: fld.fold_ident(id.node), ..*id})),
|
||||
token::NtIdent(id) => token::NtIdent(Spanned::<Ident>{node: fld.fold_ident(id.node), ..id}),
|
||||
token::NtMeta(meta_item) => token::NtMeta(fld.fold_meta_item(meta_item)),
|
||||
token::NtPath(path) => token::NtPath(Box::new(fld.fold_path(*path))),
|
||||
token::NtTT(tt) => token::NtTT(P(fld.fold_tt(&tt))),
|
||||
token::NtPath(path) => token::NtPath(fld.fold_path(path)),
|
||||
token::NtTT(tt) => token::NtTT(fld.fold_tt(&tt)),
|
||||
token::NtArm(arm) => token::NtArm(fld.fold_arm(arm)),
|
||||
token::NtImplItem(arm) =>
|
||||
token::NtImplItem(arm.map(|arm| fld.fold_impl_item(arm)
|
||||
.expect_one("expected fold to produce exactly one item"))),
|
||||
token::NtTraitItem(arm) =>
|
||||
token::NtTraitItem(arm.map(|arm| fld.fold_trait_item(arm)
|
||||
.expect_one("expected fold to produce exactly one item"))),
|
||||
token::NtImplItem(item) =>
|
||||
token::NtImplItem(fld.fold_impl_item(item)
|
||||
.expect_one("expected fold to produce exactly one item")),
|
||||
token::NtTraitItem(item) =>
|
||||
token::NtTraitItem(fld.fold_trait_item(item)
|
||||
.expect_one("expected fold to produce exactly one item")),
|
||||
token::NtGenerics(generics) => token::NtGenerics(fld.fold_generics(generics)),
|
||||
token::NtWhereClause(where_clause) =>
|
||||
token::NtWhereClause(fld.fold_where_clause(where_clause)),
|
||||
|
@ -215,7 +215,10 @@ impl<'a> Parser<'a> {
|
||||
/// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ;
|
||||
pub fn parse_meta_item(&mut self) -> PResult<'a, P<ast::MetaItem>> {
|
||||
let nt_meta = match self.token {
|
||||
token::Interpolated(token::NtMeta(ref e)) => Some(e.clone()),
|
||||
token::Interpolated(ref nt) => match **nt {
|
||||
token::NtMeta(ref e) => Some(e.clone()),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
|
||||
|
@ -107,125 +107,41 @@ pub enum SemiColonMode {
|
||||
/// be. The important thing is to make sure that lookahead doesn't balk at
|
||||
/// `token::Interpolated` tokens.
|
||||
macro_rules! maybe_whole_expr {
|
||||
($p:expr) => (
|
||||
{
|
||||
let found = match $p.token {
|
||||
token::Interpolated(token::NtExpr(ref e)) => {
|
||||
Some((*e).clone())
|
||||
}
|
||||
token::Interpolated(token::NtPath(_)) => {
|
||||
// FIXME: The following avoids an issue with lexical borrowck scopes,
|
||||
// but the clone is unfortunate.
|
||||
let pt = match $p.token {
|
||||
token::Interpolated(token::NtPath(ref pt)) => (**pt).clone(),
|
||||
_ => unreachable!()
|
||||
};
|
||||
let span = $p.span;
|
||||
Some($p.mk_expr(span.lo, span.hi, ExprKind::Path(None, pt), ThinVec::new()))
|
||||
}
|
||||
token::Interpolated(token::NtBlock(_)) => {
|
||||
// FIXME: The following avoids an issue with lexical borrowck scopes,
|
||||
// but the clone is unfortunate.
|
||||
let b = match $p.token {
|
||||
token::Interpolated(token::NtBlock(ref b)) => (*b).clone(),
|
||||
_ => unreachable!()
|
||||
};
|
||||
let span = $p.span;
|
||||
Some($p.mk_expr(span.lo, span.hi, ExprKind::Block(b), ThinVec::new()))
|
||||
}
|
||||
_ => None
|
||||
};
|
||||
match found {
|
||||
Some(e) => {
|
||||
($p:expr) => {
|
||||
if let token::Interpolated(nt) = $p.token.clone() {
|
||||
match *nt {
|
||||
token::NtExpr(ref e) => {
|
||||
$p.bump();
|
||||
return Ok(e);
|
||||
return Ok((*e).clone());
|
||||
}
|
||||
None => ()
|
||||
}
|
||||
token::NtPath(ref path) => {
|
||||
$p.bump();
|
||||
let span = $p.span;
|
||||
let kind = ExprKind::Path(None, (*path).clone());
|
||||
return Ok($p.mk_expr(span.lo, span.hi, kind, ThinVec::new()));
|
||||
}
|
||||
token::NtBlock(ref block) => {
|
||||
$p.bump();
|
||||
let span = $p.span;
|
||||
let kind = ExprKind::Block((*block).clone());
|
||||
return Ok($p.mk_expr(span.lo, span.hi, kind, ThinVec::new()));
|
||||
}
|
||||
_ => {},
|
||||
};
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// As maybe_whole_expr, but for things other than expressions
|
||||
macro_rules! maybe_whole {
|
||||
($p:expr, $constructor:ident) => (
|
||||
{
|
||||
let found = match ($p).token {
|
||||
token::Interpolated(token::$constructor(_)) => {
|
||||
Some(($p).bump_and_get())
|
||||
}
|
||||
_ => None
|
||||
};
|
||||
if let Some(token::Interpolated(token::$constructor(x))) = found {
|
||||
return Ok(x.clone());
|
||||
($p:expr, $constructor:ident, |$x:ident| $e:expr) => {
|
||||
if let token::Interpolated(nt) = $p.token.clone() {
|
||||
if let token::$constructor($x) = (*nt).clone() {
|
||||
$p.bump();
|
||||
return Ok($e);
|
||||
}
|
||||
}
|
||||
);
|
||||
(no_clone $p:expr, $constructor:ident) => (
|
||||
{
|
||||
let found = match ($p).token {
|
||||
token::Interpolated(token::$constructor(_)) => {
|
||||
Some(($p).bump_and_get())
|
||||
}
|
||||
_ => None
|
||||
};
|
||||
if let Some(token::Interpolated(token::$constructor(x))) = found {
|
||||
return Ok(x);
|
||||
}
|
||||
}
|
||||
);
|
||||
(no_clone_from_p $p:expr, $constructor:ident) => (
|
||||
{
|
||||
let found = match ($p).token {
|
||||
token::Interpolated(token::$constructor(_)) => {
|
||||
Some(($p).bump_and_get())
|
||||
}
|
||||
_ => None
|
||||
};
|
||||
if let Some(token::Interpolated(token::$constructor(x))) = found {
|
||||
return Ok(x.unwrap());
|
||||
}
|
||||
}
|
||||
);
|
||||
(deref $p:expr, $constructor:ident) => (
|
||||
{
|
||||
let found = match ($p).token {
|
||||
token::Interpolated(token::$constructor(_)) => {
|
||||
Some(($p).bump_and_get())
|
||||
}
|
||||
_ => None
|
||||
};
|
||||
if let Some(token::Interpolated(token::$constructor(x))) = found {
|
||||
return Ok((*x).clone());
|
||||
}
|
||||
}
|
||||
);
|
||||
(Some deref $p:expr, $constructor:ident) => (
|
||||
{
|
||||
let found = match ($p).token {
|
||||
token::Interpolated(token::$constructor(_)) => {
|
||||
Some(($p).bump_and_get())
|
||||
}
|
||||
_ => None
|
||||
};
|
||||
if let Some(token::Interpolated(token::$constructor(x))) = found {
|
||||
return Ok(Some((*x).clone()));
|
||||
}
|
||||
}
|
||||
);
|
||||
(pair_empty $p:expr, $constructor:ident) => (
|
||||
{
|
||||
let found = match ($p).token {
|
||||
token::Interpolated(token::$constructor(_)) => {
|
||||
Some(($p).bump_and_get())
|
||||
}
|
||||
_ => None
|
||||
};
|
||||
if let Some(token::Interpolated(token::$constructor(x))) = found {
|
||||
return Ok((Vec::new(), x));
|
||||
}
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>)
|
||||
@ -516,9 +432,6 @@ impl<'a> Parser<'a> {
|
||||
self.bump();
|
||||
Ok(i)
|
||||
}
|
||||
token::Interpolated(token::NtIdent(..)) => {
|
||||
self.bug("ident interpolation not converted to real token");
|
||||
}
|
||||
_ => {
|
||||
Err(if self.prev_token_kind == PrevTokenKind::DocComment {
|
||||
self.span_fatal_help(self.prev_span,
|
||||
@ -1162,7 +1075,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
/// Parse the items in a trait declaration
|
||||
pub fn parse_trait_item(&mut self) -> PResult<'a, TraitItem> {
|
||||
maybe_whole!(no_clone_from_p self, NtTraitItem);
|
||||
maybe_whole!(self, NtTraitItem, |x| x);
|
||||
let mut attrs = self.parse_outer_attributes()?;
|
||||
let lo = self.span.lo;
|
||||
|
||||
@ -1331,7 +1244,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
/// Parse a type.
|
||||
pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
|
||||
maybe_whole!(no_clone self, NtTy);
|
||||
maybe_whole!(self, NtTy, |x| x);
|
||||
|
||||
let lo = self.span.lo;
|
||||
|
||||
@ -1476,7 +1389,7 @@ impl<'a> Parser<'a> {
|
||||
/// This version of parse arg doesn't necessarily require
|
||||
/// identifier names.
|
||||
pub fn parse_arg_general(&mut self, require_name: bool) -> PResult<'a, Arg> {
|
||||
maybe_whole!(no_clone self, NtArg);
|
||||
maybe_whole!(self, NtArg, |x| x);
|
||||
|
||||
let pat = if require_name || self.is_named_argument() {
|
||||
debug!("parse_arg_general parse_pat (require_name:{})",
|
||||
@ -1542,12 +1455,13 @@ impl<'a> Parser<'a> {
|
||||
/// Matches token_lit = LIT_INTEGER | ...
|
||||
pub fn parse_lit_token(&mut self) -> PResult<'a, LitKind> {
|
||||
let out = match self.token {
|
||||
token::Interpolated(token::NtExpr(ref v)) => {
|
||||
match v.node {
|
||||
token::Interpolated(ref nt) => match **nt {
|
||||
token::NtExpr(ref v) => match v.node {
|
||||
ExprKind::Lit(ref lit) => { lit.node.clone() }
|
||||
_ => { return self.unexpected_last(&self.token); }
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => { return self.unexpected_last(&self.token); }
|
||||
},
|
||||
token::Literal(lit, suf) => {
|
||||
let (suffix_illegal, out) = match lit {
|
||||
token::Byte(i) => (true, LitKind::Byte(parse::byte_lit(&i.as_str()).0)),
|
||||
@ -1703,14 +1617,7 @@ impl<'a> Parser<'a> {
|
||||
/// bounds are permitted and whether `::` must precede type parameter
|
||||
/// groups.
|
||||
pub fn parse_path(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> {
|
||||
// Check for a whole path...
|
||||
let found = match self.token {
|
||||
token::Interpolated(token::NtPath(_)) => Some(self.bump_and_get()),
|
||||
_ => None,
|
||||
};
|
||||
if let Some(token::Interpolated(token::NtPath(path))) = found {
|
||||
return Ok(*path);
|
||||
}
|
||||
maybe_whole!(self, NtPath, |x| x);
|
||||
|
||||
let lo = self.span.lo;
|
||||
let is_global = self.eat(&token::ModSep);
|
||||
@ -2746,7 +2653,7 @@ impl<'a> Parser<'a> {
|
||||
// and token::SubstNt's; it's too early to know yet
|
||||
// whether something will be a nonterminal or a seq
|
||||
// yet.
|
||||
maybe_whole!(deref self, NtTT);
|
||||
maybe_whole!(self, NtTT, |x| x);
|
||||
|
||||
match self.token {
|
||||
token::Eof => {
|
||||
@ -3327,7 +3234,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
pub fn parse_arm(&mut self) -> PResult<'a, Arm> {
|
||||
maybe_whole!(no_clone self, NtArm);
|
||||
maybe_whole!(self, NtArm, |x| x);
|
||||
|
||||
let attrs = self.parse_outer_attributes()?;
|
||||
let pats = self.parse_pats()?;
|
||||
@ -3583,7 +3490,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
/// Parse a pattern.
|
||||
pub fn parse_pat(&mut self) -> PResult<'a, P<Pat>> {
|
||||
maybe_whole!(self, NtPat);
|
||||
maybe_whole!(self, NtPat, |x| x);
|
||||
|
||||
let lo = self.span.lo;
|
||||
let pat;
|
||||
@ -3888,7 +3795,7 @@ impl<'a> Parser<'a> {
|
||||
fn parse_stmt_without_recovery(&mut self,
|
||||
macro_legacy_warnings: bool)
|
||||
-> PResult<'a, Option<Stmt>> {
|
||||
maybe_whole!(Some deref self, NtStmt);
|
||||
maybe_whole!(self, NtStmt, |x| Some(x));
|
||||
|
||||
let attrs = self.parse_outer_attributes()?;
|
||||
let lo = self.span.lo;
|
||||
@ -4077,7 +3984,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
/// Parse a block. No inner attrs are allowed.
|
||||
pub fn parse_block(&mut self) -> PResult<'a, P<Block>> {
|
||||
maybe_whole!(no_clone self, NtBlock);
|
||||
maybe_whole!(self, NtBlock, |x| x);
|
||||
|
||||
let lo = self.span.lo;
|
||||
|
||||
@ -4115,7 +4022,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
/// Parse a block. Inner attrs are allowed.
|
||||
fn parse_inner_attrs_and_block(&mut self) -> PResult<'a, (Vec<Attribute>, P<Block>)> {
|
||||
maybe_whole!(pair_empty self, NtBlock);
|
||||
maybe_whole!(self, NtBlock, |x| (Vec::new(), x));
|
||||
|
||||
let lo = self.span.lo;
|
||||
self.expect(&token::OpenDelim(token::Brace))?;
|
||||
@ -4290,7 +4197,7 @@ impl<'a> Parser<'a> {
|
||||
/// | ( < lifetimes , typaramseq ( , )? > )
|
||||
/// where typaramseq = ( typaram ) | ( typaram , typaramseq )
|
||||
pub fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
|
||||
maybe_whole!(self, NtGenerics);
|
||||
maybe_whole!(self, NtGenerics, |x| x);
|
||||
let span_lo = self.span.lo;
|
||||
|
||||
if self.eat(&token::Lt) {
|
||||
@ -4431,7 +4338,7 @@ impl<'a> Parser<'a> {
|
||||
/// where T : Trait<U, V> + 'b, 'a : 'b
|
||||
/// ```
|
||||
pub fn parse_where_clause(&mut self) -> PResult<'a, ast::WhereClause> {
|
||||
maybe_whole!(self, NtWhereClause);
|
||||
maybe_whole!(self, NtWhereClause, |x| x);
|
||||
|
||||
let mut where_clause = WhereClause {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
@ -4839,7 +4746,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
/// Parse an impl item.
|
||||
pub fn parse_impl_item(&mut self) -> PResult<'a, ImplItem> {
|
||||
maybe_whole!(no_clone_from_p self, NtImplItem);
|
||||
maybe_whole!(self, NtImplItem, |x| x);
|
||||
|
||||
let mut attrs = self.parse_outer_attributes()?;
|
||||
let lo = self.span.lo;
|
||||
@ -5707,19 +5614,13 @@ impl<'a> Parser<'a> {
|
||||
/// extern crate.
|
||||
fn parse_item_(&mut self, attrs: Vec<Attribute>,
|
||||
macros_allowed: bool, attributes_allowed: bool) -> PResult<'a, Option<P<Item>>> {
|
||||
let nt_item = match self.token {
|
||||
token::Interpolated(token::NtItem(ref item)) => {
|
||||
Some((**item).clone())
|
||||
}
|
||||
_ => None
|
||||
};
|
||||
if let Some(mut item) = nt_item {
|
||||
self.bump();
|
||||
maybe_whole!(self, NtItem, |item| {
|
||||
let mut item = item.unwrap();
|
||||
let mut attrs = attrs;
|
||||
mem::swap(&mut item.attrs, &mut attrs);
|
||||
item.attrs.extend(attrs);
|
||||
return Ok(Some(P(item)));
|
||||
}
|
||||
Some(P(item))
|
||||
});
|
||||
|
||||
let lo = self.span.lo;
|
||||
|
||||
|
@ -123,7 +123,7 @@ pub enum Token {
|
||||
Lifetime(ast::Ident),
|
||||
|
||||
/* For interpolation */
|
||||
Interpolated(Nonterminal),
|
||||
Interpolated(Rc<Nonterminal>),
|
||||
// Can be expanded into several tokens.
|
||||
/// Doc comment
|
||||
DocComment(ast::Name),
|
||||
@ -172,12 +172,15 @@ impl Token {
|
||||
DotDot | DotDotDot => true, // range notation
|
||||
Lt | BinOp(Shl) => true, // associated path
|
||||
ModSep => true,
|
||||
Interpolated(NtExpr(..)) => true,
|
||||
Interpolated(NtIdent(..)) => true,
|
||||
Interpolated(NtBlock(..)) => true,
|
||||
Interpolated(NtPath(..)) => true,
|
||||
Pound => true, // for expression attributes
|
||||
_ => false,
|
||||
Interpolated(ref nt) => match **nt {
|
||||
NtExpr(..) => true,
|
||||
NtIdent(..) => true,
|
||||
NtBlock(..) => true,
|
||||
NtPath(..) => true,
|
||||
_ => false,
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,10 +218,12 @@ impl Token {
|
||||
|
||||
/// Returns `true` if the token is an interpolated path.
|
||||
pub fn is_path(&self) -> bool {
|
||||
match *self {
|
||||
Interpolated(NtPath(..)) => true,
|
||||
_ => false,
|
||||
if let Interpolated(ref nt) = *self {
|
||||
if let NtPath(..) = **nt {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Returns `true` if the token is a lifetime.
|
||||
@ -290,19 +295,19 @@ impl Token {
|
||||
pub enum Nonterminal {
|
||||
NtItem(P<ast::Item>),
|
||||
NtBlock(P<ast::Block>),
|
||||
NtStmt(P<ast::Stmt>),
|
||||
NtStmt(ast::Stmt),
|
||||
NtPat(P<ast::Pat>),
|
||||
NtExpr(P<ast::Expr>),
|
||||
NtTy(P<ast::Ty>),
|
||||
NtIdent(Box<ast::SpannedIdent>),
|
||||
NtIdent(ast::SpannedIdent),
|
||||
/// Stuff inside brackets for attributes
|
||||
NtMeta(P<ast::MetaItem>),
|
||||
NtPath(Box<ast::Path>),
|
||||
NtTT(P<tokenstream::TokenTree>), // needs P'ed to break a circularity
|
||||
NtPath(ast::Path),
|
||||
NtTT(tokenstream::TokenTree),
|
||||
// These are not exposed to macros, but are used by quasiquote.
|
||||
NtArm(ast::Arm),
|
||||
NtImplItem(P<ast::ImplItem>),
|
||||
NtTraitItem(P<ast::TraitItem>),
|
||||
NtImplItem(ast::ImplItem),
|
||||
NtTraitItem(ast::TraitItem),
|
||||
NtGenerics(ast::Generics),
|
||||
NtWhereClause(ast::WhereClause),
|
||||
NtArg(ast::Arg),
|
||||
|
@ -285,7 +285,7 @@ pub fn token_to_string(tok: &Token) -> String {
|
||||
token::Comment => "/* */".to_string(),
|
||||
token::Shebang(s) => format!("/* shebang: {}*/", s),
|
||||
|
||||
token::Interpolated(ref nt) => match *nt {
|
||||
token::Interpolated(ref nt) => match **nt {
|
||||
token::NtExpr(ref e) => expr_to_string(&e),
|
||||
token::NtMeta(ref e) => meta_item_to_string(&e),
|
||||
token::NtTy(ref e) => ty_to_string(&e),
|
||||
|
@ -134,8 +134,10 @@ impl TokenTree {
|
||||
AttrStyle::Inner => 3,
|
||||
}
|
||||
}
|
||||
TokenTree::Token(_, token::Interpolated(ref nt)) => {
|
||||
if let Nonterminal::NtTT(..) = **nt { 1 } else { 0 }
|
||||
},
|
||||
TokenTree::Token(_, token::MatchNt(..)) => 3,
|
||||
TokenTree::Token(_, token::Interpolated(Nonterminal::NtTT(..))) => 1,
|
||||
TokenTree::Delimited(_, ref delimed) => delimed.tts.len() + 2,
|
||||
TokenTree::Sequence(_, ref seq) => seq.tts.len(),
|
||||
TokenTree::Token(..) => 0,
|
||||
@ -193,8 +195,12 @@ impl TokenTree {
|
||||
TokenTree::Token(sp, token::Ident(kind))];
|
||||
v[index].clone()
|
||||
}
|
||||
(&TokenTree::Token(_, token::Interpolated(Nonterminal::NtTT(ref tt))), _) => {
|
||||
tt.clone().unwrap()
|
||||
(&TokenTree::Token(_, token::Interpolated(ref nt)), _) => {
|
||||
if let Nonterminal::NtTT(ref tt) = **nt {
|
||||
tt.clone()
|
||||
} else {
|
||||
panic!("Cannot expand a token tree");
|
||||
}
|
||||
}
|
||||
(&TokenTree::Sequence(_, ref seq), _) => seq.tts[index].clone(),
|
||||
_ => panic!("Cannot expand a token tree"),
|
||||
|
Loading…
x
Reference in New Issue
Block a user