diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 3e85565beb6d..495ad176542c 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -18,8 +18,7 @@ use errors::DiagnosticBuilder; use ext::expand::{self, Invocation, Expansion}; use ext::hygiene::Mark; use fold::{self, Folder}; -use parse; -use parse::parser::{self, Parser}; +use parse::{self, parser}; use parse::token; use parse::token::{InternedString, str_to_ident}; use ptr::P; @@ -188,146 +187,6 @@ impl AttrProcMacro for F } } -pub struct TokResult<'a> { - pub parser: Parser<'a>, - pub span: Span, -} - -impl<'a> TokResult<'a> { - // There is quite a lot of overlap here with ParserAnyMacro in ext/tt/macro_rules.rs - // We could probably share more code. - // FIXME(#36641) Unify TokResult and ParserAnyMacro. - fn ensure_complete_parse(&mut self, allow_semi: bool) { - let macro_span = &self.span; - self.parser.ensure_complete_parse(allow_semi, |parser| { - let token_str = parser.this_token_to_string(); - let msg = format!("macro expansion ignores token `{}` and any following", token_str); - let span = parser.span; - parser.diagnostic() - .struct_span_err(span, &msg) - .span_note(*macro_span, "caused by the macro expansion here") - .emit(); - }); - } -} - -impl<'a> MacResult for TokResult<'a> { - fn make_items(mut self: Box) -> Option>> { - if self.parser.sess.span_diagnostic.has_errors() { - return Some(SmallVector::zero()); - } - - let mut items = SmallVector::zero(); - loop { - match self.parser.parse_item() { - Ok(Some(item)) => items.push(item), - Ok(None) => { - self.ensure_complete_parse(false); - return Some(items); - } - Err(mut e) => { - e.emit(); - return Some(SmallVector::zero()); - } - } - } - } - - fn make_impl_items(mut self: Box) -> Option> { - let mut items = SmallVector::zero(); - loop { - if self.parser.token == token::Eof { - break; - } - match self.parser.parse_impl_item() { - Ok(item) => items.push(item), - Err(mut e) => { - e.emit(); - return Some(SmallVector::zero()); - } - } - } - self.ensure_complete_parse(false); - Some(items) - } - - fn make_trait_items(mut self: Box) -> Option> { - let mut items = SmallVector::zero(); - loop { - if self.parser.token == token::Eof { - break; - } - match self.parser.parse_trait_item() { - Ok(item) => items.push(item), - Err(mut e) => { - e.emit(); - return Some(SmallVector::zero()); - } - } - } - self.ensure_complete_parse(false); - Some(items) - } - - fn make_expr(mut self: Box) -> Option> { - match self.parser.parse_expr() { - Ok(e) => { - self.ensure_complete_parse(true); - Some(e) - } - Err(mut e) => { - e.emit(); - Some(DummyResult::raw_expr(self.span)) - } - } - } - - fn make_pat(mut self: Box) -> Option> { - match self.parser.parse_pat() { - Ok(e) => { - self.ensure_complete_parse(false); - Some(e) - } - Err(mut e) => { - e.emit(); - Some(P(DummyResult::raw_pat(self.span))) - } - } - } - - fn make_stmts(mut self: Box) -> Option> { - let mut stmts = SmallVector::zero(); - loop { - if self.parser.token == token::Eof { - break; - } - match self.parser.parse_full_stmt(false) { - Ok(Some(stmt)) => stmts.push(stmt), - Ok(None) => { /* continue */ } - Err(mut e) => { - e.emit(); - return Some(SmallVector::zero()); - } - } - } - self.ensure_complete_parse(false); - Some(stmts) - } - - fn make_ty(mut self: Box) -> Option> { - match self.parser.parse_ty() { - Ok(e) => { - self.ensure_complete_parse(false); - Some(e) - } - Err(mut e) => { - e.emit(); - Some(DummyResult::raw_ty(self.span)) - } - } - } -} - /// Represents a thing that maps token trees to Macro Results pub trait TTMacroExpander { fn expand<'cx>(&self, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index d6874f60cde7..0d4e3ebdd205 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -325,14 +325,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let item_toks = TokenStream::from_tts(tts_for_item(&item, &self.cx.parse_sess)); let tok_result = mac.expand(self.cx, attr.span, attr_toks, item_toks); - let parser = self.cx.new_parser_from_tts(&tok_result.to_tts()); - let result = Box::new(TokResult { parser: parser, span: attr.span }); - - kind.make_from(result).unwrap_or_else(|| { - let msg = format!("macro could not be expanded into {} position", kind.name()); - self.cx.span_err(attr.span, &msg); - kind.dummy(attr.span) - }) + self.parse_expansion(tok_result, kind, attr.span) } _ => unreachable!(), } @@ -429,14 +422,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }, }); - - let tok_result = expandfun.expand(self.cx, - span, - TokenStream::from_tts(marked_tts)); - let parser = self.cx.new_parser_from_tts(&tok_result.to_tts()); - let result = Box::new(TokResult { parser: parser, span: span }); - // FIXME better span info. - kind.make_from(result).map(|i| i.fold_with(&mut ChangeSpan { span: span })) + let toks = TokenStream::from_tts(marked_tts); + let tok_result = expandfun.expand(self.cx, span, toks); + Some(self.parse_expansion(tok_result, kind, span)) } }; @@ -454,10 +442,31 @@ impl<'a, 'b> MacroExpander<'a, 'b> { expn_id: Some(self.cx.backtrace()), }) } + + fn parse_expansion(&mut self, toks: TokenStream, kind: ExpansionKind, span: Span) -> Expansion { + let mut parser = self.cx.new_parser_from_tts(&toks.to_tts()); + let expansion = match parser.parse_expansion(kind, false) { + Ok(expansion) => expansion, + Err(mut err) => { + err.emit(); + return kind.dummy(span); + } + }; + parser.ensure_complete_parse(kind == ExpansionKind::Expr, |parser| { + let msg = format!("macro expansion ignores token `{}` and any following", + parser.this_token_to_string()); + parser.diagnostic().struct_span_err(parser.span, &msg) + .span_note(span, "caused by the macro expansion here") + .emit(); + }); + // FIXME better span info + expansion.fold_with(&mut ChangeSpan { span: span }) + } } impl<'a> Parser<'a> { - pub fn parse_expansion(&mut self, kind: ExpansionKind) -> PResult<'a, Expansion> { + pub fn parse_expansion(&mut self, kind: ExpansionKind, macro_legacy_warnings: bool) + -> PResult<'a, Expansion> { Ok(match kind { ExpansionKind::Items => { let mut items = SmallVector::zero(); @@ -483,7 +492,7 @@ impl<'a> Parser<'a> { ExpansionKind::Stmts => { let mut stmts = SmallVector::zero(); while self.token != token::Eof { - if let Some(stmt) = self.parse_full_stmt(true)? { + if let Some(stmt) = self.parse_full_stmt(macro_legacy_warnings)? { stmts.push(stmt); } } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 8c95e7d31f79..e78eeb8f7a4f 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -63,7 +63,7 @@ impl<'a> ParserAnyMacro<'a> { } pub fn make(mut self: Box>, kind: ExpansionKind) -> Expansion { - let expansion = panictry!(self.parser.parse_expansion(kind)); + let expansion = panictry!(self.parser.parse_expansion(kind, true)); self.ensure_complete_parse(kind == ExpansionKind::Expr, kind.name()); expansion }