diff options
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/attr.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 10 | ||||
| -rw-r--r-- | src/libsyntax/parse/token.rs | 53 |
3 files changed, 54 insertions, 13 deletions
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 082930777e5..c99a09ab24e 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -151,7 +151,7 @@ impl<'a> Parser<'a> { pub fn parse_path_and_tokens(&mut self) -> PResult<'a, (ast::Path, TokenStream)> { let meta = match self.token { - token::Interpolated(ref nt) => match **nt { + token::Interpolated(ref nt) => match nt.0 { Nonterminal::NtMeta(ref meta) => Some(meta.clone()), _ => None, }, @@ -223,7 +223,7 @@ impl<'a> Parser<'a> { /// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ; pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> { let nt_meta = match self.token { - token::Interpolated(ref nt) => match **nt { + token::Interpolated(ref nt) => match nt.0 { token::NtMeta(ref e) => Some(e.clone()), _ => None, }, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a30dcef6f44..2858d49d63d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -107,7 +107,7 @@ pub enum BlockMode { macro_rules! maybe_whole_expr { ($p:expr) => { if let token::Interpolated(nt) = $p.token.clone() { - match *nt { + match nt.0 { token::NtExpr(ref e) => { $p.bump(); return Ok((*e).clone()); @@ -134,7 +134,7 @@ macro_rules! maybe_whole_expr { macro_rules! maybe_whole { ($p:expr, $constructor:ident, |$x:ident| $e:expr) => { if let token::Interpolated(nt) = $p.token.clone() { - if let token::$constructor($x) = (*nt).clone() { + if let token::$constructor($x) = nt.0.clone() { $p.bump(); return Ok($e); } @@ -1620,7 +1620,7 @@ 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(ref nt) => match **nt { + token::Interpolated(ref nt) => match nt.0 { token::NtExpr(ref v) => match v.node { ExprKind::Lit(ref lit) => { lit.node.clone() } _ => { return self.unexpected_last(&self.token); } @@ -1791,7 +1791,7 @@ impl<'a> Parser<'a> { /// This is used when parsing derive macro paths in `#[derive]` attributes. pub fn parse_path_allowing_meta(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> { let meta_ident = match self.token { - token::Interpolated(ref nt) => match **nt { + token::Interpolated(ref nt) => match nt.0 { token::NtMeta(ref meta) => match meta.node { ast::MetaItemKind::Word => Some(ast::Ident::with_empty_ctxt(meta.name)), _ => None, @@ -2635,7 +2635,7 @@ impl<'a> Parser<'a> { } token::Interpolated(ref nt) => { self.meta_var_span = Some(self.span); - match **nt { + match nt.0 { token::NtIdent(ident) => ident, _ => return, } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index e568af66e8a..189a18f4420 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -16,9 +16,11 @@ pub use self::Token::*; use ast::{self}; use ptr::P; +use serialize::{Decodable, Decoder, Encodable, Encoder}; use symbol::keywords; -use tokenstream::TokenTree; +use tokenstream::{TokenStream, TokenTree}; +use std::cell::RefCell; use std::fmt; use std::rc::Rc; @@ -168,7 +170,7 @@ pub enum Token { Lifetime(ast::Ident), /* For interpolation */ - Interpolated(Rc<Nonterminal>), + Interpolated(Rc<(Nonterminal, LazyTokenStream)>), // Can be expanded into several tokens. /// Doc comment DocComment(ast::Name), @@ -187,6 +189,10 @@ pub enum Token { } impl Token { + pub fn interpolated(nt: Nonterminal) -> Token { + Token::Interpolated(Rc::new((nt, LazyTokenStream::new()))) + } + /// Returns `true` if the token starts with '>'. pub fn is_like_gt(&self) -> bool { match *self { @@ -211,7 +217,7 @@ impl Token { Lt | BinOp(Shl) | // associated path ModSep | // global path Pound => true, // expression attributes - Interpolated(ref nt) => match **nt { + Interpolated(ref nt) => match nt.0 { NtIdent(..) | NtExpr(..) | NtBlock(..) | NtPath(..) => true, _ => false, }, @@ -234,7 +240,7 @@ impl Token { Lifetime(..) | // lifetime bound in trait object Lt | BinOp(Shl) | // associated path ModSep => true, // global path - Interpolated(ref nt) => match **nt { + Interpolated(ref nt) => match nt.0 { NtIdent(..) | NtTy(..) | NtPath(..) => true, _ => false, }, @@ -253,7 +259,7 @@ impl Token { pub fn ident(&self) -> Option<ast::Ident> { match *self { Ident(ident) => Some(ident), - Interpolated(ref nt) => match **nt { + Interpolated(ref nt) => match nt.0 { NtIdent(ident) => Some(ident.node), _ => None, }, @@ -285,7 +291,7 @@ impl Token { /// Returns `true` if the token is an interpolated path. pub fn is_path(&self) -> bool { if let Interpolated(ref nt) = *self { - if let NtPath(..) = **nt { + if let NtPath(..) = nt.0 { return true; } } @@ -461,3 +467,38 @@ pub fn is_op(tok: &Token) -> bool { _ => true, } } + +#[derive(Clone, Eq, PartialEq, Debug)] +pub struct LazyTokenStream(RefCell<Option<TokenStream>>); + +impl LazyTokenStream { + pub fn new() -> Self { + LazyTokenStream(RefCell::new(None)) + } + + pub fn force<F: FnOnce() -> TokenStream>(&self, f: F) -> TokenStream { + let mut opt_stream = self.0.borrow_mut(); + if opt_stream.is_none() { + *opt_stream = Some(f()); + }; + opt_stream.clone().unwrap() + } +} + +impl Encodable for LazyTokenStream { + fn encode<S: Encoder>(&self, _: &mut S) -> Result<(), S::Error> { + Ok(()) + } +} + +impl Decodable for LazyTokenStream { + fn decode<D: Decoder>(_: &mut D) -> Result<LazyTokenStream, D::Error> { + Ok(LazyTokenStream::new()) + } +} + +impl ::std::hash::Hash for LazyTokenStream { + fn hash<H: ::std::hash::Hasher>(&self, hasher: &mut H) { + self.0.borrow().hash(hasher); + } +} |
