diff options
| author | bors <bors@rust-lang.org> | 2017-03-04 05:44:12 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-03-04 05:44:12 +0000 |
| commit | be304afc8c2b1a364bd406888b5378897ed82a9f (patch) | |
| tree | 442e2432aa307ac81e894e00aee33bd5a02b1c0b /src/libsyntax/parse | |
| parent | 8c6c0f80a399e61d8454bb449962103449b52739 (diff) | |
| parent | 0d554139ad7a54bbd59a5166cc3e9ff7842c5266 (diff) | |
| download | rust-be304afc8c2b1a364bd406888b5378897ed82a9f.tar.gz rust-be304afc8c2b1a364bd406888b5378897ed82a9f.zip | |
Auto merge of #40202 - jseyfried:integrate_tokenstream, r=nrc
syntax: integrate `TokenStream` Use `TokenStream` instead of `Vec<TokenTree>` in `TokenTree::Delimited` and elsewhere. r? @nrc
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/lexer/tokentrees.rs | 24 | ||||
| -rw-r--r-- | src/libsyntax/parse/mod.rs | 87 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 188 |
3 files changed, 190 insertions, 109 deletions
diff --git a/src/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs index eafc3f77ab0..554a1fcfc71 100644 --- a/src/libsyntax/parse/lexer/tokentrees.rs +++ b/src/libsyntax/parse/lexer/tokentrees.rs @@ -12,32 +12,30 @@ use print::pprust::token_to_string; use parse::lexer::StringReader; use parse::{token, PResult}; use syntax_pos::Span; -use tokenstream::{Delimited, TokenTree}; - -use std::rc::Rc; +use tokenstream::{Delimited, TokenStream, TokenTree}; impl<'a> StringReader<'a> { // Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`. - pub fn parse_all_token_trees(&mut self) -> PResult<'a, Vec<TokenTree>> { + pub fn parse_all_token_trees(&mut self) -> PResult<'a, TokenStream> { let mut tts = Vec::new(); while self.token != token::Eof { - tts.push(self.parse_token_tree()?); + tts.push(self.parse_token_tree()?.into()); } - Ok(tts) + Ok(TokenStream::concat(tts)) } // Parse a stream of tokens into a list of `TokenTree`s, up to a `CloseDelim`. - fn parse_token_trees_until_close_delim(&mut self) -> Vec<TokenTree> { + fn parse_token_trees_until_close_delim(&mut self) -> TokenStream { let mut tts = vec![]; loop { if let token::CloseDelim(..) = self.token { - return tts; + return TokenStream::concat(tts); } match self.parse_token_tree() { - Ok(tt) => tts.push(tt), + Ok(tt) => tts.push(tt.into()), Err(mut e) => { e.emit(); - return tts; + return TokenStream::concat(tts); } } } @@ -111,10 +109,10 @@ impl<'a> StringReader<'a> { _ => {} } - Ok(TokenTree::Delimited(span, Rc::new(Delimited { + Ok(TokenTree::Delimited(span, Delimited { delim: delim, - tts: tts, - }))) + tts: tts.into(), + })) }, token::CloseDelim(_) => { // An unexpected closing delimiter (i.e., there is no diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 6fec49b229a..c00d2952b3b 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -19,7 +19,7 @@ use parse::parser::Parser; use ptr::P; use str::char_at; use symbol::Symbol; -use tokenstream; +use tokenstream::{TokenStream, TokenTree}; use std::cell::RefCell; use std::collections::HashSet; @@ -141,9 +141,9 @@ pub fn parse_stmt_from_source_str<'a>(name: String, source: String, sess: &'a Pa new_parser_from_source_str(sess, name, source).parse_stmt() } -pub fn parse_tts_from_source_str<'a>(name: String, source: String, sess: &'a ParseSess) - -> Vec<tokenstream::TokenTree> { - filemap_to_tts(sess, sess.codemap().new_filemap(name, None, source)) +pub fn parse_stream_from_source_str<'a>(name: String, source: String, sess: &'a ParseSess) + -> TokenStream { + filemap_to_stream(sess, sess.codemap().new_filemap(name, None, source)) } // Create a new parser from a source string @@ -175,7 +175,7 @@ pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess, /// Given a filemap and config, return a parser pub fn filemap_to_parser<'a>(sess: &'a ParseSess, filemap: Rc<FileMap>, ) -> Parser<'a> { let end_pos = filemap.end_pos; - let mut parser = tts_to_parser(sess, filemap_to_tts(sess, filemap)); + let mut parser = stream_to_parser(sess, filemap_to_stream(sess, filemap)); if parser.token == token::Eof && parser.span == syntax_pos::DUMMY_SP { parser.span = syntax_pos::mk_sp(end_pos, end_pos); @@ -186,13 +186,8 @@ pub fn filemap_to_parser<'a>(sess: &'a ParseSess, filemap: Rc<FileMap>, ) -> Par // must preserve old name for now, because quote! from the *existing* // compiler expands into it -pub fn new_parser_from_tts<'a>(sess: &'a ParseSess, tts: Vec<tokenstream::TokenTree>) - -> Parser<'a> { - tts_to_parser(sess, tts) -} - -pub fn new_parser_from_ts<'a>(sess: &'a ParseSess, ts: tokenstream::TokenStream) -> Parser<'a> { - tts_to_parser(sess, ts.trees().cloned().collect()) +pub fn new_parser_from_tts<'a>(sess: &'a ParseSess, tts: Vec<TokenTree>) -> Parser<'a> { + stream_to_parser(sess, tts.into_iter().collect()) } @@ -215,15 +210,15 @@ fn file_to_filemap(sess: &ParseSess, path: &Path, spanopt: Option<Span>) } /// Given a filemap, produce a sequence of token-trees -pub fn filemap_to_tts(sess: &ParseSess, filemap: Rc<FileMap>) -> Vec<tokenstream::TokenTree> { +pub fn filemap_to_stream(sess: &ParseSess, filemap: Rc<FileMap>) -> TokenStream { let mut srdr = lexer::StringReader::new(sess, filemap); srdr.real_token(); panictry!(srdr.parse_all_token_trees()) } -/// Given tts and the ParseSess, produce a parser -pub fn tts_to_parser<'a>(sess: &'a ParseSess, tts: Vec<tokenstream::TokenTree>) -> Parser<'a> { - let mut p = Parser::new(sess, tts, None, false); +/// Given stream and the ParseSess, produce a parser +pub fn stream_to_parser<'a>(sess: &'a ParseSess, stream: TokenStream) -> Parser<'a> { + let mut p = Parser::new(sess, stream, None, false); p.check_unknown_macro_variable(); p } @@ -603,7 +598,6 @@ pub fn integer_lit(s: &str, suffix: Option<Symbol>, sd: &Handler, sp: Span) -> a #[cfg(test)] mod tests { use super::*; - use std::rc::Rc; use syntax_pos::{self, Span, BytePos, Pos, NO_EXPANSION}; use codemap::Spanned; use ast::{self, Ident, PatKind}; @@ -614,7 +608,7 @@ mod tests { use print::pprust::item_to_string; use ptr::P; use tokenstream::{self, TokenTree}; - use util::parser_testing::{string_to_tts, string_to_parser}; + use util::parser_testing::{string_to_stream, string_to_parser}; use util::parser_testing::{string_to_expr, string_to_item, string_to_stmt}; use util::ThinVec; @@ -659,8 +653,9 @@ mod tests { // check the token-tree-ization of macros #[test] fn string_to_tts_macro () { - let tts = string_to_tts("macro_rules! zip (($a)=>($a))".to_string()); - let tts: &[tokenstream::TokenTree] = &tts[..]; + let tts: Vec<_> = + string_to_stream("macro_rules! zip (($a)=>($a))".to_string()).trees().collect(); + let tts: &[TokenTree] = &tts[..]; match (tts.len(), tts.get(0), tts.get(1), tts.get(2), tts.get(3)) { ( @@ -672,7 +667,7 @@ mod tests { ) if name_macro_rules.name == "macro_rules" && name_zip.name == "zip" => { - let tts = ¯o_delimed.tts[..]; + let tts = ¯o_delimed.stream().trees().collect::<Vec<_>>(); match (tts.len(), tts.get(0), tts.get(1), tts.get(2)) { ( 3, @@ -681,7 +676,7 @@ mod tests { Some(&TokenTree::Delimited(_, ref second_delimed)), ) if macro_delimed.delim == token::Paren => { - let tts = &first_delimed.tts[..]; + let tts = &first_delimed.stream().trees().collect::<Vec<_>>(); match (tts.len(), tts.get(0), tts.get(1)) { ( 2, @@ -689,9 +684,9 @@ mod tests { Some(&TokenTree::Token(_, token::Ident(ident))), ) if first_delimed.delim == token::Paren && ident.name == "a" => {}, - _ => panic!("value 3: {:?}", **first_delimed), + _ => panic!("value 3: {:?}", *first_delimed), } - let tts = &second_delimed.tts[..]; + let tts = &second_delimed.stream().trees().collect::<Vec<_>>(); match (tts.len(), tts.get(0), tts.get(1)) { ( 2, @@ -700,10 +695,10 @@ mod tests { ) if second_delimed.delim == token::Paren && ident.name == "a" => {}, - _ => panic!("value 4: {:?}", **second_delimed), + _ => panic!("value 4: {:?}", *second_delimed), } }, - _ => panic!("value 2: {:?}", **macro_delimed), + _ => panic!("value 2: {:?}", *macro_delimed), } }, _ => panic!("value: {:?}",tts), @@ -712,31 +707,31 @@ mod tests { #[test] fn string_to_tts_1() { - let tts = string_to_tts("fn a (b : i32) { b; }".to_string()); + let tts = string_to_stream("fn a (b : i32) { b; }".to_string()); - let expected = vec![ - TokenTree::Token(sp(0, 2), token::Ident(Ident::from_str("fn"))), - TokenTree::Token(sp(3, 4), token::Ident(Ident::from_str("a"))), + let expected = TokenStream::concat(vec![ + TokenTree::Token(sp(0, 2), token::Ident(Ident::from_str("fn"))).into(), + TokenTree::Token(sp(3, 4), token::Ident(Ident::from_str("a"))).into(), TokenTree::Delimited( sp(5, 14), - Rc::new(tokenstream::Delimited { + tokenstream::Delimited { delim: token::DelimToken::Paren, - tts: vec![ - TokenTree::Token(sp(6, 7), token::Ident(Ident::from_str("b"))), - TokenTree::Token(sp(8, 9), token::Colon), - TokenTree::Token(sp(10, 13), token::Ident(Ident::from_str("i32"))), - ], - })), + tts: TokenStream::concat(vec![ + TokenTree::Token(sp(6, 7), token::Ident(Ident::from_str("b"))).into(), + TokenTree::Token(sp(8, 9), token::Colon).into(), + TokenTree::Token(sp(10, 13), token::Ident(Ident::from_str("i32"))).into(), + ]).into(), + }).into(), TokenTree::Delimited( sp(15, 21), - Rc::new(tokenstream::Delimited { + tokenstream::Delimited { delim: token::DelimToken::Brace, - tts: vec![ - TokenTree::Token(sp(17, 18), token::Ident(Ident::from_str("b"))), - TokenTree::Token(sp(18, 19), token::Semi), - ], - })) - ]; + tts: TokenStream::concat(vec![ + TokenTree::Token(sp(17, 18), token::Ident(Ident::from_str("b"))).into(), + TokenTree::Token(sp(18, 19), token::Semi).into(), + ]).into(), + }).into() + ]); assert_eq!(tts, expected); } @@ -979,8 +974,8 @@ mod tests { let expr = parse::parse_expr_from_source_str("foo".to_string(), "foo!( fn main() { body } )".to_string(), &sess).unwrap(); - let tts = match expr.node { - ast::ExprKind::Mac(ref mac) => mac.node.tts.clone(), + let tts: Vec<_> = match expr.node { + ast::ExprKind::Mac(ref mac) => mac.node.stream().trees().collect(), _ => panic!("not a macro"), }; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 71274c4fdaa..6e3724b5fd8 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -9,7 +9,7 @@ // except according to those terms. use abi::{self, Abi}; -use ast::BareFnTy; +use ast::{AttrStyle, BareFnTy}; use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; use ast::Unsafety; use ast::{Mod, Arg, Arm, Attribute, BindingMode, TraitItemKind}; @@ -46,21 +46,21 @@ use errors::{self, DiagnosticBuilder}; use parse::{self, classify, token}; use parse::common::SeqSep; use parse::lexer::TokenAndSpan; +use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; use parse::obsolete::ObsoleteSyntax; use parse::{new_sub_parser_from_file, ParseSess, Directory, DirectoryOwnership}; use util::parser::{AssocOp, Fixity}; use print::pprust; use ptr::P; use parse::PResult; -use tokenstream::{Delimited, TokenTree}; +use tokenstream::{self, Delimited, ThinTokenStream, TokenTree, TokenStream}; use symbol::{Symbol, keywords}; use util::ThinVec; use std::collections::HashSet; -use std::mem; +use std::{cmp, mem, slice}; use std::path::{Path, PathBuf}; use std::rc::Rc; -use std::slice; bitflags! { flags Restrictions: u8 { @@ -175,12 +175,112 @@ pub struct Parser<'a> { /// into modules, and sub-parsers have new values for this name. pub root_module_name: Option<String>, pub expected_tokens: Vec<TokenType>, - pub tts: Vec<(TokenTree, usize)>, + token_cursor: TokenCursor, pub desugar_doc_comments: bool, /// Whether we should configure out of line modules as we parse. pub cfg_mods: bool, } +struct TokenCursor { + frame: TokenCursorFrame, + stack: Vec<TokenCursorFrame>, +} + +struct TokenCursorFrame { + delim: token::DelimToken, + span: Span, + open_delim: bool, + tree_cursor: tokenstream::Cursor, + close_delim: bool, +} + +impl TokenCursorFrame { + fn new(sp: Span, delimited: &Delimited) -> Self { + TokenCursorFrame { + delim: delimited.delim, + span: sp, + open_delim: delimited.delim == token::NoDelim, + tree_cursor: delimited.stream().into_trees(), + close_delim: delimited.delim == token::NoDelim, + } + } +} + +impl TokenCursor { + fn next(&mut self) -> TokenAndSpan { + loop { + let tree = if !self.frame.open_delim { + self.frame.open_delim = true; + Delimited { delim: self.frame.delim, tts: TokenStream::empty().into() } + .open_tt(self.frame.span) + } else if let Some(tree) = self.frame.tree_cursor.next() { + tree + } else if !self.frame.close_delim { + self.frame.close_delim = true; + Delimited { delim: self.frame.delim, tts: TokenStream::empty().into() } + .close_tt(self.frame.span) + } else if let Some(frame) = self.stack.pop() { + self.frame = frame; + continue + } else { + return TokenAndSpan { tok: token::Eof, sp: syntax_pos::DUMMY_SP } + }; + + match tree { + TokenTree::Token(sp, tok) => return TokenAndSpan { tok: tok, sp: sp }, + TokenTree::Delimited(sp, ref delimited) => { + let frame = TokenCursorFrame::new(sp, delimited); + self.stack.push(mem::replace(&mut self.frame, frame)); + } + } + } + } + + fn next_desugared(&mut self) -> TokenAndSpan { + let (sp, name) = match self.next() { + TokenAndSpan { sp, tok: token::DocComment(name) } => (sp, name), + tok @ _ => return tok, + }; + + let stripped = strip_doc_comment_decoration(&name.as_str()); + + // Searches for the occurrences of `"#*` and returns the minimum number of `#`s + // required to wrap the text. + let mut num_of_hashes = 0; + let mut count = 0; + for ch in stripped.chars() { + count = match ch { + '"' => 1, + '#' if count > 0 => count + 1, + _ => 0, + }; + num_of_hashes = cmp::max(num_of_hashes, count); + } + + let body = TokenTree::Delimited(sp, Delimited { + delim: token::Bracket, + tts: [TokenTree::Token(sp, token::Ident(ast::Ident::from_str("doc"))), + TokenTree::Token(sp, token::Eq), + TokenTree::Token(sp, token::Literal( + token::StrRaw(Symbol::intern(&stripped), num_of_hashes), None))] + .iter().cloned().collect::<TokenStream>().into(), + }); + + self.stack.push(mem::replace(&mut self.frame, TokenCursorFrame::new(sp, &Delimited { + delim: token::NoDelim, + tts: if doc_comment_style(&name.as_str()) == AttrStyle::Inner { + [TokenTree::Token(sp, token::Pound), TokenTree::Token(sp, token::Not), body] + .iter().cloned().collect::<TokenStream>().into() + } else { + [TokenTree::Token(sp, token::Pound), body] + .iter().cloned().collect::<TokenStream>().into() + }, + }))); + + self.next() + } +} + #[derive(PartialEq, Eq, Clone)] pub enum TokenType { Token(token::Token), @@ -309,14 +409,10 @@ impl From<P<Expr>> for LhsExpr { impl<'a> Parser<'a> { pub fn new(sess: &'a ParseSess, - tokens: Vec<TokenTree>, + tokens: TokenStream, directory: Option<Directory>, desugar_doc_comments: bool) -> Self { - let tt = TokenTree::Delimited(syntax_pos::DUMMY_SP, Rc::new(Delimited { - delim: token::NoDelim, - tts: tokens, - })); let mut parser = Parser { sess: sess, token: token::Underscore, @@ -328,7 +424,13 @@ impl<'a> Parser<'a> { directory: Directory { path: PathBuf::new(), ownership: DirectoryOwnership::Owned }, root_module_name: None, expected_tokens: Vec::new(), - tts: if tt.len() > 0 { vec![(tt, 0)] } else { Vec::new() }, + token_cursor: TokenCursor { + frame: TokenCursorFrame::new(syntax_pos::DUMMY_SP, &Delimited { + delim: token::NoDelim, + tts: tokens.into(), + }), + stack: Vec::new(), + }, desugar_doc_comments: desugar_doc_comments, cfg_mods: true, }; @@ -346,29 +448,14 @@ impl<'a> Parser<'a> { } fn next_tok(&mut self) -> TokenAndSpan { - loop { - let tok = if let Some((tts, i)) = self.tts.pop() { - let tt = tts.get_tt(i); - if i + 1 < tts.len() { - self.tts.push((tts, i + 1)); - } - if let TokenTree::Token(sp, tok) = tt { - TokenAndSpan { tok: tok, sp: sp } - } else { - self.tts.push((tt, 0)); - continue - } - } else { - TokenAndSpan { tok: token::Eof, sp: self.span } - }; - - match tok.tok { - token::DocComment(name) if self.desugar_doc_comments => { - self.tts.push((TokenTree::Token(tok.sp, token::DocComment(name)), 0)); - } - _ => return tok, - } + let mut next = match self.desugar_doc_comments { + true => self.token_cursor.next_desugared(), + false => self.token_cursor.next(), + }; + if next.sp == syntax_pos::DUMMY_SP { + next.sp = self.prev_span; } + next } /// Convert a token to a string using self's reader @@ -972,19 +1059,16 @@ impl<'a> Parser<'a> { F: FnOnce(&token::Token) -> R, { if dist == 0 { - return f(&self.token); - } - let mut tok = token::Eof; - if let Some(&(ref tts, mut i)) = self.tts.last() { - i += dist - 1; - if i < tts.len() { - tok = match tts.get_tt(i) { - TokenTree::Token(_, tok) => tok, - TokenTree::Delimited(_, delimited) => token::OpenDelim(delimited.delim), - }; - } + return f(&self.token) } - f(&tok) + + f(&match self.token_cursor.frame.tree_cursor.look_ahead(dist - 1) { + Some(tree) => match tree { + TokenTree::Token(_, tok) => tok, + TokenTree::Delimited(_, delimited) => token::OpenDelim(delimited.delim), + }, + None => token::CloseDelim(self.token_cursor.frame.delim), + }) } pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> { self.sess.span_diagnostic.struct_span_fatal(self.span, m) @@ -2022,10 +2106,10 @@ impl<'a> Parser<'a> { }) } - fn expect_delimited_token_tree(&mut self) -> PResult<'a, (token::DelimToken, Vec<TokenTree>)> { + fn expect_delimited_token_tree(&mut self) -> PResult<'a, (token::DelimToken, ThinTokenStream)> { match self.token { token::OpenDelim(delim) => self.parse_token_tree().map(|tree| match tree { - TokenTree::Delimited(_, delimited) => (delim, delimited.tts.clone()), + TokenTree::Delimited(_, delimited) => (delim, delimited.stream().into()), _ => unreachable!(), }), _ => Err(self.fatal("expected open delimiter")), @@ -2569,10 +2653,14 @@ impl<'a> Parser<'a> { pub fn parse_token_tree(&mut self) -> PResult<'a, TokenTree> { match self.token { token::OpenDelim(..) => { - let tt = self.tts.pop().unwrap().0; - self.span = tt.span(); + let frame = mem::replace(&mut self.token_cursor.frame, + self.token_cursor.stack.pop().unwrap()); + self.span = frame.span; self.bump(); - return Ok(tt); + return Ok(TokenTree::Delimited(frame.span, Delimited { + delim: frame.delim, + tts: frame.tree_cursor.original_stream().into(), + })); }, token::CloseDelim(_) | token::Eof => unreachable!(), _ => Ok(TokenTree::Token(self.span, self.bump_and_get())), |
