99// except according to those terms.
1010
1111use ast:: { Block , Crate , Ident , Mac_ , PatKind } ;
12- use ast:: { MacStmtStyle , StmtKind , ItemKind } ;
12+ use ast:: { Name , MacStmtStyle , StmtKind , ItemKind } ;
1313use ast;
1414use ext:: hygiene:: Mark ;
1515use ext:: placeholders:: { placeholder, PlaceholderExpander } ;
@@ -21,9 +21,9 @@ use ext::base::*;
2121use feature_gate:: { self , Features } ;
2222use fold;
2323use fold:: * ;
24- use parse:: { ParseSess , lexer} ;
24+ use parse:: { ParseSess , PResult , lexer} ;
2525use parse:: parser:: Parser ;
26- use parse:: token:: { intern, keywords} ;
26+ use parse:: token:: { self , intern, keywords} ;
2727use print:: pprust;
2828use ptr:: P ;
2929use tokenstream:: { TokenTree , TokenStream } ;
@@ -38,12 +38,12 @@ macro_rules! expansions {
3838 ( $( $kind: ident: $ty: ty [ $( $vec: ident, $ty_elt: ty) * ] , $kind_name: expr, . $make: ident,
3939 $( . $fold: ident) * $( lift . $fold_elt: ident) * ,
4040 $( . $visit: ident) * $( lift . $visit_elt: ident) * ; ) * ) => {
41- #[ derive( Copy , Clone ) ]
41+ #[ derive( Copy , Clone , PartialEq , Eq ) ]
4242 pub enum ExpansionKind { OptExpr , $( $kind, ) * }
4343 pub enum Expansion { OptExpr ( Option <P <ast:: Expr >>) , $( $kind( $ty) , ) * }
4444
4545 impl ExpansionKind {
46- fn name( self ) -> & ' static str {
46+ pub fn name( self ) -> & ' static str {
4747 match self {
4848 ExpansionKind :: OptExpr => "expression" ,
4949 $( ExpansionKind :: $kind => $kind_name, ) *
@@ -106,6 +106,12 @@ macro_rules! expansions {
106106 self . expand( Expansion :: $kind( SmallVector :: one( node) ) ) . $make( )
107107 } ) * ) *
108108 }
109+
110+ impl <' a> MacResult for :: ext:: tt:: macro_rules:: ParserAnyMacro <' a> {
111+ $( fn $make( self : Box <:: ext:: tt:: macro_rules:: ParserAnyMacro <' a>>) -> Option <$ty> {
112+ Some ( self . make( ExpansionKind :: $kind) . $make( ) )
113+ } ) *
114+ }
109115 }
110116}
111117
@@ -293,10 +299,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
293299 } ;
294300
295301 attr:: mark_used ( & attr) ;
302+ let name = intern ( & attr. name ( ) ) ;
296303 self . cx . bt_push ( ExpnInfo {
297304 call_site : attr. span ,
298305 callee : NameAndSpan {
299- format : MacroAttribute ( intern ( & attr . name ( ) ) ) ,
306+ format : MacroAttribute ( name) ,
300307 span : Some ( attr. span ) ,
301308 allow_internal_unstable : false ,
302309 }
@@ -319,14 +326,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
319326 let item_toks = TokenStream :: from_tts ( tts_for_item ( & item, & self . cx . parse_sess ) ) ;
320327
321328 let tok_result = mac. expand ( self . cx , attr. span , attr_toks, item_toks) ;
322- let parser = self . cx . new_parser_from_tts ( & tok_result. to_tts ( ) ) ;
323- let result = Box :: new ( TokResult { parser : parser, span : attr. span } ) ;
324-
325- kind. make_from ( result) . unwrap_or_else ( || {
326- let msg = format ! ( "macro could not be expanded into {} position" , kind. name( ) ) ;
327- self . cx . span_err ( attr. span , & msg) ;
328- kind. dummy ( attr. span )
329- } )
329+ self . parse_expansion ( tok_result, kind, name, attr. span )
330330 }
331331 _ => unreachable ! ( ) ,
332332 }
@@ -423,14 +423,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
423423 } ,
424424 } ) ;
425425
426-
427- let tok_result = expandfun. expand ( self . cx ,
428- span,
429- TokenStream :: from_tts ( marked_tts) ) ;
430- let parser = self . cx . new_parser_from_tts ( & tok_result. to_tts ( ) ) ;
431- let result = Box :: new ( TokResult { parser : parser, span : span } ) ;
432- // FIXME better span info.
433- kind. make_from ( result) . map ( |i| i. fold_with ( & mut ChangeSpan { span : span } ) )
426+ let toks = TokenStream :: from_tts ( marked_tts) ;
427+ let tok_result = expandfun. expand ( self . cx , span, toks) ;
428+ Some ( self . parse_expansion ( tok_result, kind, extname, span) )
434429 }
435430 } ;
436431
@@ -448,6 +443,75 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
448443 expn_id : Some ( self . cx . backtrace ( ) ) ,
449444 } )
450445 }
446+
447+ fn parse_expansion ( & mut self , toks : TokenStream , kind : ExpansionKind , name : Name , span : Span )
448+ -> Expansion {
449+ let mut parser = self . cx . new_parser_from_tts ( & toks. to_tts ( ) ) ;
450+ let expansion = match parser. parse_expansion ( kind, false ) {
451+ Ok ( expansion) => expansion,
452+ Err ( mut err) => {
453+ err. emit ( ) ;
454+ return kind. dummy ( span) ;
455+ }
456+ } ;
457+ parser. ensure_complete_parse ( name, kind. name ( ) , span) ;
458+ // FIXME better span info
459+ expansion. fold_with ( & mut ChangeSpan { span : span } )
460+ }
461+ }
462+
463+ impl < ' a > Parser < ' a > {
464+ pub fn parse_expansion ( & mut self , kind : ExpansionKind , macro_legacy_warnings : bool )
465+ -> PResult < ' a , Expansion > {
466+ Ok ( match kind {
467+ ExpansionKind :: Items => {
468+ let mut items = SmallVector :: zero ( ) ;
469+ while let Some ( item) = self . parse_item ( ) ? {
470+ items. push ( item) ;
471+ }
472+ Expansion :: Items ( items)
473+ }
474+ ExpansionKind :: TraitItems => {
475+ let mut items = SmallVector :: zero ( ) ;
476+ while self . token != token:: Eof {
477+ items. push ( self . parse_trait_item ( ) ?) ;
478+ }
479+ Expansion :: TraitItems ( items)
480+ }
481+ ExpansionKind :: ImplItems => {
482+ let mut items = SmallVector :: zero ( ) ;
483+ while self . token != token:: Eof {
484+ items. push ( self . parse_impl_item ( ) ?) ;
485+ }
486+ Expansion :: ImplItems ( items)
487+ }
488+ ExpansionKind :: Stmts => {
489+ let mut stmts = SmallVector :: zero ( ) ;
490+ while self . token != token:: Eof {
491+ if let Some ( stmt) = self . parse_full_stmt ( macro_legacy_warnings) ? {
492+ stmts. push ( stmt) ;
493+ }
494+ }
495+ Expansion :: Stmts ( stmts)
496+ }
497+ ExpansionKind :: Expr => Expansion :: Expr ( self . parse_expr ( ) ?) ,
498+ ExpansionKind :: OptExpr => Expansion :: OptExpr ( Some ( self . parse_expr ( ) ?) ) ,
499+ ExpansionKind :: Ty => Expansion :: Ty ( self . parse_ty ( ) ?) ,
500+ ExpansionKind :: Pat => Expansion :: Pat ( self . parse_pat ( ) ?) ,
501+ } )
502+ }
503+
504+ pub fn ensure_complete_parse ( & mut self , macro_name : ast:: Name , kind_name : & str , span : Span ) {
505+ if self . token != token:: Eof {
506+ let msg = format ! ( "macro expansion ignores token `{}` and any following" ,
507+ self . this_token_to_string( ) ) ;
508+ let mut err = self . diagnostic ( ) . struct_span_err ( self . span , & msg) ;
509+ let msg = format ! ( "caused by the macro expansion here; the usage \
510+ of `{}!` is likely invalid in {} context",
511+ macro_name, kind_name) ;
512+ err. span_note ( span, & msg) . emit ( ) ;
513+ }
514+ }
451515}
452516
453517struct InvocationCollector < ' a , ' b : ' a > {
0 commit comments