about summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>2016-11-02 03:03:55 +0000
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>2016-11-03 23:48:24 +0000
commiteb3ac29a101f9388966175bb51e340a98b849b59 (patch)
treef77cf112fbbd52dcbd25d018850c6c0886606cf0 /src/libsyntax/parse
parent5f280a5c608c6cb92fa75829599d5759ed6305a5 (diff)
downloadrust-eb3ac29a101f9388966175bb51e340a98b849b59.tar.gz
rust-eb3ac29a101f9388966175bb51e340a98b849b59.zip
Reduce the size of `Token` and make it cheaper to clone by refactoring
`Token::Interpolated(Nonterminal)` -> `Token::Interpolated(Rc<Nonterminal>)`.
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/attr.rs5
-rw-r--r--src/libsyntax/parse/parser.rs187
-rw-r--r--src/libsyntax/parse/token.rs35
3 files changed, 68 insertions, 159 deletions
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs
index 3cb34fa3c91..983c882eafc 100644
--- a/src/libsyntax/parse/attr.rs
+++ b/src/libsyntax/parse/attr.rs
@@ -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,
         };
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index eb68f5a309b..f77525ff549 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -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())
+    ($p:expr) => {
+        if let token::Interpolated(nt) = $p.token.clone() {
+            match *nt {
+                token::NtExpr(ref e) => {
+                    $p.bump();
+                    return Ok((*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!()
-                    };
+                token::NtPath(ref path) => {
+                    $p.bump();
                     let span = $p.span;
-                    Some($p.mk_expr(span.lo, span.hi, ExprKind::Path(None, pt), ThinVec::new()))
+                    let kind = ExprKind::Path(None, (*path).clone());
+                    return Ok($p.mk_expr(span.lo, span.hi, kind, 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!()
-                    };
+                token::NtBlock(ref block) => {
+                    $p.bump();
                     let span = $p.span;
-                    Some($p.mk_expr(span.lo, span.hi, ExprKind::Block(b), ThinVec::new()))
+                    let kind = ExprKind::Block((*block).clone());
+                    return Ok($p.mk_expr(span.lo, span.hi, kind, ThinVec::new()));
                 }
-                _ => None
+                _ => {},
             };
-            match found {
-                Some(e) => {
-                    $p.bump();
-                    return Ok(e);
-                }
-                None => ()
-            }
         }
-    )
+    }
 }
 
 /// 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());
-            }
-        }
-    );
-    (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));
+    ($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);
             }
         }
-    )
+    };
 }
 
 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;
 
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 4d0da660302..0198ee073d2 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -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),